【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了

先上一张效果图:
【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第1张图片

1. 何为Electron?

Electron官网地址:Electron官网

一句话来总结Electron,就是官网上写的:使用Web技术JavaScript、HTML和CSS构建跨平台的桌面应用程序

目前使用Electron来构建的热门应用有:VS Code、Facebook Messenger、Figma、Microsoft Teams…

Electron的目标及优势就是:如果你可以建一个网站,你就可以建一个桌面应用程序。Electron是一个使用JavaScript、HTML、CSS等Web技术创建原生程序的框架,开发者只需要专注于使用web技术进行业务开发,产品落地为桌面程序的问题由Electron来解决。

Electron的特性:

  • Web技术,Electron的实现基于Chromium和Node.js。

所谓Chromium是Google为发展自家的浏览器Google Chrome(以下简称Chrome)而开启的计划,所以Chromium相当于Chrome的工程版或称实验版(尽管Chrome自身也有β版阶段),新功能会率先在Chromium上实现,待验证后才会应用在Chrome上,故Chrome的功能会相对落后、稳定。Chromium的更新速度很快,每隔数小时即有新的开发版本发布,而且可以免安装,下载zip封装版后解压缩即可使用(Windows下也有安装版)。Chrome虽然理论上也可以免安装,但Google仅提供安装版.

  • 开源,Electron是一个由OpenIS基金会和一个活跃的贡献者社区管理的开源项目
  • 跨平台。Electron兼容Mac、Windows和Linux,可以构建出三个平台的应用程序

Electron 创建的应用使用网页作为其 GUI ,因此可以将其当成由 JavaScript 控制的迷你精简版Chromium 浏览器。也可以将 Electron 当成 node.js 变体,只不过它更专注于桌面应用而非 Web 服务器。

在 Electron 中, 把package.json中设定的main.js脚本的所在进程称为主进程。这个进程中运行的脚本也可通过创建网页这种方式来展现其 GUI。 因为 Electron 是通过 Chromium 来显示页面,所以 Chromium 自带的多进程架构也一同被利用。这样每个页面都运行着一个独立的进程,它们被统称为渲染进程

通常来说,浏览器中的网页会被限制在沙盒环境中运行并且不允许访问系统原生资源。但是由于 Eelectron 用户可在页面中调用 Node.js API,所以可以和底层操作系统直接交互。

优点

对前端开发者友好,方便快捷的开发桌面应用,跨平台,社区活跃,API丰富,上手快

缺点

性能肯定比不上原生的桌面应用,发布的包体积比较大。

2.React集成Electron实践

2.1 快速创建一个React的Demo

  1. 使用create-react-app快速生成一个react的Demo,react2electron为项目名称
npx create-react-app react2electron
  1. 运行npm start,浏览器中看到如下界面代表搭建React初始项目成功!:
    【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第2张图片
    接下来,我们的目标就是把在浏览器展示的这个Demo页面,使用Electron集成为桌面程序.

2.2 在React的Demo项目中引入Electron

修改npm的config里Electron的镜像源,防止下载失败。具体百度.

2.2.1 执行Electron的安装命令

npm install electron --save-dev

【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第3张图片

2.2.2 在项目根目录下新增main.js文件

main.js是React集成Electron的关键文件.

main.js文件内容如下所示:

基本和Electron的官方Demo里的一致,直接粘去用即可。

// 引入electron并创建一个Browserwindow
const {app, BrowserWindow} = require('electron')
const path = require('path')
const url = require('url')


// 获取在 package.json 中的命令脚本传入的参数,来判断是开发还是生产环境
const mode = process.argv[2];


// 保持window对象的全局引用,避免JavaScript对象被垃圾回收时,窗口被自动关闭.
let mainWindow


function createWindow() {
    //创建浏览器窗口,宽高自定义
    mainWindow = new BrowserWindow({width: 800, height: 600})
    if (mode === 'dev') {
        // 加载应用----适用于 react 项目
        mainWindow.loadURL('http://localhost:3000/');
    } else {
        // 加载应用-----react项目打包后的路径
        mainWindow.loadURL(url.format({
            pathname: path.join(__dirname, './build/index.html'),
            protocol: 'file:',
            slashes: true
        }))
    }


    // 打开开发者工具,默认不打开
    // mainWindow.webContents.openDevTools()
    // 关闭window时触发下列事件.
    mainWindow.on('closed', function () {
        mainWindow = null
    })
}


// 当 Electron 完成初始化并准备创建浏览器窗口时调用此方法
app.on('ready', createWindow)
// 所有窗口关闭时退出应用.
app.on('window-all-closed', function () {
    // macOS中除非用户按下 `Cmd + Q` 显式退出,否则应用与菜单栏始终处于活动状态.
    if (process.platform !== 'darwin') {
        app.quit()
    }
})
app.on('activate', function () {
    // macOS中点击Dock图标时没有已打开的其余应用窗口时,则通常在应用中重建一个窗口
    if (mainWindow === null) {
        createWindow()
    }
})
// 你可以在这个脚本中续写或者使用require引入独立的js文件.

2.2.2 修改项目的package.json

主要做了如下几个改动:

  • 新增homepage属性,值为“./”,表明打包后项目放在哪里

默认情况下,homepage 是 http://localhost:3000. build 后,所有资源文件路径都是 /static,而 Electron 调用的入口是 file :协议,/static 就会定位到根目录去,所以找不到静态文件。在 package.json 文件中添加 homepage 字段并设置为"."后,静态文件的路径就变成了相对路径,就能正确地找到了

  • 新增main属性,值为"main.js",表明打包策略采用的是main.js里的规则
  • 在scripts里新增脚本启动命令

electron-start对应启动的是开发环境下的项目

electron对应启动的是线上环境下的项目

用两个命令来区分比较好调试~
【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第4张图片

{
  "name": "react2electron",
  "version": "1.0.0",
  "private": true,
  "homepage": "./",
  "main": "main.js",
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^13.1.1",
    "@testing-library/user-event": "^13.5.0",
    "react": "^18.0.0",
    "react-dom": "^18.0.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "electron-start": "electron . dev",
    "electron": "electron .",
    "package": "electron-packager . react2electron --win=x32 --out ./hello --electron-version=18.1.0"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "electron": "^18.1.0",
    "electron-packager": "^15.5.1"
  }
}

2.2.3 执行npm start,开发环境下启动react项目

npm start

再开一个会话执行npm electron-start, 启动开发环境下的Electron

npm run electron-start

这样在网页里调试React的项目,可以同步在Electron里查看效果,Electron可以做到热调试,当修改代码时,会同步在Electron进行实时更新。

出现如下桌面程序,就代表Electron启动成功啦~
【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第5张图片

2.2.4 执行npm run build,打包我们的react项目为线上版本

npm run build

打包后的文件长这个样:
【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第6张图片
接下来,我们就可以用打包后的react来测试Electron:

执行npm run electron

npm run electron

如果也能弹出桌面应用,那证明线上版本也正常~

2.3 打包Electron为桌面执行文件

市面上主流的打包Electron有electron-packager和electron-builder两种。

经过调研,electron-builder功能更多,但是配置更复杂;而electron-packager较为轻量,但是也已满足我们的日常需求,且配置简单,因此本次打包采用electron-packager.

2.3.1 引入electron-packager

建议先去npm官网了解一下这个npm包:electron-packager

按照文档说明,electron-packager可以跨端打包Electron的项目。

在项目中引入该打包库的命令为:

npm install electron-packager --save-dev

【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第7张图片
官方推荐在项目路径下安装这个打包库,而不是全局进行安装~
【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第8张图片

2.3.2 electron-packager使用说明

使用electron-packager进行项目的打包有两种方式,这两种方式打包都挺慢的,需要耐心等待:

2.3.2.1 第一种是直接执行electron-packager .

electron-packager .


这种方式比较简单,electron-packager会自动帮我们完成剩下的工作:
【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第9张图片
翻译一下就是:

  • 使用当前的项目目录为要打包的目录
  • 根据项目的productName来生成打包后桌面程序的appname
  • 根据项目的version来生成打包后桌面程序的appVersion
  • 根据主机的型号和arch来生成桌面程序的型号和arch
  • 下载electron 1.4.15版本的darwin x64,并放在项目文件根目录的.elctron,这里的electron由项目下载的对应版本来决定
  • 生成macOS的桌面程序
  • 把生成的macOS从桌面程序放置在对应文件夹下

2.3.2.2 使用命令行来打包:

这种方式就需要我们在package.json文件的script里写脚本了:

"scripts": {
  "package": "electron-packager . react2electron --win=x32 --out ./hello --electron-version=18.1.0"
},

按照官方文档,脚本格式如下:

electron-packager   --platform= --arch= [optional flags...]
  • sourcedir:项目源文件所在路径(唯一的必须参数)

  • appname:项目名称(直接使用package.json文件中的name属性更方便)

  • platform:要构建哪个平台的应用(Windows、Mac 还是 Linux)

  • arch:决定了使用 x86 (ia32)还是 x64(x64),还是两个架构都用

  • optional options:可选选项

然后执行npm run package即可:

npm run package

【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第10张图片 这是另一个版本:
【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第11张图片 对于我们没有写的内容,electron-packager会根据项目的package.json来进行填充。
如果还想有其他规则,在上列脚本后面继续跟着写就行了,

比如–overwrite表示写覆盖,如果不加这个,打包后文件的目录如果存在的话就会跳过打包:
【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第12张图片 --icon=./favicon.ico指明了icon路径

打包后的文件结构长这个样:
【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第13张图片
resources文件下就是我们的项目源码:
【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第14张图片

2.4 打包优化

有没有发现打包后源码文件很大?包含了所有文件,我们完全可以只打包前面我们生成的build下的线上代码呀,这里全给打包了…

解决方案是添加ignore参数:

"package": "electron-packager . react2electron --win --arch=x64 --out=release  --electron-version=18.1.0 --overwrite --ignore="(src*|.gitignore|.idea|README.md|node_modules)""

需要注意的是,main.js和package.json文件不能被ignore,不然打包会报错
【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第15张图片 此时打包就结束了,但是细心的同学应该发现了,我们打包后的文件里resource文件夹下是我们项目的源码,这要是被贼人拿了去(开个玩笑),岂不是会泄露源码?

Electron早就考虑到了这个问题,提供了一个npm包来进行自动加密,

因此我们需要使用加密来混淆一下源码。

2.5 加密源码

2.5.1 全局安装asar

npm install -g asar


接下来在生成的应用源码的上级文件夹下执行下面命令:

asar pack ./app app.asar


发现源码加密完成:
【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第16张图片
然后把上面的app文件夹删掉即可~

2.6 测试

运行react2electron.exe,正常启动~
【Electron+React入门Demo】用Web技术写桌面应用,这也太酷了_第17张图片

3. 源码

react2electron源码

你可能感兴趣的:(前端,React,Electron,JS,桌面应用,package)