7

electron-builder

 3 years ago
source link: https://blog.rxliuli.com/p/63f0a26fdd3743668b11410a10625c1b/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

基本项目搭建 中,我们已经能够启动一个 electron 应用程序了(开发环境),现在来看如何将之打包为二进制程序便于分发给最终用户。

渲染层打包

直接使用 cra 的打包工具即可,没什么大不了的,但确实存在一些注意事项

  • 因为 electron 在生产环境会从文件系统中加载静态资源,所以打包出来的静态资源必须支持相对路径,下面是常见的两个设置。

主进程打包

electron-builder 打包需要以下几个步骤

更新 package.json 的一些配置

  1. 使用 package.json 中的 build 字段作为配置项,参考: https://www.electron.build/
  2. electron-builder 使用 main 字段作为启动脚本文件
  3. electron-builder 要求必须使用固定的版本号,意味着 electron 依赖需要指定为 "electron": "10.2.0"

下面是一个基本的配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
"main": "dist/main.js",
"scripts": {
// 一个非常基本的打包脚本
"pkg": "electron-builder"
},
"devDependencies": {
"electron": "10.2.0",
"electron-builder": "^22.9.1",
// electron 主进程实际上是 nodejs 环境,所以为了更好的开发体验,安装 nodejs 的类型定义
"@types/node": "^12.19.12"
},
"build": {
// 程序的唯一标识符
"appId": "com.rxliuli.electron_example",
// 打包出来的 exe 名字
"productName": "electron 示例应用",
// 打包的目录
"directories": {
"output": "release"
},
"win": {
// 打包目标,参考: https://www.electron.build/
"target": ["nsis"]
}
}
}

复制静态资源

现在,我们需要打包静态资源并复制到主进程模块里面

  1. cd apps/renderer 目录
  2. yarn build 打包静态资源
  3. 将静态资源复制到 build/dist 目录下

修改主进程入口文件 main.ts

还需要修改 src/main.ts 代码,主要修改 BrowserWindow 对象载入的 url 地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { app, BrowserWindow } from "electron";
import path = require("path");
import { URL } from "url";

async function createMainWindow() {
// 创建新的 electron 窗口
const mainWindow = new BrowserWindow();
// 载入生产环境的 url
await mainWindow.loadURL(
new URL(path.join(__dirname, "./build/index.html")).href
);
}

// 其他代码...

注意,这个 url 路径是相对于打包后的 dist/main.js 而言的,因为最终打包的程序运行时的相对路径也是这样。

打包主进程的 exe 程序

因为 electron-builder 需要下载基本的 electron 程序,所以请提前设置好透明代理,如果不知道它是什么,参考: 透明网关Proxifier

  1. 使用 yarn compile 编译 ts 代码
  2. 使用 yarn pkg 打包 electron 应用

现在,我们应该可以在 apps/main/release/win-unpacked 下看到 exe 程序,双击它即可看到之前在开发环境的首页了。

参考: https://github.com/rxliuli/electron_example/tree/85d398fc2c6ba6c918ad9641dbb5d8bae2d4216b/apps/main

虽然打包已经实现,但确实还存在一些问题

  • 打包脚本仍然不是一键的
  • 不能兼容开发、生产环境

下面我们来解决这两个问题

实现一键打包二进制程序

使用 gulp 复制渲染层的静态资源

1、添加 gulp 相关依赖 yarn add -D gulp ts-node @types/gulp fs-extra @types/fs-extra

  • gulp @types/gulp: gulp 核心依赖
  • ts-node: 使用 ts 编写 gulp 脚本必须的依赖
  • fs-extra @types/fs-extra: fs 的扩展增强,使用 Promise 包装异步 api

2、添加 gulp 脚本文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import { copy, remove } from "fs-extra";
import * as path from "path";

async function copyByMap(copyMap: [string, string][]) {
await Promise.all(
copyMap.map(async ([src, destDir]) => {
const srcPath = path.resolve(__dirname, src);
const destPath = path.resolve(__dirname, destDir, path.basename(srcPath));
await copy(srcPath, destPath);
})
);
}

/**
* 清理最终生成目录
*/
export async function clean() {
await remove(path.resolve(__dirname, "dist"));
await remove(path.resolve(__dirname, "release"));
}

/**
* 复制一些资源到 dist 目录中
*/
export async function copyStatic() {
await copyByMap([["../renderer/build", "dist/"]]);
}

3、添加 npm script

注: lerna 的好处之一就是可以运行其它模块的 npm script。

1
2
3
4
5
6
7
8
{
"scripts": {
// 打包渲染层的静态资源
"build:web": "lerna run --scope renderer build",
// 打包渲染层的静态资源之后复制然后使用 electron-builder 打包 exe 程序
"pkg": "gulp clean && yarn compile && yarn build:web && gulp copyStatic && electron-builder"
}
}

4、修改 tsconfig.json

此时在 apps/main 模块根目录下也有 ts 文件了,所以 tsc 翻译代码会将它们也包含进去,但实际上不需要。

1
2
3
{
"include": ["src"]
}

现在,我们可以使用一个命令打包 exe 程序了。

参考: https://github.com/rxliuli/electron_example/blob/3dacff5dc0/apps/main/package.json

使用环境变量来兼容开发、生产环境

解决方案简单来说就一句话:使用环境变量指定开发环境的 URL。
这里使用 env-cmd 来跨平台写入环境变量(不使用 dotenv 的原因在于自定义环境使用起来有点麻烦,不像 env-cmd 那么直观),而另一个 cross-env 并未提供管理环境变量的解决方案。下面说一下使用 env-cmd 的步骤

  1. 安装依赖 yarn add -D env-cmd

  2. 添加配置文件 .env-cmdrc.json
    基本上是一个键值映射文件,键是环境,值对象是环境变量

    1
    2
    3
    4
    5
    {
    "dev": {
    "ELECTRON_START_URL": "http://localhost:3000/"
    }
    }
  3. dev:electron 命令之前设定环境变量 env-cmd -e dev electron ./dist/main.js

  4. 修改 src/main.ts 读取环境变量

    1
    2
    3
    4
    await mainWindow.loadURL(
    process.env.ELECTRON_START_URL ||
    path.join(__dirname, "./build/index.html")
    );

    现在,像 基本项目搭建更新 package.json 添加几个 npm script 说的那样启动开发环境就会显示开发环境的页面,打包后显示的则是打包后的静态资源。

参考: https://github.com/rxliuli/electron_example/blob/f8b4f94435/apps/main/.env-cmdrc.json

虽然 electron-builder 已经足够好用了,但它仍然不能解决 electron 项目工程上的问题,所以这里结合了 lerna/gulp/env-cmd 打包。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK