使用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 相关文章推荐
Mootools 1.2教程 排序类和方法简介
Sep 15 Javascript
js转义字符介绍
Nov 05 Javascript
javascript实现复选框选中属性
Mar 25 Javascript
jQuery EasyUI 菜单与按钮之创建简单的菜单和链接按钮
Nov 18 Javascript
学习JavaScript设计模式(代理模式)
Dec 03 Javascript
利用jQuery对无序列表排序的简单方法
Oct 16 Javascript
巧用Javascript的逻辑运算符
Dec 02 Javascript
vue-router 学习快速入门
Mar 01 Javascript
js制作简单的音乐播放器的示例代码
Aug 28 Javascript
React组件refs的使用详解
Feb 09 Javascript
微信小程序用户授权、位置授权及获取微信绑定手机号
Jul 18 Javascript
JavaScript实现省份城市的三级联动
Feb 11 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实现 data url的图片生成与保存
2016/12/04 PHP
PHP cookie与session会话基本用法实例分析
2019/11/18 PHP
Dom 结点创建 基础知识
2011/10/01 Javascript
基于编写jQuery的无缝滚动插件
2014/08/02 Javascript
浅谈JavaScript 浏览器对象
2016/06/03 Javascript
Bootstrap三种表单布局的使用方法
2016/06/21 Javascript
EasyUI折叠表格层次显示detailview详解及实例
2016/12/28 Javascript
JavaScript中捕获与冒泡详解及实例
2017/02/03 Javascript
jQuery为DOM动态追加事件的方法
2017/02/16 Javascript
jQuery在header中设置请求信息的方法
2017/03/06 Javascript
angularJs中json数据转换与本地存储的实例
2018/10/08 Javascript
JavaScript时间与时间戳的转换操作实例分析
2018/12/07 Javascript
Vue实现根据hash高亮选项卡
2019/05/27 Javascript
JavaScript生成一个不重复的ID的方法示例
2019/09/16 Javascript
JS内置对象和Math对象知识点详解
2020/04/03 Javascript
基于VSCode调试网页JavaScript代码过程详解
2020/07/20 Javascript
Python中用memcached来减少数据库查询次数的教程
2015/04/07 Python
玩转python爬虫之爬取糗事百科段子
2016/02/17 Python
Python的Twisted框架上手前所必须了解的异步编程思想
2016/05/25 Python
python面向对象_详谈类的继承与方法的重载
2017/06/07 Python
pygame实现弹力球及其变速效果
2017/07/03 Python
python实现媒体播放器功能
2018/02/11 Python
python获取网页中所有图片并筛选指定分辨率的方法
2018/03/31 Python
python处理数据,存进hive表的方法
2018/07/04 Python
最新pycharm安装教程
2020/11/18 Python
解决python3.6用cx_Oracle库连接Oracle的问题
2020/12/07 Python
python 实现socket服务端并发的四种方式
2020/12/14 Python
巴西食品补充剂在线零售商:Músculos na Web
2017/08/07 全球购物
幼儿园中班教师寄语
2014/04/03 职场文书
文明寄语大全
2014/04/11 职场文书
抗洪救灾先进集体事迹材料
2014/05/26 职场文书
学校督导评估方案
2014/06/10 职场文书
爱心捐款感谢信
2015/01/20 职场文书
建筑工程材料员岗位职责
2015/04/11 职场文书
企业战略合作意向书
2015/05/08 职场文书
python tkinter实现定时关机
2021/04/21 Python