Electron 项目实战 02:打包和自动更新

技术选型

  • electron-forge
  • electron-builder

electron-forge 是Electron 官方文档介绍的,打包和发布都包含了,但是包含的坑也非常多。electron-builder下载量和集成打包非常顺利,本教程也是采用electron-buid来介绍打包。大家在技术选型的时候要多找几个,原则:选下载量高、社区活跃度高、问题少的技术,这样可以让你少走很多弯路。

由于我没有mac os 环境,就只介绍windows 环境打包和更新,按文档添加对应配置应该问题不大。

安装依赖

jsx 复制代码
yarn add electron-builder -D

添加打包配置

  • package.json

    jsx 复制代码
    {
      "name": "my-electron-app",
      "version": "0.0.1",
      "main": "main.js",
      "author": "Potter<aa4790139@gmail.com>",
      "license": "MIT",
      "scripts": {
        "dev": "electron .",
        "publish": "electron-builder --win -p always"
      },
      "build": {
        "appId": "com.my.electron.app",
        "productName": "my-electron-app",
        "publish": [
          {
            "provider": "github",
            "owner": "yxw007",
            "repo": "electron_app"
          }
        ],
        "win": {
          "target": "nsis"
        },
        "directories": {
          "output": "build"
        },
        "nsis": {
          "oneClick": false,
          "allowToChangeInstallationDirectory": true
        }
      },
      "devDependencies": {
        "electron": "^28.0.0",
        "electron-builder": "^24.9.1"
      },
    }

打包

bash 复制代码
npm run publish

打包后会自动发布至github对应仓库,Release页会自动生成一个Draft,需要手动发布才能成为正式版本

集成自动更新

  • 安装依赖

    bash 复制代码
    yarn add electron-updater electron-log
  • index.html,添加一个更新标签来显示我们的更新信息

    html 复制代码
    <!DOCTYPE html>
    <html>
    
    <head>
    	<meta charset="UTF-8" />
    	<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    	<meta http-equiv="Content-Security-Policy"
    				content="default-src 'self'; script-src 'self'" />
    	<meta http-equiv="X-Content-Security-Policy"
    				content="default-src 'self'; script-src 'self'" />
    	<title>Electron App</title>
    </head>
    
    <body>
    	<div>Electron App</div>
    	Current version: <span id="version">vX.Y.Z</span>
    	<p id="info"></p>
    	<div id="message"></div>
    </body>
    <script src="./renderer.js"></script>
    
    </html>
  • main.js 添加自动相关代码

    jsx 复制代码
    const { app, BrowserWindow, ipcMain } = require("electron");
    const path = require("node:path");
    //1.添加日志显示,方便问题排查
    const log = require("electron-log");
    const { autoUpdater } = require("electron-updater");
    
    autoUpdater.logger = log;
    autoUpdater.logger.transports.file.level = "info";
    log.info("App starting...");
    
    let win;
    const createWindow = () => {
    	win = new BrowserWindow({
    		width: 800,
    		height: 600,
    		webPreferences: {
    			preload: path.join(__dirname, "preload.js"),
    		},
    	});
    
    	// win.loadFile("index.html");
    	win.loadURL(`file://${__dirname}/index.html#v${app.getVersion()}`);
    };
    
    function sendStatusToWindow(text) {
    	log.info(text);
    	win.webContents.send("message", { message: text });
    }
    //! autoUpdater 监听相关的常用事件
    autoUpdater.on("checking-for-update", () => {
    	sendStatusToWindow("Checking for update...");
    });
    autoUpdater.on("update-available", (info) => {
    	sendStatusToWindow("Update available.");
    });
    autoUpdater.on("update-not-available", (info) => {
    	sendStatusToWindow("Update not available.");
    });
    autoUpdater.on("error", (err) => {
    	sendStatusToWindow("Error in auto-updater. " + err);
    });
    autoUpdater.on("download-progress", (progressObj) => {
    	let log_message = "Download speed: " + progressObj.bytesPerSecond;
    	log_message = log_message + " - Downloaded " + progressObj.percent + "%";
    	log_message =
    		log_message +
    		" (" +
    		progressObj.transferred +
    		"/" +
    		progressObj.total +
    		")";
    	sendStatusToWindow(log_message);
    });
    autoUpdater.on("update-downloaded", (info) => {
    	sendStatusToWindow("Update downloaded");
    	//! 下载完后立即更新
    	autoUpdater.quitAndInstall();
    });
    
    app.whenReady().then(() => {
    	//! 主进程,处理渲染进程的消息
    	ipcMain.handle("ping", () => {
    		return `I'm ipcMain`;
    	});
    
    	// ! 1.监听来自渲染进程的消息
    	ipcMain.on("message-from-renderer", (event, arg) => {
    		console.log("Renderer Process Message:", arg);
    
    		//! 2.发送回复消息到渲染进程
    		event.sender.send("message-from-main", "Hello from main process!");
    	});
    
    	createWindow();
    	console.log(process.platform);
    	app.on("activate", () => {
    		if (BrowserWindow.getAllWindows().length === 0) {
    			createWindow();
    		}
    	});
    });
    
    app.whenReady().then(() => {
      //! app ready 自动检查更新
    	autoUpdater.checkForUpdatesAndNotify();
    	console.log("app ready: checkForUpdatesAndNotify");
    });
    
    app.on("window-all-closed", () => {
    	if (process.platform !== "darwin") {
    		console.log("quit");
    		app.quit();
    	}
    });

重新发布版本

jsx 复制代码
npm run publish

此时github 对应仓库Release 页面又会多一个Draft版本,点击修改让其发布,然后更新package.json 中的版本号,再重新发布一次。

为了让你看到这个过程,你可以先下载我演示的my-electron-app-Setup-0.1.4.exe,安装完后打开会检测自动更新,安装完后再打开就会看到更新至v0.1.5

总结

  • 技术选型时尽量多选几个,选择下载量高、社区活跃高(发包更新频率、bug修复数量、bug修复速度综合对比下)的技术,可以让你少踩坑

补充

说明:如果更新出错,可以到C:\Users\Administrator\AppData\Roaming\xxx\logs 目录下查看main.log 日志查看具体问题

完整:demo

参考文献

更多

家人们,我最近花了2个多月开源了一个文章发布助手artipub,可以帮你一键将markdown发布至多平台(发布和更新),方便大家更好的传播知识和分享你的经验。

目前已支持平台:个人博客、Medium、Dev.to(未来会支持更多平台)

官网地址:https://artipub.github.io/artipub/

仓库地址:https://github.com/artipub/artipub

目前库已可以正常使用,欢迎大家体验、如果你有任何问题和建议都可以提Issue给我反馈。

如果你感兴趣,特别欢迎你的加入,让我们一起完善好这个工具。

帮忙点个star⭐,让更多人知道这个工具,感谢大家🙏

相关推荐
万少3 分钟前
万少用9个AI工具,帮朋友完成了一个"不可能"的项目
前端
小小小小宇5 分钟前
Vue `import` 为什么可以异步加载
前端
WMYeah10 分钟前
【无标题】
前端·rust·抽奖程序·跨平台抽奖程序
Unbelievabletobe11 分钟前
免费外汇api的响应时间在不同时段下的波动分析
大数据·开发语言·前端·python
大哥,带带弟弟20 分钟前
Grafana 前端嵌入与 JWT 鉴权实战
前端·grafana
小小小小宇21 分钟前
前端 V8 引擎垃圾回收机制与内存问题排查
前端
前端老石人32 分钟前
CSS 值定义语法
前端·css
sheeta199842 分钟前
Vue 前端基础笔记
前端·vue.js·笔记
小小小小宇43 分钟前
GitLab + GitLab Runner + Qiankun 微前端 + Nginx + Node 中间件 前端开发机从零搭建 CI/CD 全流程
前端
前端那点事1 小时前
别再写垃圾组件!Vue3 如何设计「真正可复用」的高质量通用组件
前端·vue.js