Electron + React + Ant Design 配置及打包

4,277 阅读4分钟

Electron + React + Ant Design 配置及打包

Step0 配置 NodeJS 环境

首先,安装好 Node.JS 及 npm,具体方法不在此赘述了,安装好之后再安装一个 cnpm,国内 npm 安装 React 和 Electron 的速度都很慢,甚至还有可能连接不上。

npm install -g cnpm --registry=https://registry.npm.taobao.org
# 以后就可以使用 cnpm 代替 npm 了,使用方法一样
npm config set registry https://registry.npm.taobao.org

Step1 安装 React

大多数时候可能我们会先安装 create-react-app,命令如下所示:

# Mac 下可能需要加 sudo
cnpm install -g create-react-app

不过这个方案官方并不推荐

官方推荐我们卸载掉全局的 create-react-app,并使用 npx 去创建项目,因为这个可以保证我们使用的 create-react-app 是最新的

npm uninstall -g create-react-app

使用 create-react-app 快速创建 React 应用

# 先进入想创建项目的目录,my-app 是应用的名称,可以自定义
npx create-react-app my-app

安装成功之后根据提示的命令可以启动 react 项目

cd my-app
npm start

注意:在 react 代码中如果想要使用 node 模块,需要在创建 window 的时候配置 contextIsolation: false,,并使用 window.require 引入模块,例如:const fs = window.require('fs');

Step2 安装 Electron

执行如下命令安装 Electron:

# Mac 下可能需要加 sudo
cnpm i electron -D

Step3 配置 Electron 的 main 程序

建议给 Electron 创建目录专门的一个目录,Electron 的代码都放在里面和前端代码隔离开,方便管理,我创建了一个 /main/index.js 作为 Electron 的 main 程序。

// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron');
const path = require('path');
const isDev = require('electron-is-dev');

// 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: {
      nodeIntegration: true,
      contextIsolation: false,
      preload: path.join(__dirname, 'preload.js'),
    }
  });

  mainWindow.loadURL(isDev ? 'http://localhost:3000' : `file://${__dirname}/../build/index.html`);

  // Open the DevTools.
  isDev && 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.

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]);
  }
});

另外,我们在 React 开发的时候都用到 webpack-dev-server,所以在开发的时候我们会用到 mainWindow.loadURL('http://localhost:3000');,而在生产环境的时候通常还是会使用打包好的产物,例如: mainWindow.loadURL('file://${__dirname}/build/index.html');,这样为了让代码能适应这样的场景所以就需要能判断当前是开发环境还是生产环境。

# 安装
cnpm install electron-is-dev -S
// 使用
const isDev = require('electron-is-dev');

最后配置一下package.json,在最外层属性中(通常在 version 字段后面)加入

"main": "./main/index.js",

在 scripts 下面加入

"dev": "electron ."

此时就可以依次使用以下命令启动项目了:

npm start
npm run dev

Step4 配置一键启动

每次都执行多个命令,而且还会自动打开浏览器,这其实是我们不期望的,我们期望的是一条命令,不打开浏览器自动依次去执行各个命令。为了实现这个功能,我们需要进行如下配置:

# 安装 concurrently 以同时执行多个命令
cnpm i concurrently -D
# 安装 wait-on 等待资源加载完成
cnpm i wait-on -D
# 安装 cross-env 可以使用环境变量
cnpm i cross-env -D

修改 scripts 下的 dev 字段:

"dev": "concurrently \" wait-on http://localhost:3000 && electron . \" \" cross-env BROWSER=none npm start \" "

使用 npm run dev就可以实现一键启动项目了。

Step5 安装 Ant Design

# 安装
cnpm install antd -S

至此,开发环境配置完毕,下面配置打包。

Step6 打包

打包使用的是 electron-builder 的方案,也是当前比较主流的方案,这是官方链接

GitHub - electron-userland/electron-builder: A complete solution to package and build a ready for distribution Electron app with “auto update” support out of the box

Introduction - electron-builder

# 安装
cnpm i electron-builder -D

修改 package.json 的配置

配置 homepage 使得 react 打包之后的 index.html 可以正常访问

"homepage": ".",

配置 scripts,添加:

pack 用于对 electron 进行打包,打包之前需要对 react 代码进行打包,所以用到了 pre 这个钩子,在执行 cnpm run pack的时候会先执行 prepack,pack:dir 用于打包绿色免安装的运行程序。

"pack": "electron-builder",
"prepack": "react-scripts build",
"pack:dir": "electron-builder --dir"

打包 windows 包的时候,electron-builder --dir 依赖 winCodeSign,而 electron-builder 依赖 winCodeSign 和 nsis。

winCodeSign 和 nsis 在国内的网络环境下都不好下载,可以尝试去 github 手动下载 Releases · electron-userland/electron-builder-binaries · GitHub

继续添加 build 相关配置:

"build": {
    "extends": null,
    "productName": "my-app",
    "copyright": "©2021 XXX, Inc.",
    "appId": "com.my-app.app",
    "directories": {
        "output": "build-electron"
    },
    "files": [
        "main/**/*",
        "build/**/*"
    ],
    "extraResources": [{
        "filter": ["./config.json", "./server-config.json"]
    }],
    "win": {
        "target": [
            {
                "target": "nsis",
                "arch": [
                    "ia32"
                ]
            }
        ]
    },
    "nsis": {
        "oneClick": false,
        "allowElevation": true,
        "allowToChangeInstallationDirectory": true,
        "installerIcon": "./public/favicon.ico",
        "uninstallerIcon": "./public/favicon.ico",
        "installerHeaderIcon": "./public/favicon.ico",
        "createDesktopShortcut": true,
        "createStartMenuShortcut": true,
        "shortcutName": "my-app"
    },
    "mac": {
        "category": "public.app-category.productivity"
    },
    "dmg": {
        "background": "./appdmg.png",
        "icon": "./icon.icns",
        "iconSize": 100,
        "contents": [
            {
                "x": 380,
                "y": 280,
                "type": "link",
                "path": "/Applications"
            },
            {
                "x": 110,
                "y": 280,
                "type": "file"
            }
        ],
        "window": {
            "width": 500,
            "height": 500
        }
    }
}
  • output 是打包之后的输出路径
  • files 是 react 和 electron 相关的代码路径
  • extraResources 是额外的需要打包到 resources 文件夹下的文件
  • win 是打包 Windows 包的配置信息
  • nsis 是 Windows 安装包的配置
  • mac 是打包 Mac 包的配置信息
  • dmg 是 Mac 安装包配置