使用Electron构建React+Webpack桌面应用的方法


Posted in Javascript onDecember 15, 2017

前言

Electron可以使用HTML、CSS、JavaScript构建跨平台桌面应用,可是在使用到React和Webpack时,会遇到一些配置问题,本文将针对React+Webpack下的Electron配置提供一个通用的解决方案。

环境配置

"babel-core": "^6.26.0",
  "babel-loader": "^7.1.2",
  "babel-plugin-transform-class-properties": "^6.24.1",
  "babel-plugin-transform-object-rest-spread": "^6.26.0",
  "babel-preset-env": "^1.6.1",
  "babel-preset-react": "^6.24.1",
  "css-loader": "^0.28.7",
  "electron": "^1.7.9",
  "electron-packager": "^10.1.0",
  "extract-text-webpack-plugin": "^3.0.2",
  "node-sass": "^4.7.2",
  "react": "^16.2.0",
  "react-dom": "^16.2.0",
  "sass-loader": "^6.0.6",
  "style-loader": "^0.19.1",
  "webpack": "^3.10.0",
  "webpack-dev-server": "^2.9.7"

配置webpack.config.js

由于使用默认的Webpack打包,会生成一个很大的bundle文件,在桌面端比较影响性能,而调试的时候却需要较快地生成bundle,可是又需要使用sourcemap来定位bug,所以我们使用一个函数来切换各种环境:

module.exports = (env)=>{
 ******
 const isProduction = env==='production';
 ******
 devtool: isProduction ? 'source-map':'inline-source-map',

而我们在package.json文件里,编写以下命令:

"build:dev": "webpack",
"build:prod":"webpack -p --env production",

就可以较好的切换环境。

以下是全部webpack.config.js:

const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = (env)=>{
 const isProduction = env==='production';
 const CSSExtract = new ExtractTextPlugin('styles.css');
 console.log('env='+env);
 return {
  entry:'./src/app.js',
  target: 'electron-renderer',
  output:{
   path:path.join(__dirname, 'public','dist'),
   filename:'bundle.js'
  },
  module:{
   rules:[{
    loader: 'babel-loader',
    test: /\.js(x)?$/,
    exclude: /node_modules/
   }, {
    test: /\.s?css$/,
    use:CSSExtract.extract({
     use:[
      {
       loader:'css-loader',
       options:{
        sourceMap:true
       }
      },
      {
       loader:'sass-loader',
       options:{
        sourceMap:true
       }
      }
     ]
    })
   }]
  },
  plugins:[
   CSSExtract
  ],
  devtool: isProduction ? 'source-map':'inline-source-map',
  devServer:{
   contentBase: path.join(__dirname, 'public'),
   historyApiFallback:true,
   publicPath:'/dist/'
  }
 };
}

注意:target: 'electron-renderer',让我们的App在调试时只能在Electron下作用。

React

本次编写的是一个简单的显示时间的App,React 模块如下:

import React from 'react';
class Time extends React.Component{
 state = {
  time:''
 }
 getTime(){
  let date = new Date();
  let Year = date.getFullYear();
  let Month = date.getMonth();
  let Day = date.getDate();
  let Hour = date.getHours();
  let Minute = date.getMinutes();
  let Seconds = date.getSeconds();
  let time = Year+'年'+Month+'月'+Day+'日'+Hour+':'+Minute+':'+Seconds;
  return time;
 }
 componentDidMount(){
  setInterval(()=>{
   this.setState(()=>{
    return {
     time:this.getTime()
    }
   });
  },1000);
 }
 render(){
  let timetext = this.state.time;
  return (
   <div>
    <h1>{timetext}</h1>
   </div>
  );
 }
}
export default Time;

Electron

本次的App不涉及复杂的Electron API,仅仅作为展示的容器:

const electron = require('electron');
const {app,BrowserWindow} = electron;
let mainWindow = electron;
app.on('ready',()=>{
 mainWindow = new BrowserWindow({});
 mainWindow.loadURL(`file://${__dirname}/public/index.html`);
});

index.html

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>React-Webpack-Electron</title>
 <link rel="stylesheet" type="text/css" href="./dist/styles.css" rel="external nofollow" >
</head>
<body>
 <div id="app"></div>
 <script src="./dist/bundle.js"></script>
</body>
</html>

我们将webpack打包的js和css加载到html中。

调试

yarn run build:prod

首先我们用webpack打包文件,在dist/下生成bundle.js和style.css

yarn run electron

开始调试:

使用Electron构建React+Webpack桌面应用的方法

构建App

我们在package.json文件里添加如下命令:

"packager": "electron-packager . --platform=darwin --electron-version=1.7.9 --overwrite"

意思为构建Mac桌面应用,并覆盖之前我们使用该命令构建的文件。

等待一会儿会在目录下看到构建好的文件夹,里面便是我们的桌面应用。

使用Electron构建React+Webpack桌面应用的方法

而在这时我们打开应用,会发现其在调试中的导航栏菜单均已消失,只有一个退出选项,这是因为我们并没有设置应用的菜单栏项目,Electron在构建App时会舍去调试的各种菜单。

改进

大家应该注意到按照之前的方法,我们在调试时每修改一次就要重用webpack打包,当然也可以使用webpack-dev-server来监测改变。只不过这样我们需要对项目进行调整:

在index.js文件里修改loadURL为:

mainWindow.loadURL(`http://localhost:8080/index.html`);

再运行:

yarn run electron

因为此时我们是检测的webpack-dev-server下的文件,此时我们在项目中做的修改就能实时在electron中看到了。

若调试和测试完成,只需要修改loadURL为:

mainWindow.loadURL(`file://${__dirname}/public/index.html`);

即可进行下一步构建操作。

!注意,在构建最终应用前应该注意此时的web文件是否在webpack-dev-server下运作,若是则应该使用webpack生成静态打包文件。

本文项目文件地址:https://github.com/Voyager-One/react-webpack-electron

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery中 noConflict() 方法使用
Apr 25 Javascript
Enter转换为Tab的小例子(兼容IE,Firefox)
Nov 14 Javascript
javascript动态修改Li节点值的方法
Jan 20 Javascript
实例讲解javascript注册事件处理函数
Jan 09 Javascript
jQuery模仿单选按钮选中效果
Jun 24 Javascript
AngularJs自定义服务之实现签名和加密
Aug 02 Javascript
js HTML5多媒体影音播放
Oct 17 Javascript
Bootstrap如何激活导航状态
Mar 22 Javascript
vue.js高德地图实现热点图代码实例
Apr 18 Javascript
vue单页应用的内存泄露定位和修复问题小结
Aug 02 Javascript
详解vuex数据传输的两种方式及this.$store undefined的解决办法
Aug 26 Javascript
vue基本使用--refs获取组件或元素的实例
Nov 07 Javascript
vue给input file绑定函数获取当前上传的对象完美实现方法
Dec 15 #Javascript
微信小程序左右滑动的实现代码
Dec 15 #Javascript
浅析JavaScript中的特殊数据类型
Dec 15 #Javascript
微信小程序ajax实现请求服务器数据及模版遍历数据功能示例
Dec 15 #Javascript
微信小程序使用request网络请求操作实例
Dec 15 #Javascript
VS Code转换大小写、修改选中文字或代码颜色的方法
Dec 15 #Javascript
Angular中管道操作符(|)的使用方法
Dec 15 #Javascript
You might like
PHP的拦截器实例分析
2014/11/03 PHP
PHP基于MySQL数据库实现对象持久层的方法
2015/06/17 PHP
yii插入数据库防并发的简单代码
2017/05/27 PHP
jquery移动listbox的值原理及代码
2013/05/03 Javascript
5秒后跳转效果(setInterval/SetTimeOut)
2013/05/03 Javascript
Shell脚本实现Linux系统和进程资源监控
2015/03/05 Javascript
javascript Array 数组常用方法
2015/04/05 Javascript
详细分析JavaScript变量类型
2015/07/08 Javascript
jQuery基于ajax实现带动画效果无刷新柱状图投票代码
2015/08/10 Javascript
localResizeIMG先压缩后使用ajax无刷新上传(移动端)
2015/08/11 Javascript
轻松学习jQuery插件EasyUI EasyUI表单验证
2015/12/01 Javascript
jquery实现全选和全不选功能效果的实现代码【推荐】
2016/05/05 Javascript
全面了解JavaScript的数据类型转换
2016/07/01 Javascript
Vue computed计算属性的使用方法
2017/07/14 Javascript
小程序实现短信登录倒计时
2019/07/12 Javascript
原生Vue 实现右键菜单组件功能
2019/12/16 Javascript
Bootstrap实现前端登录页面带验证码功能完整示例
2020/03/26 Javascript
详解Node.js使用token进行认证的简单示例
2020/05/25 Javascript
JS+css3实现幻灯片轮播图
2020/08/14 Javascript
numpy使用fromstring创建矩阵的实例
2018/06/15 Python
Python实现Event回调机制的方法
2019/02/13 Python
Python Django简单实现session登录注销过程详解
2019/08/06 Python
ProBikeKit美国官网:自行车套件,跑步和铁人三项套件
2016/10/13 全球购物
美国知名奢侈美容品牌零售商:Cos Bar
2017/04/21 全球购物
Linux如何压缩可执行文件
2014/03/27 面试题
实体的生命周期
2013/08/31 面试题
司机岗位职责
2013/11/15 职场文书
见习报告的格式
2014/11/04 职场文书
质量负责人岗位职责
2015/02/15 职场文书
学校运动会简讯
2015/07/20 职场文书
企业年会祝酒词
2015/08/11 职场文书
2016年推广普通话宣传周活动总结
2016/04/06 职场文书
Python基础之元类详解
2021/04/29 Python
浅析MongoDB之安全认证
2021/06/26 MongoDB
剖析后OpLog订阅MongoDB的数据变更就没那么难了
2022/02/24 MongoDB
服务器nginx权限被拒绝解决案例
2022/09/23 Servers