楔子
上一篇文章(https://blog.youkuaiyun.com/liulun/article/details/110953968)中,
我们讲了Electron+Vite的开发环境,并成功的加载了本地Vue3项目的页面
这一节我们讲如何编译打包项目
使用electron-builder打包electron应用,
需要经过如下几步:
1:把静态资源html,css,js,img等编译好,放到指定的目录
2:把主进程代码编译好,放到指定目录
3:制作一个package.json指定入口文件为主进程文件,并放置到指定目录
4:调用electron-builder内置的API完成打包工作
编译渲染进程资源
首先要通过编码的方式,调用Vite的API来编译Vue项目,代码如下:
async buildRender () {
let options = {
root: process.cwd(),
enableEsbuild: true,
minify: false,
outDir: path.join(process.cwd(), "release/bundled"),
alias: {
"/@/": path.resolve(__dirname, "./src"),
},
optimizeDeps: {
exclude: ['process']
}
};
await vite.build(options);
let htmlPath = path.join(this.bundledDir, "index.html")
let html = fs.readFileSync(htmlPath, { encoding: "utf8" })
html = html.replace("<head>", `<head><script>${this.getEnvScript()};</script>`)
fs.writeFileSync(htmlPath, html)
},
其中options的alias和optimizeDeps属性,你用不到的话可以拿掉。
outDir属性是输出目录,在上一篇文章中我们讲了目录结构,这里就是指定Vite编译完成后把编译结果放到哪个目录下(release/bundled)
接下来,我们修改了输出目录下的index.html文件,在它的head头中插入了一段js脚本
这段脚本的代码为:
let env = require("./release.env.js")
getEnvScript () {
let script = `process.env={...process.env,...${JSON.stringify(env)}};`
script += `process.env.RES_DIR = require("path").join(require("path").dirname(process.execPath),"resources/resource/release")`
return script
},
它就是为生产环境的渲染进程设置环境变量的
读环境变量的文件是:release.env.js,与上一篇讲的dev.env.js是对应的。
除了在release.env.js文件中设置的环境变量的值以外,
还包含RES_DIR这个值,这个值指向应用程序的资源目录(resource\release),
我们可以把一些不希望被打包到asar中的资源放置到这个目录下
注意:这一节讲到的环境变量并不包含WEB_PORT这个变量
因为在生产环境没有启本地http服务,所以不需要这个变量。
编译主进程资源
因为渲染进程Vite工具的背后是esbuild,所以编译主进程资源时,
我们也就直接用esbuild了
buildMain () {
let outfile = path.join(process.cwd(), "release/bundled/entry.js");
let entryFilePath = path.join(process.cwd(), "src/main/app.ts");
esbuild.buildSync({
entryPoints: [entryFilePath],
outfile,
minify: false,
bundle: true,
platform: "node",
sourcemap: false,
external: ["electron"],
});
let js = `${this.getEnvScript()}${os.EOL}${fs.readFileSync(outfile)}`;
fs.writeFileSync(outfile, js);
},
首先指定了入口文件和输出文件路径
然后交给esbuild编译,
这里有两个参数需要注意:
external: ["electron"]和platform: "node"
指定了这两个参数后esbuild就不会尝试编译node内置的库或electron内置的库了
最后,我们也把环境变量添加到了输出文件的首部
getEnvScript方法与编译渲染进程用到的方法一致。
准备package.json
接下来我们根据项目现有的package.json精简后生成了一个新的package.json文件,
也放在了release/bundled/目录下:
preparePackageJson () {
let pkgJsonPath = path.join(process.cwd(), "package.json");
let localPkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
let electronConfig = localPkgJson.devDependencies.electron.replace("^", "");
localPkgJson.main = "entry.js";
delete localPkgJson.scripts
delete localPkgJson.devDependencies
localPkgJson.devDependencies = { electron: electronConfig }
fs.writeFileSync(
path.join(path.join(process.cwd(), "release/bundled"), "package.json"),
JSON.stringify(localPkgJson)
);
fs.mkdirSync(path.join(path.join(process.cwd(), "release/bundled"), "node_modules"));
},
首先关注的是:
现有工程的package.json内的scripts和devDependencies配置节
对于生产环境来说是毫无意义的,所以我们直接删掉
但是!devDependencies配置节下的electron配置项却是有用的
还得给它加回来(哈!)
不但要追加回来,还要把electron版本号前面的"^"去掉
这样打包才不至于出错,这是electron-builder的一个BUG
https://github.com/electron-userland/electron-builder/issues/4157
处理完package.json后,把它保存到release/bundled目录下
生成安装包
接下去就是通过编程的方式创建了electron-builder的配置
然后调用electron-builder的api生成安装包
buildInstaller () {
let options = {
config: {
directories: {
output: path.join(process.cwd(), "release"),
app: path.join(process.cwd(), "release/bundled"),
},
files: ["**"],
extends: null,
productName: "******",
appId: "com.******",
asar: true,
extraResources: "./resource/release",
win: {
icon: "../resource/unrelease/icon.ico",
target: [
{
target: "nsis",
arch: ["ia32"],
},
]
},
mac: {
icon: "../resource/unrelease/icon.icns",
},
nsis: {
oneClick: true,
perMachine: true,
allowElevation: true,
allowToChangeInstallationDirectory: false,
include: path.join(process.cwd(), "script/installer.nsh"),
createDesktopShortcut: true,
createStartMenuShortcut: true,
shortcutName: "HikLink",
installerIcon: "../resource/unrelease/icon.ico",
uninstallerIcon: "../resource/unrelease/icon.ico",
installerHeader: "../resource/unrelease/icon.ico",
installerHeaderIcon: "../resource/unrelease/icon.ico",
installerSidebar: "../resource/unrelease/sidebar.bmp",
},
publish: [{ provider: "generic", url: "" }]
},
project: process.cwd(),
}
return builder.build(options);
},
其中几个值得注意的配置项为:
directories.output是编译后安装包的输出目录
directories.app是待编译的资源的目录(就是我们前面主进程资源、渲染进程资源和package.json放置的目录)
至此Vite+Electron的开发环境和生产环境都构建完成了