使用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判断字符输入个数(数字英文长度记为1,中文记为2,超过长度自动截取)
Oct 15 Javascript
jquery教程ajax请求json数据示例
Jan 13 Javascript
js获取当前日期时间及其它操作汇总
Apr 17 Javascript
jQuery使用经验小技巧(推荐)
May 31 Javascript
jQuery插件FusionCharts绘制的3D环饼图效果示例【附demo源码】
Apr 02 jQuery
jQuery上传插件webupload使用方法
Aug 01 jQuery
jQuery初级教程之网站品牌列表效果
Aug 02 jQuery
Vue 递归多级菜单的实例代码
May 05 Javascript
记录vue做微信自定义分享的一些问题
Sep 12 Javascript
vue 实现模糊检索并根据其他字符的首字母顺序排列
Sep 19 Javascript
解决vue刷新页面以后丢失store的数据问题
Aug 11 Javascript
Webpack5正式发布,有哪些新特性
Oct 12 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 论坛采集程序 模拟登陆,抓取页面 实现代码
2009/07/09 PHP
php实现的一个很好用HTML解析器类可用于采集数据
2013/09/23 PHP
小谈php正则提取图片地址
2014/03/27 PHP
DEDECMS首页调用图片集里的多张图片
2015/06/05 PHP
Laravel使用Queue队列的技巧汇总
2019/09/02 PHP
数理公式,也可以这么唯美
2021/03/10 无线电
出现“不能执行已释放的Script代码”错误的原因及解决办法
2007/08/29 Javascript
JavaScript简单实现网页回到顶部功能
2013/11/12 Javascript
简单的js图片轮换代码(js图片轮播)
2014/05/06 Javascript
Flexigrid在IE下不显示数据的有效处理方法
2014/09/04 Javascript
JavaScript运动减速效果实例分析
2015/08/04 Javascript
在create-react-app中使用sass的方法示例
2018/10/01 Javascript
浅谈在Vue.js中如何实现时间转换指令
2019/01/06 Javascript
微信 jssdk 签名错误invalid signature的解决方法
2019/01/14 Javascript
微信小程序开发之转发分享功能
2019/10/22 Javascript
Vue实现 点击显示再点击隐藏效果(点击页面空白区域也隐藏效果)
2020/01/16 Javascript
[46:21]Liquid vs LGD 2018国际邀请赛淘汰赛BO3 第一场 8.23
2018/08/24 DOTA
python处理中文编码和判断编码示例
2014/02/26 Python
Python中import导入上一级目录模块及循环import问题的解决
2016/06/04 Python
python生成excel的实例代码
2017/11/08 Python
python八大排序算法速度实例对比
2017/12/06 Python
Python3.6连接Oracle数据库的方法详解
2018/05/18 Python
使用Python AIML搭建聊天机器人的方法示例
2018/07/09 Python
基于Python3.6+splinter实现自动抢火车票
2018/09/25 Python
Python matplotlib通过plt.scatter画空心圆标记出特定的点方法
2018/12/13 Python
python从list列表中选出一个数和其对应的坐标方法
2019/07/20 Python
Django框架 查询Extra功能实现解析
2019/09/04 Python
python实现XML解析的方法解析
2019/11/16 Python
Keras自定义IOU方式
2020/06/10 Python
Python基于staticmethod装饰器标示静态方法
2020/10/17 Python
python中Mako库实例用法
2020/12/31 Python
CSS3五个技巧给你的网站带来出色的效果
2009/04/02 HTML / CSS
丝芙兰香港官网:Sephora香港
2018/03/13 全球购物
学生个人的自我评价分享
2013/11/05 职场文书
体育教师自荐信范文
2013/12/16 职场文书
电脑饰品店的创业计划书
2014/01/21 职场文书