Tauri 应用自动更新 | Updater

Tauri 应用自动更新 | Updater

正常的应用程序更新需要手动下载并安装,而借助 Tauri 内置的 Updater 程序 ,我们可以实现应用程序的自动更新推送

下面将介绍如何在 tauri 项目中实现自动更新推送的过程(仅windows环境)。为了避免给后端增加工作量,我选择静态json文件来配置更新信息,json与安装包同时保存在 minioOSS 中

实现步骤

1. 生成签名

使用签名可以确保文件的完整性和来源可信性,在项目根目录执行命令 npm run tauri signer generate -- -w ./app.key

后生成 app.key 和 app.key.pub(公钥) 文件

2. 配置 Updater

文档: tauri.app/zh-cn/v1/ap...

确保 Tauri 项目配置文件(tauri.conf.json)已经正确配置 Updater:

json5 复制代码
{
  "updater": {
    "active": true,
    // 更新程序是否激活
    "dialog": false,
    // 显示内置对话框,太丑了我不用
    "pubkey": "xxx",
    // app.key.pub签名公钥
    "endpoints": [
      "https://xxx/updater.json"
      // 更新元数据的静态json文件地址
    ]
  }
}
  • endpoints:数组,通过地址列表来确定服务器端是否有可用更新,字符串 {{target}} 和 {{current_version}} 会在 URL 中自动替换。如果指定了多个地址,服务器在预期时间内未响应,更新程序将依次尝试。 endpoints 支持两种格式:

    • 动态接口 - 服务器根据客户端的更新请求确定是否需要更新。 如果需要更新,服务器应以状态代码 200 OK 进行响应,并在正文中包含更新 JSON。 如果不需要更新,服务器必须响应状态代码 204 No Content。
    • 静态文件 - 备用更新技术使用纯 JSON 文件,将更新元数据存储在 gist,github-pages 或其他静态文件存储中。(我选择的)

配置完成后执行构建客户端的命令得到安装包,别忘了开启 updater 后的构建需要环境变量 TAURI_PRIVATE_KEY、TAURI_KEY_PASSWORD

3. 编辑静态json文件(保存更新元数据)

文档: tauri.app/zh-cn/v1/gu...

由于关闭了内置更新对话框,需要在程序内手动检查更新,并执行后续的交互逻辑:

json5 复制代码
// updater.json
{
  "version": "v1.0.0",
  // 版本号,版本格式:主版本号.次版本号.修订号
  "notes": "new Version",
  // 更新说明
  "pub_date": "2024-01-26T01:57:18.253Z",
  // RFC 3339
  "platforms": {
    "windows-x86_64": {
      "signature": "xxx",
      // 私钥,app.key内容
      "url": "https://xxx/xxx.nsis.zip"
      // 安装包地址
    }
  }
}

4. 程序内手动检查更新

自定义弹窗:tauri.app/zh-cn/v1/gu...

typescript 复制代码
checkUpdate().then((res) => {
  const {shouldUpdate, manifest} = res;
  if (shouldUpdate) {
    Modal.confirm({
      title: `发现新版本:${manifest?.version}`,
      content: `是否升级?`,
      okText: '升级',
      cancelText: '取消',
      onOk: async () => {
        try {
          notification.info({
            message: '正在下载更新...',
            duration: 3000,
          });
          await installUpdate();
          await relaunch();
        } catch (e) {
          notification.error({
            message: '下载更新失败',
            description: e?.toString() || '',
          });
        }
      },
    });
  }
});

5. 手动上传文件到 minioOSS

将 updater.json 和 安装包.zip 文件上传到 minioOSS 中,然后将地址替换。在每次发版时手动修改 updater.json 中的信息,再重新构建并上传安装包。

一切顺利时客户端将收到更新

6. 懒人模式(脚本)

  • 在 node 环境内执行构建命令,并继承环境变量
typescript 复制代码
execSync('npm run tauri build', {
  stdio: 'inherit',
  env: {
    ...process.env,
    TAURI_PRIVATE_KEY,
    TAURI_KEY_PASSWORD,
  },
});
  • 登录 minio 并获取cookie

    typescript 复制代码
    async function login() {
      try {
        // 拿到header内的cookie
        const res = await axios.post('https://xxx/xxx/login', {
          accessKey: 'xxx',
          secretKey: 'xxx',
        });
        return res?.headers?.['set-cookie']?.toString();
      } catch (err) {
        console.log('登录minio失败');
        console.log(err);
      }
    }
  • 上传文件到 minio

    typescript 复制代码
    async function uploadFile(data, cookie) {
      try {
        await request.post(
          `https://xxx/buckets/xxx/objects/upload`,
          data,
          {
            headers: {
              Cookie: cookie,
              'Content-Type': 'multipart/form-data',
            },
          },
        );
      } catch (err) {
        console.log('上传文件失败');
        console.log(err);
      }
    }
  • 读取本地安装包并上传

    typescript 复制代码
    const FormData = require('form-data');
    const fs = require('fs');
    
    // 读取本地的 updater.json 文件
    const buffer_updater = fs.readFileSync('./xxx/updater.json')
    // 模拟 formData 格式上传
    const formData_updater = new FormData()
    formData_updater.append(buffer_updater.length.toString(), buffer_updater)
    await uploadFile(formData_updater, cookie)
    
    // 上传安装包同理
相关推荐
ice___Cpu8 分钟前
Linux 基本使用和 web 程序部署 ( 8000 字 Linux 入门 )
linux·运维·前端
JYbill11 分钟前
nestjs使用ESM模块化
前端
加油吧x青年29 分钟前
Web端开启直播技术方案分享
前端·webrtc·直播
吕彬-前端1 小时前
使用vite+react+ts+Ant Design开发后台管理项目(二)
前端·react.js·前端框架
小白小白从不日白1 小时前
react hooks--useCallback
前端·react.js·前端框架
恩婧1 小时前
React项目中使用发布订阅模式
前端·react.js·前端框架·发布订阅模式
mez_Blog1 小时前
个人小结(2.0)
前端·javascript·vue.js·学习·typescript
珊珊而川2 小时前
【浏览器面试真题】sessionStorage和localStorage
前端·javascript·面试
森叶2 小时前
Electron 安装包 asar 解压定位问题实战
前端·javascript·electron
drebander2 小时前
ubuntu 安装 chrome 及 版本匹配的 chromedriver
前端·chrome