electron应用打包与更新--思路与踩坑总结

803 阅读4分钟

前言

经过8个多月的开发,我的个人electron应用终于功能全部开发完成啦,下一步就是去发布、去上线、去运营...

在功能完成之后上线之前,首先要做的就是打包,让应用能够跑在不同平台

技术栈

前端:vue+vite+electron

后端:koa+mysql

打包

思路

打包大致分成了两种,一种是在package.json中定义build选项

{
    "build":{
            // 对应的配置项
    }
}

这种方式有局限性,它打出来的包是源代码,毫无安全性可言(虽然也做不到绝对安全,但防君子不妨小人)

所以我的选择是用编程接口来实现

大体就分成4步,或者说5步也行

image.png

init

此函数用来清空上一次打包留下来的文件夹,即builddist

rimraf.sync('对应的文件夹目录')

这里对应一个坑点,那就是,在打包的dist文件夹名称不变的情况下,最终生成的app.asar包是上一次的,但我找了官方文档一圈,也没找到有缓存相关的配置

我的解决方式是根据package.jsonversion字段来生成dist目录,并对其重写

// 读取根目录下的package.json
const json = resolvePkgJson();
// 根据旧版本生成新版本
const { version: pVersion } = json;
const nVersion = createVersion(pVersion)
// 将新版本写入package.json
writeFileSync()

buildLogo

这一步用来生成应用logo

image.png

主要借助了electron-icon-buildersharp,后者用来为前者提供一张1024*1024格式的基图

// 生成基图
sharp()
// 生成logo
createLogo()

这里稍微有点难的地方是electron-icon-builder这个包并没有提供默认的函数导出,他只支持从scripts传参数,需要在代码中进行模拟

// 模拟参数
process.argv.push('参数')
// 调用打包
import('包')

buildVite

这部分是对vue编写的代码做打包,本质上就是vite build

build({
    ...
})

稍微不同的是,我的应用需要基于html创建多窗口,vite默认是只打包index.html的,所以在打包结束后我得把对应的html文件拷贝一份

build().then(()=>{
    // 拷贝到指定目录
})

buildApkCode

这个是对主进程代码的打包,用的是rollup

rollupBuild({
    ...
})

这里的坑点是不能打包依赖,因为electron-build打包后会帮我们把node_modules中需要的依赖拷贝过去,自己打包不仅是多此一举,还会出现异常情况,就比如electron打包后就会报错(因为是事后总结,报错截图就不贴了,当时也没专门留存

所以在执行打包前需要将依赖全部排除,让rollup只打包项目代码

// 读取根目录下的package.json
const json = resolvePkgJson();
// 将依赖从rollup打包配置中排除
const option = resolveRollupOption()
option.external.push(json.dep,json.devDep)
// 打包
rollupBuild(option)

buildElectron

这里是最终生成平台安装包的地方,它借助electron-builder来实现

electronBuilder(//配置)

主要有3个坑点

一个是electron下载会出问题,可以通过配置切换源,或者事先下载好,我这里是使用的后者,然后设置electronDist从本地获取

electronBuilder({
    electronDist:"下载zip的位置"
})

另一个是在打包多平台时,必须为每一个平台单独设置目录,且不能并发执行

for (let i = 0; i < plats.length; i++) {
    const output = resolveDir(plats[i])
    await electronBuilder({
        output
    })
}

最后一个是主进程引入路径问题:渲染进程在打包后需要通过file://开头引入,非渲染进程则需要以绝对路径引入

预览

经过上边几步打包过程,就会在指定目录下生成如下一堆文件

image.png

更新

更新的思路也比较简单,无非是把打包后的文件放到指定的服务器,当应用启动时去看看是否需要更新,需要就下载

这里关于打包文件如何上传花了我挺长时间的

按照官方源码的用例来看,只需要在本地创建对应的文件,当打包完成后理应能够自动调用的

image.png

但实际上并未按照预期的那样

至于原因,有懂的小伙伴可以评论区讲讲,我反正是没深究

我采取自主上传,新增upload脚本,从dist中找出需要上传的文件

const files = resolveFiles()

然后丢到ali-oss

aliOss.put('循环拿到file上传')

这样一来,就只需要在应用启动时去检测更新就可以了

app.on('ready', () => { 
    // 设置更新路径
    autoUpdater.setFeedURL('上传到oss的路径');
    // 开始检查
    autoUpdater.checkForUpdates();
    // 监听检查结果
    autoUpdater.on("update-downloaded", () => {
        // 询问用户是否需要更新
        dialog.showMessageBox({
            ...
        }).then(()=>{
            if(用户选择立即更新){
                autoUpdater.quitAndInstall();
                app.quit();
            }
        })
    })
}

结尾

经过上边的步骤之后,就可以把压缩包发给别人来运行你的程序了

但如果想要通过应用商店下载,或者在用户电脑上体验完整功能,还需要进行签名

我大致了解了下,发现签名的费用有点高

所以最终我是采用的web``+基座的形式,即将其发布成网站,然后在electron中加载对应的url

可能有人会有疑问:你这不还是要用electron吗?不还是要签名?

en.......

是没错,但老哥我啊,有自己的考量呢😎