使用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 相关文章推荐
javascript contains和compareDocumentPosition 方法来确定是否HTML节点间的关系
Feb 04 Javascript
Array的push与unshift方法性能比较分析
Mar 05 Javascript
用javascript作一个通用向导说明
Aug 30 Javascript
一个通过script自定义属性传递配置参数的方法
Sep 15 Javascript
一起学写js Calender日历控件
Apr 14 Javascript
jQuery插件EasyUI获取当前Tab中iframe窗体对象的方法
Aug 05 Javascript
网页中的图片查看器viewjs使用方法
Jul 11 Javascript
jQuery Collapse1.1.0折叠插件简单使用
Aug 28 jQuery
js和jQuery以及easyui实现对下拉框的指定赋值方法
Jan 23 jQuery
微信小程序如何像vue一样在动态绑定类名
Apr 17 Javascript
layer的prompt弹出框,点击回车,触发确定事件的方法
Sep 06 Javascript
VUE table表格动态添加一列数据,新增的这些数据不可以编辑(v-model绑定的数据不能实时更新)
Apr 03 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
咖啡历史、消费和行业趋势
2021/03/03 咖啡文化
真正面向对象编程:PHP5.01发布
2006/10/09 PHP
基于php iconv函数的使用详解
2013/06/09 PHP
在Yii框架中使用PHP模板引擎Twig的例子
2014/06/13 PHP
详解WordPress中调用评论模板和循环输出评论的PHP函数
2016/01/05 PHP
JavaScript 滚轮事件使用说明
2010/03/07 Javascript
js href的用法
2010/05/13 Javascript
js获取或设置当前窗口url参数的小例子
2013/10/14 Javascript
JavaScript调试技巧之console.log()详解
2014/03/19 Javascript
jqeury-easyui-layout问题解决方法
2014/03/24 Javascript
用jquery的方法制作一个简单的导航栏
2014/06/23 Javascript
js和jquery中循环的退出和继续下一个循环
2014/09/03 Javascript
浅谈pc端rem字体设置的问题
2017/08/03 Javascript
vue编写简单的购物车功能
2021/01/08 Vue.js
基于vuex实现购物车功能
2021/01/10 Vue.js
python数据结构之二叉树的遍历实例
2014/04/29 Python
Python AES加密模块用法分析
2017/05/22 Python
linux中如何使用python3获取ip地址
2019/07/15 Python
Python django搭建layui提交表单,表格,图标的实例
2019/11/18 Python
UGG美国官网:购买UGG雪地靴、拖鞋和鞋子
2017/12/31 全球购物
Omio俄罗斯:一次搜索公共汽车、火车和飞机的机票
2018/11/17 全球购物
巴西最大的珠宝连锁店:Vivara
2019/04/18 全球购物
LACOSTE波兰官网:Polo衫、服装和鞋类
2020/09/29 全球购物
RUIFIER官网:英国奢侈高级珠宝品牌
2020/06/12 全球购物
大专生工程监理求职信
2013/10/04 职场文书
办公室主任主任岗位责任制
2014/02/11 职场文书
运动会获奖感言
2014/02/11 职场文书
棉花姑娘教学反思
2014/02/15 职场文书
《争吵》教学反思
2014/02/15 职场文书
房产代理公证处委托书
2014/04/04 职场文书
青年文明号汇报材料
2014/12/23 职场文书
通知范文怎么写
2015/04/16 职场文书
表扬信范文
2015/05/04 职场文书
2015年学校图书室工作总结
2015/05/19 职场文书
趣味运动会广播稿
2015/08/19 职场文书
Mysql中where与on的区别及何时使用详析
2021/08/04 MySQL