Electron.js + React 实现跨平台方案

974 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Electron.js 是使用 JavaScript,HTML 和 CSS 构建跨平台的桌面应用程序。

Electron 压缩包下载

因为 electron 压缩包的服务器在国外,所以网速很慢而且不稳定,在下载之前把下载镜像的地址切换为淘宝的

npm config set ELECTRON_MIRROR https://npm.taobao.org/mirrors/electron/

Electron 打包 React 项目

1 安装 Electron

npm install -g electron
npm install -D electron
  • 这里使用的是全局安装 electron,原因是因为 electron 包比较大,而且运行 electron 这一操作是可复用的,所以我认为全局安装 electron 更加合适。

2 相关配置

  1. 在根目录添加 main.js 文件

    // Modules to control application life and create native browser window
    const {app, BrowserWindow} = require('electron');
    const path = require('path');
    const url = require('url');
    
    // Keep a global reference of the window object, if you don't, the window will
    // be closed automatically when the JavaScript object is garbage collected.
    let mainWindow;
    
    function createWindow () {
      // Create the browser window.
      mainWindow = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
          preload: path.join(__dirname, 'preload.js'),
        },
      });
    
      // 加载应用----适用于 react 项目
     mainWindow.loadURL('http://localhost:3000/');
    
      // 打开开发者工具,默认不打开
      // mainWindow.webContents.openDevTools()
    
      // Open the DevTools.
      // mainWindow.webContents.openDevTools()
    
      // Emitted when the window is closed.
      mainWindow.on('closed', function () {
        // Dereference the window object, usually you would store windows
        // in an array if your app supports multi windows, this is the time
        // when you should delete the corresponding element.
        mainWindow = null;
      });
    }
    
    // This method will be called when Electron has finished
    // initialization and is ready to create browser windows.
    // Some APIs can only be used after this event occurs.
    app.on('ready', createWindow);
    
    // Quit when all windows are closed.
    app.on('window-all-closed', function () {
      // On macOS it is common for applications and their menu bar
      // to stay active until the user quits explicitly with Cmd + Q
      if (process.platform !== 'darwin') app.quit();
    });
    
    app.on('activate', function () {
      // On macOS it's common to re-create a window in the app when the
      // dock icon is clicked and there are no other windows open.
      if (mainWindow === null) createWindow();
    });
    
    // In this file you can include the rest of your app's specific main process
    // code. You can also put them in separate files and require them here.
    
  2. 修改 package.json 配置

    • 将刚刚配置的 main.js 文件配置到 package.json"main": "main.js"

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

      "homepage": "."

    • 配置

      {
        "name": "client",
        "version": "0.1.0",
        "private": true,
        "main": "main.js",
        "homepage": ".",
        "author": {
          "name": "Samuel Liu"
        },
        "dependencies": {
          "antd": "^4.9.2",
          "electron": "^11.0.4",
          "electron-packager": "^15.2.0",
          "react": "^16.12.0",
          "react-dom": "^16.12.0",
          "react-router": "^5.2.0",
          "react-router-dom": "^5.2.0",
          "react-scripts": "^3.3.0"
        },
        "scripts": {
          "start": "react-scripts start",
          "build": "react-scripts build",
          "test": "react-scripts test --env=jsdom",
          "eject": "react-scripts eject",
          "electron-start": "electron .",
          "electron-build": "electron-packager ./build rui --win --out=release --arch=x64 --app-version=1.0.0 --electron-version=11.0.4"
        },
        "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": "^11.0.4"
        }
      }
      
      
  3. 在根目录添加preload.js文件

    // All of the Node.js APIs are available in the preload process.
    // It has the same sandbox as a Chrome extension.
    window.addEventListener('DOMContentLoaded', () => {
      const replaceText = (selector, text) => {
        const element = document.getElementById(selector);
        if (element) element.innerText = text;
      };
    
      for (const type of ['chrome', 'node', 'electron']) {
        replaceText(`${type}-version`, process.versions[type]);
      }
    });
    

3 启动 Electron

# 启动react项目
npm start
# 启动electron
npm run electron-start

注意:启动 electron 应用后,如果无法显示 index 页面,可能是你路由配置了 BrowserRouter 模式,请改成 HashRouter。Vue 项目出不来的话,很大可能是使用了 history 路由模式,改成 hash 路由模式就可以了。

4 打包

  • 注意:要修改跟目录下面的 main.js 文件

    // 加载应用----react 打包
    mainWindow.loadURL(url.format({
      pathname: path.join(__dirname, './build/index.html'),
      protocol: 'file:',
      slashes: true,
    }));
    // 加载应用----适用于 react 开发配置
    // mainWindow.loadURL('http://localhost:3000/');
    
  • 将你配置的 main.jspackage.jsonpreload.js,复制一份到 /public 静态文件中,不然打包后,还是会无法打开程序。 注意:修改 /public 中的 main.js pathname: path.join(__dirname, './index.html')

    // 加载应用----react 打包
    mainWindow.loadURL(url.format({
      pathname: path.join(__dirname, './index.html'),
      protocol: 'file:',
      slashes: true,
    }));
    // 加载应用----适用于 react 开发配置
    // mainWindow.loadURL('http://localhost:3000/');
    
  • 安装 electron-packager

    # 根目录下安装 electron-packager 包
    npm install electron-packager --save-dev
    # 安装 electron-packager 命令
    npm install electron-packager -g
    
  • electron-packager 命令介绍

    electron-packager <location of project> <name of project> <platform> <architecture> <electron version> <optional options>
    
    • location of project: 项目的本地地址,此处我这边是 ~/knownsec-fed
    • location of project: 项目名称,此处是 knownsec-fed
    • platform: 打包成的平台
    • architecture: 使用 x86 还是 x64 还是两个架构都用
    • electron version: electron 的版本
  • 配置package.json打包脚本

    "electron-build": "electron-packager ./build rui --platform=win32 --arch=x64 --out=./../out --ar --app-version=0.0.1 --electron-version=6.0.1",

  • 开始打包

    # 先编译出静态资源
    npm run build
    # 再编译 electron
    npm run electron-build
    

找到打包文件中 exe 文件,双击打开运行

5 asar压缩

"electron-build": "electron-packager ./build rui --platform=win32 --arch=x64 --out=./../out --app-version=0.0.1 --asar --electron-version=6.0.1",

6 使用 inno 来编译打包好的文件