记录:electron-vue大佬博客
使用electron-builder库,先安装它。
1、cnpm i electron-builder -D
2、尝试使用npm run build打包react项目
注意事项一:
注:electron-is-dev 需要变成生产依赖
3、根据electron-builder配置文档去实施
4、配置分基础配置,和不同操作系统配置,对象会覆盖基础配置。
5、增加基础描述,为了使打包的信息详细。
6、增加scripts // pack是出来一个安装完毕的文件,而dist 是打包出来的安装包
"pack": "electron-builder --dir",
"dist": "electron-builder",
7、package.json 内置钩子 preXXX和postXXX
表示在运行pack时,先执行prepack命名,再执行pack,最后执行postpack
此时pack肯定是失败的,因为还缺少很多配置项,所以
注意事项二:extends: null
运行npm run pack 打包命令后,出现报错。
检测是拉取[email protected]相关资源失败,
解决方案: 回退至[email protected]
但是发现npm install [email protected] 也报错
解决方案:cnpm去安装[email protected]
成功!
如果想使用electron@7.+的版本,可以自行去release中寻找,查找合适的资源点,然后即可pack。
npm i --registry=https://registry.npm.taobao.org
可以手动去下载 release 的任意版本,并放置Cache 目录下,如
C:\Users\lenovo\AppData\Local\electron\Cache\electron-v7.1.2-win32-x64.zip
Electron:运行npm run build构建环境失败解决方案
软件生产环境的依赖需要被明确,不能放入开发环境依赖中。
打包成功后,运行exe执行文件没有页面。
原因:create-react-app 生成的文件是在build文件夹下。但electron认为整个项目打包出的文件是在pack过程中指定出需要使用的一些文件。即我们缺失了支持以及服务electron相关的文件。
解决方案: 手动添加要打包哪些文件,在files对象中。
注:glob打包路径 **/*
,2个星号即匹配所有文件夹和子文件,1个星号匹配当前路径下的所有文件
"build": {
"appId": "cloudDoc",
"productName": "七牛云文档",
"copyright": "Copyright © 2019 ${author}",
"files": [
"main.js", // 主进程
"build/**/*", // create-react-app 渲染进程1
"settings/**/*", // 渲染进程2
"./src/menuTemplate.js", // 菜单项
"./src/AppWindow.js", // 进程封装 类
"./src/utils/QiniuManager.js", // 七牛服务 类
"./src/utils/mainHelper.js" // 主进程工具
],
"extends": null
},
然后继续打包一次,又发生了错误。
3、错误三:
react渲染进程的资源定位失败
是因为build出来的都是绝对路径,需要改成相对路径。
注:react自身打包出来是绝对路径是为了方便资源的代理,但是对于桌面端场景,相对路径更合适。
解决方案: 将create-react-app打包路径改成相对路径。 修改package.json,然后重新打包react项目,并打包electron
1、首先我们electron打包出的项目,其运行需要chromeV8引擎的支持。
2、主要占内存的文件是app.asar(130mb)和七牛云文档.exe(95mb)
3、为了刨根问底,app.asar到底含有什么文件,我们可以使用官方解压缩工具
1、未配置files的app.asar解压出来,是整个项目的文件目录。
2、配置过files后,解压出来是以main.js为入口,携带node_modules,package.json,以及一系列files包含的文件。
3、最后打包出来的可执行文件只有一个
它的功能就是加载resrouces/app.asar文件中的内容(从package.json中的main字段获取main.js,进行一系列加载)
"build": {
"appId": "cloudDoc",
"productName": "七牛云文档",
"copyright": "Copyright © 2019 ${author}",
"files": [ //... 若干需药打包的文件]
"extends": null, // 扩展入口
"directories": {
"buildResources": "assets" // 静态资源路径
},
"mac": { // mac系统
"category": "public.app-category.productivity", // 安装在mac'效率'分类下
"artifactName": "${productName}-${version}-${arch}.${ext}", // 安装包的名称
},
"dmg": { // mac安装软件dmg格式
"background": "assets/adddmg.png",
"icon": "assets/icon.icns",
"iconSize": 100,
"contents": [
{
"x": 380,
"y": 280,
"type": "link",
"path": "/Applications"
},
{
"x": 110,
"y": 280,
"type": "file",
}
],
"window": {
"width": 500,
"height": 500
}
},
"win": { // window系统
"target": [
"msi","nsis"
],
"icon": "assets/icon.ico",
"artifactName": "${productName}-Web-Setup-${version}.${ext}",
"publisherName": "Killer"
},
"nsis": {
"allowToChangeInstallationDirectory": true, // 改变目录
"oneClick": false, // 是否一键安装
"perMachine": false
}
}
1、create-react-app在build时,已将生产依赖dependencies,全部打包到了[chunk].js中,所以app.asar中的node_modules,是没必要全部被打包到应用中的。
2、故在进行electron打包时,将dependencies不相关模块,全部移到devDependencies中
3、打包完成后显示压缩至11mb。
1、因为main.js不受webpack的控制,所以我们需要尝试用webpack去压缩它,并尝试优化files需要依赖的文件(不那么码农式的一个个复制,像这样)
上述的文件都被单独打包在 build下(webpack 打包完主进程文件),删除上述文件后,运行打包会报下述错误:
是因为 electron-builder 打包 会默认以根目录的 main.js 为入口。
我们需要改变配置项
"build": {
// ...
"extraMetadata": {
"main": "./build/main.js"
},
webpack 针对 electron 的打包优化有特殊的配置
const path = require('path')
module.exports = {
mode: "production",
target: 'electron-main',
entry: {
main: path.resolve(__dirname, 'main.js')
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
node: {
__dirname: false
}
}
2、新建webpack.config.js文件
2019年12月9日10:57:27,耗时,30分钟,打包啥的都没问题,但是运行exe失败了。
1、npm run build 和 npm run pack 这2个是create-react-app和electron分别的打包命令,但是devdenp和denp均设置不同。张轩大大是直接多打包运行,共用一个package.json,我暂不清楚是否有问题。
思考得出: create-react-app 的build 用了webpack,并将模块依赖打包入了[chunk].js,所以,开发和生产依赖的标识,并不会影响webpack打包该包。所以,仅需适配electron即可
2、webpack.config.js打包主进程main.js后,尝试使用extraMetadata:{main: “main.js”},引入调整后,运行exe,加载失败,尚不清楚原因。
自动更新:是指远程客户端的版本与服务端版本不一致,进行更新的过程。
1、需要将本地上传好的文件,pack到某处,并进行一次release,这个过程就是publish。
2、完成github部署后,即可进行release发布。
3、electron-builder 在pack时,为我们提供了release过程,简单配置即可。
// package.json
"scripts:{
// ...
"release": "electron-builder",
"prerelease": "npm run build"
}
4、根据文档指示github需要去生成GH_TOKEN
并使用cross-env 添加参数至release命令中。
npm run release 发现代码已上传
1、npm install electron-updater --save-dev
在main.js中
app的ready事件内,
2、然后运行npm run pack 打包测试下是否正常。
注意:使用updater后electron依赖必须明确版本而不能采用向上兼容^号。
3、然后尝试运行exe,报错,error事件已经捕获,是因为我们需要重新release带有更新功能的项目,才能进行更新。
4、重新release当前带有更新模块的版本。
release成功后,会在resources文件夹下生成.yml,用于指向更新地址。
5、release结束后,本地打开exe查看,弹出弹窗。
但是没有一个程序员会每次打包并release到github上来测试更新的代码。
6、在开发环境下可以手动模拟release创建的.yml文件
7、之后直接npm run dev 以开发者模式运行即可,开发模式可以检测到更新,我这里不截图了,自己也云里雾里的,我就粘贴代码了。
app.on('ready', () => {
if (isDev) {
autoUpdater.updateConfigPath = path.join(__dirname, 'dev-app-update.yml');
}
/**
* autoUpdater
* checkForUpdatesAndNotify 仅在生成模式才能运行
* 若是开发模式
* 可以兼容使用 checkForUpdates
*/
// 取消自动下载
autoUpdater.autoDownload = false; // 仅生成模式
autoUpdater.checkForUpdates(); // 兼容开发和生产模式
// 检测异常
autoUpdater.on('error', (error) => {
dialog.showErrorBox(
'检测更新异常',
error === null ? 'unknown' : '有错误提示,但是我不知道怎么打印...'
);
});
// 检测版本中...
autoUpdater.on('checking-for-update', () => {
console.log('checking for update ...');
});
// 如果检测到新版本
autoUpdater.on('update-available', () => {
dialog.showMessageBox({
type: 'info',
title: '应用有新的版本',
message: '发现新版本,是否现在更新?',
button: ['是', '否']
}, (buttonIndex) => {
if (buttonIndex === 0) {
autoUpdater.downloadUpdate();
}
});
});
// 当前是新版本
autoUpdater.on('update-not-available', () => {
dialog.showMessageBox({
title: '没有新版本',
message: '当前已经是最新版本'
});
});
// github拉取最新版本中...
autoUpdater.on('download-progress', (progressObj) => {
const { bytesPerSecond, progress, percent, total, transferred } = progressObj;
console.log('bytesPerSecond: ' + bytesPerSecond + ',progress: ' + progress + ',percent: ' + percent + ',transferred: ' + transferred + '/total: ' + total);
});
// 拉取新版本完毕
autoUpdater.on('update-downloaded', () => {
dialog.showMessageBox({
title: '安装更新',
message: '更新下载完毕,应用将重启并进行安装'
}, () => {
setImmediate(() => autoUpdater.quitAndInstall())
});
});
// ...逻辑代码