使用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 相关文章推荐
utf-8编码引起js输出中文乱码的解决办法
Jun 23 Javascript
js和jquery中循环的退出和继续学习记录
Sep 06 Javascript
Javascript模拟加速运动与减速运动代码分享
Dec 11 Javascript
javascript弹出拖动窗口
Aug 11 Javascript
多种JQuery循环滚动文字图片效果代码
Jun 23 Javascript
jQuery Timelinr实现垂直水平时间轴插件(附源码下载)
Feb 16 Javascript
JS正则子匹配实例分析
Dec 22 Javascript
JS去除字符串中空格的方法
Feb 14 Javascript
微信小程序 页面跳转传值实现代码
Jul 27 Javascript
jQuery实现的粘性滚动导航栏效果实例【附源码下载】
Oct 19 jQuery
在小程序中使用腾讯视频插件播放教程视频的方法
Jul 10 Javascript
微信小程序实现卡片层叠滑动效果
Jun 21 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
SONY ICF-SW07收音机电路分析
2021/03/02 无线电
php使用curl检测网页是否被百度收录的示例分享
2014/01/31 PHP
学习php设计模式 php实现观察者模式(Observer)
2015/12/09 PHP
php投票系统之增加与删除投票(管理员篇)
2016/07/01 PHP
redirect_uri参数错误的解决方法(必看)
2017/02/16 PHP
关于 Laravel Redis 多个进程同时取队列问题详解
2017/12/25 PHP
setTimeout 不断吐食CPU的问题分析
2009/04/01 Javascript
兼容IE、FireFox、Chrome等浏览器的xml处理函数js代码
2011/11/30 Javascript
DOM和XMLHttpRequest对象的属性和方法整理
2012/01/04 Javascript
自定义jquery模态窗口插件无法在顶层窗口显示问题
2014/05/29 Javascript
js判断元素是否隐藏的方法
2014/06/09 Javascript
Javascript中this绑定的3种方法与比较
2016/10/13 Javascript
简单学习vue指令directive
2016/11/03 Javascript
JS简单实现数组去重的方法示例
2017/03/27 Javascript
JS模拟超市简易收银台小程序代码解析
2017/08/18 Javascript
使用淘宝镜像cnpm安装Vue.js的图文教程
2018/05/17 Javascript
js中自定义react数据验证组件实例详解
2018/10/19 Javascript
如何去除富文本中的html标签及vue、react、微信小程序中的过滤器
2018/11/21 Javascript
详解django模板与vue.js冲突问题
2019/07/07 Javascript
js实现视图和数据双向绑定的方法分析
2020/02/05 Javascript
JS+HTML实现自定义上传图片按钮并显示图片功能的方法分析
2020/02/12 Javascript
Vue列表循环从指定下标开始的多种解决方案
2020/04/08 Javascript
javascript设计模式 ? 享元模式原理与用法实例分析
2020/04/15 Javascript
js实现盒子滚动动画效果
2020/08/09 Javascript
VSCode 添加自定义注释的方法(附带红色警戒经典注释风格)
2020/08/27 Javascript
python自动发送邮件脚本
2018/06/20 Python
Numpy之将矩阵拉成向量的实例
2019/11/30 Python
html5 实现客户端验证上传文件的大小(简单实例)
2016/05/15 HTML / CSS
Dillard’s百货官网:Dillards.com
2018/05/26 全球购物
"引用"与指针的区别是什么
2016/09/07 面试题
英文版网络工程师求职信
2013/10/28 职场文书
最新奶茶店创业计划书范文
2014/02/08 职场文书
手机销售员岗位职责
2015/04/11 职场文书
幼儿园2016年圣诞活动总结
2016/03/31 职场文书
怎样写好工作计划
2019/04/10 职场文书
SpringCloud Alibaba项目实战之nacos-server服务搭建过程
2021/06/21 Java/Android