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)
    
    // 上传安装包同理
相关推荐
蜡台6 分钟前
Uniapp H5Builderx 预览Html 显示404问题解决
前端·uni-app
We་ct12 分钟前
LeetCode 190. 颠倒二进制位:两种解法详解
前端·算法·leetcode·typescript
踩着两条虫22 分钟前
AI驱动的Vue3应用开发平台深入探究(二十五):API与参考之Renderer API 参考
前端·javascript·vue.js·人工智能·低代码·前端框架·ai编程
信创DevOps先锋30 分钟前
本土化突围:Gitee如何重新定义企业级项目管理工具价值
前端·gitee·jquery
圣光SG42 分钟前
Java类与对象及面向对象基础核心详细笔记
java·前端·数据库
Jinuss1 小时前
源码分析之React中的useImperativeHandle
开发语言·前端·javascript
ZC跨境爬虫1 小时前
CSS核心知识点与定位实战全解析(结合Playwright爬虫案例)
前端·css·爬虫
Jinuss1 小时前
源码分析之React中的forwardRef解读
前端·javascript·react.js
mengsi551 小时前
Antigravity IDE 在浏览器上 verify 成功但本地 IDE 没反应 “开启Tun依然无济于事” —— 解决方案
前端·ide·chrome·antigravity
Можно1 小时前
pages.json 和 manifest.json 有什么作用?uni-app 核心配置文件详解
前端·小程序·uni-app