首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >打造通用应用启动器

打造通用应用启动器

作者头像
javpower
发布2026-04-13 16:58:38
发布2026-04-13 16:58:38
730
举报

写在前面

你用 Java 写了一个 Spring Boot 后端,前端用 Vue 开发了一个管理界面。现在你需要把这个前后端组合打包成一个桌面应用,分发给客户使用。你开始研究 Electron、Tauri、pkg、launch4j……折腾了几天,终于搞定了。

过了几天,产品经理说:我们还有一个 Python Flask 的数据分析工具,也要打包成桌面应用。你又得从头来一遍。

再过几天,运维同事说:那个 Go 写的监控脚本,能不能也做成桌面版?你崩溃了。

每个后端应用都要单独写一套启动逻辑、打包配置、健康检查……这不合理。

这篇文章不是理论介绍,而是一份"跟着做"的实操教程。你会从零开始,一步一步完成一个真实的桌面应用打包。无论你的后端是 Java、Node.js、Python 还是 Go,只需要一份 YAML 配置文件,就能打包成一个漂亮的桌面应用。

图 1:本文实操流程概览
图 1:本文实操流程概览

图 1:本文实操流程概览


第一章 安装环境准备

在开始之前,你需要确保电脑上已经安装好必要的工具。这一章会带你逐一检查并安装。

1.1 检查 Node.js

打开终端(Windows 按 Win+R 输入 cmd,macOS/Linux 打开 Terminal),输入以下命令:

代码语言:javascript
复制
node --version

如果显示 v18.x.x 或更高版本,说明已安装,跳到下一步。如果没有安装或版本低于 18,按以下方式安装:

访问 https://nodejs.org ,下载 LTS(长期支持)版本并安装。安装完成后重新打开终端,再次运行 node --version 确认。

1.2 检查 Rust

在终端输入:

代码语言:javascript
复制
rustc --version

如果显示版本号,说明已安装。如果没有,访问 https://rustup.rs ,按页面提示安装。Windows 用户直接下载 rustup-init.exe 运行即可。

⚠️ 注意: Windows 用户需要先安装 Visual Studio Build Tools(C++ 构建工具)。访问 https://visualstudio.microsoft.com/visual-cpp-build-tools/ 下载安装,勾选"使用 C++ 的桌面开发"工作负载。

1.3 平台特定依赖

不同操作系统还需要安装额外的系统依赖:

macOS 用户

代码语言:javascript
复制
xcode-select --install

Ubuntu/Debian 用户

代码语言:javascript
复制
sudo apt update
sudo apt install -y libwebkit2gtk-4.0-dev build-essential \
  curl wget file libssl-dev libgtk-3-dev \
  libayatana-appindicator3-dev librsvg2-dev

Fedora 用户

代码语言:javascript
复制
sudo dnf install -y webkit2gtk4.0-devel openssl-devel \
  curl wget file libappindicator-gtk3-devel librsvg2-devel

Arch Linux 用户

代码语言:javascript
复制
sudo pacman -S --needed webkit2gtk-4.0 base-devel \
  curl wget file openssl appmenu-gtk-module \
  libappindicator-gtk3 librsvg

💡 提示: 安装完所有依赖后,建议重启终端,确保环境变量生效。


第二章 理解启动器的工作原理

在动手之前,先花两分钟理解启动器是怎么工作的。知道原理后,后面配置起来会更有底气。

2.1 它解决什么问题

传统方式下,每种后端技术需要不同的打包方案:

图 2:不同后端技术的传统打包方案对比
图 2:不同后端技术的传统打包方案对比

图 2:不同后端技术的传统打包方案对比

而通用启动器的思路是:一个启动器 + 多份配置文件,覆盖所有后端类型。

图 3:传统方式 vs 通用启动器方式
图 3:传统方式 vs 通用启动器方式

图 3:传统方式 vs 通用启动器方式

2.2 三层架构

启动器分为三层,各司其职:

图 4:启动器三层架构
图 4:启动器三层架构

图 4:启动器三层架构

层级

技术栈

职责

第一层(用户界面层)

Vue 3

负责显示启动画面、加载动画、错误提示。最终在 WebView 中加载你的前端页面。

第二层(核心控制层)

Rust

负责解析配置文件、启动后端进程、执行健康检查、管理端口和环境变量。这是启动器的大脑。

第三层(后端进程层)

任意语言

你的实际业务代码。启动器不关心它是什么语言,只关心怎么启动它。

2.3 启动流程

双击启动器后,内部会按以下顺序执行:

图 5:启动器完整启动流程
图 5:启动器完整启动流程

图 5:启动器完整启动流程

步骤

动作

说明

1

读取 launcher.yml 配置文件

解析所有配置项

2

启动后端进程

根据 backend.command 和 backend.args 启动

3

执行健康检查

按照 health_check 配置,反复检查后端是否就绪

4

加载前端页面

后端就绪后,在 WebView 中加载前端页面

5

应用就绪

用户看到完整的应用界面,可以正常使用

💡 提示: 如果健康检查超时(后端迟迟没起来),启动器会在界面上显示错误信息和日志路径,不会直接闪退。

2.4 为什么选 Tauri 不选 Electron

图 6:Tauri vs Electron 技术对比
图 6:Tauri vs Electron 技术对比

图 6:Tauri vs Electron 技术对比

简单说:Tauri 打出来的包只有 5MB 左右,Electron 要 100MB+。对于启动器这种工具,轻量是第一优先级。


第三章 目录结构与文件组织

这一章告诉你打包后的文件长什么样、每个文件干什么用。理解了目录结构,后面的配置就不会迷路。

3.1 标准目录结构

图 7:标准项目目录结构
图 7:标准项目目录结构

图 7:标准项目目录结构

代码语言:javascript
复制
MyApp/
├── MyApp.exe          # 启动器的可执行文件(Windows)
├── launcher.yml       # 核心配置文件
├── frontend/          # 前端文件目录
│   └── index.html
├── backend/           # 后端文件目录
│   └── app.jar
├── runtime/           # 运行时目录(可选)
└── logs/              # 日志目录(自动创建)

文件/目录

作用

MyApp.exe(或 MyApp.app / my-app)

启动器的可执行文件。用户双击它就能启动整个应用。不同平台的文件名不同:Windows 是 .exe,macOS 是 .app,Linux 是无后缀的可执行文件。

launcher.yml

核心配置文件。启动器的一切行为都由它控制:启动什么命令、检查什么端口、前端在哪、窗口多大……改这个文件就够了,不需要改任何代码。

frontend/

放你的前端文件。启动器会在 WebView 中加载这个目录下的 index.html。如果你用的是 Vue/React,这里放的是 npm run build 后的输出(通常是 dist/ 或 build/ 目录的内容)。

backend/

放你的后端文件。Java 应用放 .jar 文件,Node.js 放 server.js 和 node_modules,Python 放 .py 文件和虚拟环境,Go 放编译好的二进制文件。

**runtime/**(可选)

如果你不想让用户自己安装 Java/Python/Node.js,可以把运行时打包进来。比如放一个 JRE 目录,配置文件里指向它。代价是体积变大(JRE 约 150MB)。

logs/

启动器自动创建。运行日志写在这里,排查问题时看 launcher.log。

3.2 精简版目录结构

如果你的应用很简单,文件可以全部放根目录,不需要子文件夹:

代码语言:javascript
复制
MyApp/
├── MyApp.exe      # 启动器
├── launcher.yml   # 配置文件
├── index.html     # 前端(直接放根目录)
└── app.jar        # 后端(直接放根目录)

只要在 launcher.yml 里把路径写成 ./index.html./app.jar 就行。


第四章 快速开始:5 分钟打包第一个应用

这一章是全文的核心。跟着做,你会在 5 分钟内完成第一个桌面应用的打包。

4.1 第一步:下载启动器

从 GitHub Releases 页面下载对应平台的启动器。假设项目地址是 github.com/your-org/universal-launcher

平台

下载文件

Windows

launcher-1.0.0-windows.msi

macOS (Intel)

launcher-1.0.0-macos-intel.dmg

macOS (Apple Silicon M1/M2/M3/M4)

launcher-1.0.0-macos-arm64.dmg

Linux

launcher-1.0.0-linux.AppImage

安装方式:

Windows:双击 .msi 文件安装

macOS:双击 .dmg 文件,把启动器拖到 Applications

Linux:给 AppImage 加执行权限后双击:

代码语言:javascript
复制
chmod +x launcher-1.0.0-linux.AppImage

4.2 第二步:创建项目目录

在任意位置创建一个文件夹,比如桌面上的 MyApp

代码语言:javascript
复制
# Windows
mkdir C:\Users\你的用户名\Desktop\MyApp

# macOS / Linux
mkdir ~/Desktop/MyApp
cd ~/Desktop/MyApp

把下载的启动器复制到这个目录里。Windows 用户把安装后的 .exe 复制过来,或者直接在这个目录安装。

4.3 第三步:创建配置文件

MyApp 目录下创建 launcher.yml 文件。用任何文本编辑器(VS Code、记事本、Sublime Text)都可以。

图 8:用文本编辑器创建配置文件
图 8:用文本编辑器创建配置文件

图 8:用文本编辑器创建配置文件

输入以下内容(这是一个 Spring Boot 应用的配置,后面会讲其他后端的配置):

代码语言:javascript
复制
# launcher.yml
app:
name:"我的应用"
version:"1.0.0"

window:
width:1200
height:800
title:"我的应用 v1.0.0"

backend:
enabled:true
command:"java"
args:
    -"-jar"
    -"backend/app.jar"
working_dir:"./"
env:
    JAVA_HOME:"C:/Program Files/Java/jdk-17"
port:8080

health_check:
type:"http"
url:"http://localhost:8080/actuator/health"
timeout:60
interval:2

frontend:
path:"./frontend"

⚠️ 注意: YAML 对缩进非常敏感!必须用空格缩进(不能用 Tab),每级缩进 2 个空格。如果缩进错误,启动器会解析失败。

4.4 第四步:放入前后端代码

按照配置文件中的路径,组织你的文件:

代码语言:javascript
复制
MyApp/
├── MyApp.exe      # 启动器
├── launcher.yml   # 刚才创建的配置
├── frontend/      # 前端文件
│   └── index.html
└── backend/       # 后端文件
    └── app.jar

如果你还没有现成的前后端代码,可以先用最简单的文件测试:

创建 frontend/index.html

代码语言:javascript
复制
<!DOCTYPE html>
<html>
<head><title>Test</title></head>
<body><h1>Hello from Launcher!</h1></body>
</html>

创建一个最简单的后端(以 Python 为例,因为最快):

代码语言:javascript
复制
# backend/app.py
from http.server import HTTPServer, SimpleHTTPRequestHandler
import json

class Handler(SimpleHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/health':
            self.send_response(200)
            self.send_header('Content-Type', 'application/json')
            self.end_headers()
            self.wfile.write(json.dumps({'status':'ok'}).encode())
        else:
            super().do_GET()

HTTPServer(('127.0.0.1', 8080), Handler).serve_forever()

然后修改 launcher.yml 中的 backend 部分为:

代码语言:javascript
复制
backend:
  enabled:true
command:"python"
args:
    -"backend/app.py"
working_dir:"./"
port:8080
health_check:
    type:"http"
    url:"http://localhost:8080/health"
    timeout:10
    interval:1

4.5 第五步:运行

双击启动器(Windows 双击 .exe,macOS 双击 .app,Linux 双击 AppImage 或 ./my-app)。

你会看到:

  1. 弹出一个窗口,显示加载画面
  2. 后端进程在后台启动(可以打开任务管理器/活动监视器确认)
  3. 几秒后,前端页面加载完成,显示 Hello from Launcher!
  4. 应用就绪,可以正常使用

💡 提示: 如果启动失败,检查 logs/launcher.log 文件,里面有详细的错误信息。最常见的原因是:配置文件路径不对、后端命令找不到、端口被占用。


第五章 配置文件完全指南

launcher.yml 是整个系统的控制中心。这一章逐项讲解每个配置的含义、可选值和实际效果。

图 9:配置文件是启动器的控制中心
图 9:配置文件是启动器的控制中心

图 9:配置文件是启动器的控制中心

5.1 配置文件格式

支持两种格式,推荐 YAML:

代码语言:javascript
复制
# YAML 格式(推荐,支持注释)
app:
  name: "我的应用"
代码语言:javascript
复制
// JSON 格式(备选,方便程序生成)
{ "app": { "name": "我的应用" } }

5.2 查找顺序

启动器按以下顺序查找配置文件:

  1. launcher.yml(优先)
  2. launcher.json(其次)
  3. 内置默认值(都没有的话)

配置文件必须和启动器(.exe/.app)放在同一个目录下。

5.3 应用配置(app)

控制窗口的外观和行为:

代码语言:javascript
复制
app:
  name:"我的应用"           # 应用名称
version:"1.0.0"         # 版本号

window:
title:"我的应用 v1.0.0"# 窗口标题栏文字
width:1200              # 窗口宽度(像素)
height:800              # 窗口高度(像素)
resizable:true          # 是否允许拖拽调整大小
fullscreen:false        # 是否全屏启动
min_width:800           # 最小宽度
min_height:600          # 最小高度
center:true             # 启动时窗口居中
always_on_top:false     # 是否始终置顶

5.4 后端配置(backend)

控制后端进程的启动方式:

代码语言:javascript
复制
backend:
  enabled:true            # 是否启用后端(false=纯前端应用)
command:"java"          # 启动命令
args:                    # 命令参数(列表)
    -"-jar"
    -"backend/app.jar"
    -"--server.port=8080"
working_dir:"./"        # 后端进程的工作目录
env:                     # 环境变量
    JAVA_HOME:"C:/Program Files/Java/jdk-17"
    SPRING_PROFILES_ACTIVE:"prod"
port:8080               # 后端监听端口

💡 提示:command 也可以写成完整命令字符串(不推荐,因为路径中有空格时容易出错):command: "java -jar backend/app.jar"。推荐用 command + args 的列表形式。

5.5 健康检查配置(health_check)

控制如何判断后端已经启动完成:

代码语言:javascript
复制
health_check:
  type:"http"             # 检查类型:http/tcp/file/none
url:"http://localhost:8080/actuator/health"# HTTP检查URL
host:"localhost"        # TCP检查的主机
port:8080               # TCP检查的端口
file_path:"./.ready"    # FILE检查的文件路径
timeout:60              # 最大等待秒数
interval:2              # 每次检查间隔秒数
startup_delay:0         # 启动后延迟几秒再检查
retries:0               # 重试次数(0=无限)

5.6 前端配置(frontend)

代码语言:javascript
复制
frontend:
  path:"./frontend"       # 前端文件目录
entry:"index.html"      # 入口文件名

dev_server:              # 开发模式(仅开发时用)
    enabled:false
    command:"npm"
    args:["run","dev"]
    port:3000

第六章 配置实战:八大场景手把手教你配

这一章是全文最实用的部分。每个场景都是真实工作中会遇到的,配置直接复制就能用。

图 10:不同后端类型的配置差异
图 10:不同后端类型的配置差异

图 10:不同后端类型的配置差异


场景一:Spring Boot + Vue 管理系统

这是最常见的场景。假设你有一个 Spring Boot 后端(打包成 app.jar)和 Vue 前端(npm run build 后输出到 frontend/dist)。

步骤 1:准备文件

app.jar 放到 backend/ 目录,把 Vue 构建产物放到 frontend/dist/ 目录。

确保 app.jar 是 Fat JAR(包含所有依赖),可以用 mvn packagegradle build 生成。

步骤 2:编写配置

创建 launcher.yml,内容如下:

代码语言:javascript
复制
app:
  name:"企业管理系统"
version:"2.1.0"

window:
title:"企业管理系统 v2.1.0"
width:1400
height:900
min_width:1024
min_height:768

backend:
enabled:true
command:"java"
args:
    -"-Xms256m"
    -"-Xmx512m"
    -"-jar"
    -"backend/app.jar"
    -"--spring.profiles.active=prod"
working_dir:"./"
env:
    JAVA_HOME:"${JAVA_HOME}"
    SPRING_PROFILES_ACTIVE:"prod"
port:8080

health_check:
type:"http"
url:"http://localhost:8080/actuator/health"
timeout:120
interval:3

frontend:
path:"./frontend/dist"

步骤 3:验证

双击启动器,等待窗口出现。Java 启动较慢,耐心等 30-60 秒。

如果超时,把 timeout 改大(比如 180),或者检查 JAVA_HOME 路径是否正确。

💡 提示: 生产环境中,建议把 JRE 打包到 runtime/jre/ 目录,然后修改 command./runtime/jre/bin/java,这样用户不需要自己装 Java。


场景二:Node.js + React 全栈应用

Express 后端 + React 前端。注意必须包含 node_modules 目录。

步骤 1:准备文件

backend/ 目录放 server.jspackage.json,运行 npm install 生成 node_modules/

frontend/ 目录放 React 构建产物(npm run build 后的 build/ 目录内容)。

步骤 2:编写配置

代码语言:javascript
复制
app:
  name:"数据看板"
version:"1.0.0"

window:
width:1600
height:1000

backend:
enabled:true
command:"node"
args:["backend/server.js"]
working_dir:"./"
env:
    NODE_ENV:"production"
    PORT:"3001"
port:3001

health_check:
type:"http"
url:"http://localhost:3001/api/health"
timeout:30
interval:2

frontend:
path:"./frontend/build"

⚠️ 注意:node_modules 目录必须完整复制过来!如果缺少依赖,require() 会报错。建议在打包前运行 npm ci --production 只安装生产依赖,减小体积。


场景三:Python Flask 数据分析工具

步骤 1:准备文件

backend/ 目录放 app.pyrequirements.txt

创建虚拟环境并安装依赖:

代码语言:javascript
复制
python -m venv backend/venv
backend/venv/bin/pip install -r requirements.txt

步骤 2:编写配置

代码语言:javascript
复制
app:
  name:"数据分析工具"
version:"3.2.1"

backend:
enabled:true
# Windows:
command:"./backend/venv/Scripts/python.exe"
# macOS/Linux:
# command: "./backend/venv/bin/python"
args:
    -"-m"
    -"flask"
    -"run"
    -"--host=127.0.0.1"
    -"--port=5000"
    -"--no-reload"
working_dir:"./backend"
env:
    FLASK_APP:"app.py"
    FLASK_ENV:"production"
    PYTHONUNBUFFERED:"1"
port:5000

health_check:
type:"http"
url:"http://localhost:5000/api/ping"
timeout:30

frontend:
path:"./frontend"

💡 提示:PYTHONUNBUFFERED 设为 1 很重要!否则 Python 的输出会被缓冲,你看不到实时日志,排查问题时会抓瞎。


场景四:Go 二进制应用

Go 最简单,编译出来就是一个二进制文件,不需要运行时。

代码语言:javascript
复制
# 先编译(在开发机上执行)
# Windows:
GOOS=windows GOARCH=amd64 go build -o backend/monitor.exe ./cmd/server

# macOS:
GOOS=darwin GOARCH=arm64 go build -o backend/monitor ./cmd/server

# Linux:
GOOS=linux GOARCH=amd64 go build -o backend/monitor ./cmd/server
代码语言:javascript
复制
app:
  name:"系统监控"
version:"1.0.0"

backend:
enabled:true
command:"./backend/monitor"
args:[]
working_dir:"./backend"
env:
    GIN_MODE:"release"
port:9090

health_check:
type:"http"
url:"http://localhost:9090/healthz"
timeout:10
interval:1

frontend:
path:"./frontend/dist"

💡 提示: Go 启动只要几十毫秒,timeout 设 10 秒绰绰有余。如果想进一步减小二进制体积,编译时加 -ldflags="-s -w" 去掉调试信息。


场景五:纯前端应用(无后端)

有些应用只有前端,比如计算器、离线文档查看器、Markdown 编辑器。

代码语言:javascript
复制
app:
  name:"离线文档查看器"
version:"1.0.0"

backend:
enabled:false

health_check:
type:"none"

frontend:
path:"./frontend"

就这么简单。启动器会直接加载前端页面,不启动任何后端进程。


场景六:TCP 端口检查(gRPC / WebSocket)

有些后端没有 HTTP 接口,只监听 TCP 端口。这时候用 TCP 检查:

代码语言:javascript
复制
health_check:
  type:"tcp"
host:"localhost"
port:5672
timeout:30
interval:2

场景七:文件检查(数据初始化场景)

有些后端启动后需要初始化数据(比如导入大量数据),完成后创建一个标记文件。这时候用文件检查:

代码语言:javascript
复制
health_check:
  type: "file"
  file_path: "./backend/.ready"
  timeout: 300
  interval: 5

后端代码中,初始化完成后创建标记文件:

代码语言:javascript
复制
# Python 示例
import os

# ... 数据初始化代码 ...

with open('.ready', 'w') as f:
    f.write('ok')

场景八:不检查健康状态

后端启动极快,或者前端不依赖后端,直接启动:

代码语言:javascript
复制
health_check:
  type: "none"

第七章 健康检查机制详解

健康检查是启动器最关键的功能之一。这一章深入讲解它的工作原理和参数调优。

图 11:健康检查机制
图 11:健康检查机制

图 11:健康检查机制

7.1 为什么需要健康检查

桌面应用启动时,需要先启动后端,再打开前端。如果后端还没准备好就打开前端,前端会收到"连接被拒绝"的错误。健康检查的作用就是确保后端完全就绪后,再加载前端页面。

7.2 四种检查方式对比

图 12:四种健康检查方式对比
图 12:四种健康检查方式对比

图 12:四种健康检查方式对比

类型

适用场景

说明

HTTP

Web 应用、REST API

发送 HTTP GET 请求,收到 200 状态码即就绪

TCP

gRPC、WebSocket、数据库

检测端口是否可连接

FILE

数据初始化场景

检测标记文件是否存在

NONE

纯前端或后端启动极快

跳过检查,直接加载前端

7.3 HTTP 检查详解

最常用的方式。向后端发送 HTTP GET 请求,收到 200 状态码就认为后端就绪。

图 13:HTTP 健康检查流程
图 13:HTTP 健康检查流程

图 13:HTTP 健康检查流程

各框架默认健康检查端点:

图 14:常见框架的健康检查端点
图 14:常见框架的健康检查端点

图 14:常见框架的健康检查端点

如果你的后端没有现成的健康检查端点,加一个很简单。以 Express 为例:

代码语言:javascript
复制
// server.js
app.get('/api/health', (req, res) => {
  res.json({ status: 'ok', uptime: process.uptime() });
});

7.4 参数调优建议

不同后端的启动速度差异很大,需要调整参数:

代码语言:javascript
复制
# Java(启动慢)
timeout:120
interval:3
startup_delay:5

# Node.js(启动中等)
timeout:30
interval:2

# Go(启动极快)
timeout:10
interval:1

# Python(取决于依赖加载)
timeout:60
interval:2
startup_delay:3

7.5 排查健康检查失败

图 15:健康检查失败排查指南
图 15:健康检查失败排查指南

图 15:健康检查失败排查指南

实际排查步骤:

步骤 1:查看日志

打开 logs/launcher.log,搜索 ERRORFAILED 关键字。

步骤 2:手动测试后端

在终端手动启动后端命令,看能不能正常启动。

步骤 3:手动测试健康检查

后端启动后,在浏览器访问 health_check.url,看返回什么。

步骤 4:检查端口占用

  • Windowsnetstat -ano | findstr 8080
  • macOS/Linuxlsof -i :8080

第八章 从源码构建启动器

如果你不想用预构建版本,或者需要修改启动器本身,可以从源码构建。

图 16:从源码构建流程
图 16:从源码构建流程

图 16:从源码构建流程

8.1 克隆项目并安装依赖

代码语言:javascript
复制
git clone https://github.com/your-org/universal-launcher.git
cd universal-launcher
npm install

8.2 开发模式运行

代码语言:javascript
复制
npm run tauri dev

这会同时启动 Vite 开发服务器和 Tauri 窗口。修改前端代码后会自动刷新,修改 Rust 代码后会自动重新编译。适合开发调试。

8.3 生产构建

代码语言:javascript
复制
npm run tauri build

构建完成后,安装包在 src-tauri/target/release/bundle/ 目录下。

各平台的输出文件:

图 17:各平台构建输出文件

8.4 交叉编译(在 Mac 上构建 Windows 版)

Tauri 支持交叉编译,但需要额外配置。以在 macOS 上构建 Windows 版为例:

代码语言:javascript
复制
# 安装 Windows 目标
rustup target add x86_64-pc-windows-msvc

# 构建
npm run tauri build -- --target x86_64-pc-windows-msvc

⚠️ 注意: 交叉编译需要对应平台的链接器。实际操作中,建议在 GitHub Actions 中为每个平台单独构建(下一章会讲)。


第九章 GitHub Actions 自动化构建

手动在不同平台上构建太麻烦。配置好 GitHub Actions 后,推送一个 Git 标签就能自动构建所有平台的安装包。

图 18:GitHub Actions 自动化构建
图 18:GitHub Actions 自动化构建

图 18:GitHub Actions 自动化构建

9.1 创建工作流文件

在项目根目录创建 .github/workflows/release.yml

代码语言:javascript
复制
name: Release

on:
push:
    tags:
      -'v*'

jobs:
release:
    permissions:
      contents:write
    strategy:
      fail-fast:false
      matrix:
        include:
          -platform:windows-latest
            args:'--target x86_64-pc-windows-msvc'
            asset_name:launcher-windows
          -platform:macos-latest
            args:'--target aarch64-apple-darwin'
            asset_name:launcher-macos-arm64
          -platform:macos-latest
            args:'--target x86_64-apple-darwin'
            asset_name:launcher-macos-intel
          -platform:ubuntu-latest
            args:''
            asset_name:launcher-linux

    runs-on:${{matrix.platform}}
    steps:
      -uses:actions/checkout@v4
      -uses:actions/setup-node@v4
        with:
          node-version:20
      -uses:dtolnay/rust-toolchain@stable
      
      -name:InstallLinuxdeps
        if:matrix.platform=='ubuntu-latest'
        run:sudoaptinstall-ylibwebkit2gtk-4.0-dev\
          libappindicator3-devlibrsvg2-devpatchelf
      
      -run:npminstall
      -run:npmruntauribuild${{matrix.args}}
      
      -uses:actions/upload-artifact@v4
        with:
          name:${{matrix.asset_name}}
          path:|
            src-tauri/target/release/bundle/msi/*.msi
            src-tauri/target/release/bundle/dmg/*.dmg
            src-tauri/target/release/bundle/appimage/*.AppImage
      
      -uses:softprops/action-gh-release@v1
        with:
          files: |
            src-tauri/target/release/bundle/msi/*.msi
            src-tauri/target/release/bundle/dmg/*.dmg
            src-tauri/target/release/bundle/appimage/*.AppImage

9.2 发布新版本

配置好之后,发布新版本只需要三步:

代码语言:javascript
复制
# 1. 修改版本号(在 package.json 和 tauri.conf.json 中)

# 2. 提交并打标签
git add .
git commit -m "chore: bump version to 1.2.0"
git tag v1.2.0
git push origin main --tags

# 3. 等待 GitHub Actions 完成(约 10-15 分钟)

# 4. 从 GitHub Releases 页面下载各平台安装包

构建完成后,Releases 页面会包含以下文件:

图 19:GitHub Actions 构建产物
图 19:GitHub Actions 构建产物

图 19:GitHub Actions 构建产物


第十章 跨平台支持详解

图 20:跨平台支持
图 20:跨平台支持

图 20:跨平台支持

10.1 平台支持矩阵

图 21:跨平台特性支持矩阵
图 21:跨平台特性支持矩阵

图 21:跨平台特性支持矩阵

10.2 各平台注意事项

Windows

路径用反斜杠或正斜杠都行,推荐正斜杠。环境变量用 %JAVA_HOME%${JAVA_HOME}

如果遇到"缺少 MSVCP140.dll"错误,需要安装 Visual C++ Redistributable。

macOS

首次打开会提示"无法验证开发者"。解决方法:右键点击应用 → 选择"打开" → 点击"打开"确认。

如果要正式分发,需要 Apple Developer 账号进行代码签名和公证($99/年)。

Linux

AppImage 需要加执行权限:chmod +x my-app

某些 Linux 发行版需要安装 FUSE:sudo apt install fuse

如果 AppImage 无法运行,尝试解压运行:./my-app --appimage-extract && ./squashfs-root/AppRun


第十一章 更新与分发

11.1 最简单的更新方式:替换文件

通用启动器采用最朴素的更新策略——直接替换文件。用户操作步骤:

步骤 1:关闭正在运行的应用

步骤 2:用新文件替换旧文件

替换 .exe/.applauncher.ymlfrontend/backend/ 目录

步骤 3:重新启动

11.2 脚本更新(推荐)

创建一个 update.bat(Windows)或 update.sh(Linux/macOS),用户双击就能更新:

Windows (update.bat):

代码语言:javascript
复制
@echo off
echo 正在更新应用...
taskkill /F /IM MyApp.exe 2>nul
timeout /t 2 /nobreak >nul
xcopy /Y /E new_version\*.* .\
echo 更新完成!
start MyApp.exe

Linux/macOS (update.sh):

代码语言:javascript
复制
#!/bin/bash
echo "正在更新应用..."
pkill -f MyApp 2>/dev/null
sleep 2
cp -r new_version/* ./
echo "更新完成!"
open MyApp.app    # macOS
# ./MyApp         # Linux

11.3 分发方式

方式

说明

内网分发

把安装包放在内网文件服务器,用户自行下载

U盘分发

拷贝到U盘,在目标机器上安装。适合离线环境

网盘分发

上传到百度网盘、阿里云盘,分享链接


第十二章 技术栈解析

图 22:技术栈
图 22:技术栈

图 22:技术栈

图 23:技术栈协作关系
图 23:技术栈协作关系

图 23:技术栈协作关系

12.1 Tauri(Rust)

Tauri 是启动器的核心框架。它负责:窗口管理、WebView 嵌入、进程启动和管理、系统集成(系统托盘、通知、文件操作)、跨平台构建。

选择 Tauri 的原因:包体积小(~5MB)、内存占用低(~30MB)、启动快(<1秒)、安全性高(Rust 内存安全)。

12.2 Vue 3

启动器的用户界面用 Vue 3 开发,包括:启动画面(应用启动时显示)、加载动画(等待后端就绪时显示)、错误页面(健康检查失败时显示)。

选择 Vue 3 的原因:上手快、组合式 API 代码组织好、TypeScript 支持优秀。

12.3 Vite

Vite 是前端构建工具。开发时提供极快的热更新,构建时生成优化的静态文件。选择它的原因:启动速度快、HMR 快、插件生态丰富。


第十三章 常见问题排查手册

这一章收集了实际使用中最常遇到的问题和解决方案。

问题

解答

Q1:启动器双击后闪退,什么都没看到

查看 logs/launcher.log。最常见原因:YAML 缩进错误(必须用空格不能用 Tab)、后端命令路径不对、端口被占用。

Q2:后端启动了但前端显示连接错误

健康检查通过了但前端请求的 API 地址不对。检查前端的 API baseURL 配置,确保指向正确的后端端口。

Q3:Java 应用启动超时

Java 启动慢是正常的。把 timeout 改到 120-180 秒。如果用了 Spring Boot,确认 spring.profiles.active 设置正确。

Q4:macOS 提示"无法验证开发者"

右键点击应用 → 打开 → 点击打开确认。如果要正式分发,需要 Apple Developer 账号签名。

Q5:Linux AppImage 双击没反应

终端执行 chmod +x my-app 添加执行权限。如果还不行,终端运行 ./my-app 看报错信息。

Q6:如何减小应用体积

不打包运行时(要求用户自行安装)、前端用 npm run build 生产构建、Go 加 -ldflags="-s -w"、Java 排除不需要的依赖。

Q7:如何让应用开机自启动

Windows:把快捷方式放到 shell:startup 目录。macOS:系统设置 → 通用 → 登录项。Linux:创建 ~/.config/autostart/myapp.desktop。

Q8:配置文件中如何使用环境变量

用 ${变量名} 语法,比如 JAVA_HOME: "${JAVA_HOME}"。启动器会自动替换为系统环境变量的值。

Q9:如何同时运行多个实例

目前不支持。每个应用使用独立的目录和配置文件即可。

Q10:如何自定义启动画面

替换 frontend/ 目录下的启动页面文件。启动画面是一个普通的 HTML 页面,你可以自由设计样式。


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-04-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coder建设 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • 第一章 安装环境准备
    • 1.1 检查 Node.js
    • 1.2 检查 Rust
    • 1.3 平台特定依赖
      • macOS 用户
      • Ubuntu/Debian 用户
      • Fedora 用户
      • Arch Linux 用户
  • 第二章 理解启动器的工作原理
    • 2.1 它解决什么问题
    • 2.2 三层架构
    • 2.3 启动流程
    • 2.4 为什么选 Tauri 不选 Electron
  • 第三章 目录结构与文件组织
    • 3.1 标准目录结构
    • 3.2 精简版目录结构
  • 第四章 快速开始:5 分钟打包第一个应用
    • 4.1 第一步:下载启动器
    • 4.2 第二步:创建项目目录
    • 4.3 第三步:创建配置文件
    • 4.4 第四步:放入前后端代码
    • 4.5 第五步:运行
  • 第五章 配置文件完全指南
    • 5.1 配置文件格式
    • 5.2 查找顺序
    • 5.3 应用配置(app)
    • 5.4 后端配置(backend)
    • 5.5 健康检查配置(health_check)
    • 5.6 前端配置(frontend)
  • 第六章 配置实战:八大场景手把手教你配
    • 场景一:Spring Boot + Vue 管理系统
    • 场景二:Node.js + React 全栈应用
    • 场景三:Python Flask 数据分析工具
    • 场景四:Go 二进制应用
    • 场景五:纯前端应用(无后端)
    • 场景六:TCP 端口检查(gRPC / WebSocket)
    • 场景七:文件检查(数据初始化场景)
    • 场景八:不检查健康状态
  • 第七章 健康检查机制详解
    • 7.1 为什么需要健康检查
    • 7.2 四种检查方式对比
    • 7.3 HTTP 检查详解
    • 7.4 参数调优建议
    • 7.5 排查健康检查失败
  • 第八章 从源码构建启动器
    • 8.1 克隆项目并安装依赖
    • 8.2 开发模式运行
    • 8.3 生产构建
    • 8.4 交叉编译(在 Mac 上构建 Windows 版)
  • 第九章 GitHub Actions 自动化构建
    • 9.1 创建工作流文件
    • 9.2 发布新版本
  • 第十章 跨平台支持详解
    • 10.1 平台支持矩阵
    • 10.2 各平台注意事项
      • Windows
      • macOS
      • Linux
  • 第十一章 更新与分发
    • 11.1 最简单的更新方式:替换文件
    • 11.2 脚本更新(推荐)
    • 11.3 分发方式
  • 第十二章 技术栈解析
    • 12.1 Tauri(Rust)
    • 12.2 Vue 3
    • 12.3 Vite
  • 第十三章 常见问题排查手册
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档