本帖最后由 溯水流光 于 2025-4-29 10:44 编辑
文章的下载和备份:
Gitee: https://gitee.com/HHandHsome/pwa-tutorial
GitHub: https://github.com/HHsomeHand/pwa-tutorial
如何快速开发桌面 APP?PWA 也许是你的答案
本文是上一篇文章《如何快速开发手机 APP?PWA 也许是你的答案》的延续。是其的姊妹篇。
上一篇我们介绍了 PWA 是什么,分析了它的优缺点,并通过 Vue + Vant + Tailwind 快速搭建了一个手机端 DEMO,并成功部署到 GitHub Pages 上, 还打包为了 apk, 体验了 PWA 的开发流程。
上篇文章的传送门: https://bbs.tampermonkey.net.cn/thread-8537-1-1.html
随着 Web 技术的发展,开发一个跨平台的桌面 App 已不再是难事。
特别是对于前端开发者来说,利用现有技术栈,我们可以迅速搭建出一个桌面 Web App。
本篇文章将延续上一篇的思路,打造一个桌面端的小工具,并通过 GitHub Actions 自动部署为 GitHub Pages。
我们会一起完成以下几个步骤:
- 使用 Vite 快速初始化 Vue + Tailwind 项目, 并 git init(与上篇相同,不再赘述, 你可以直接 git clone element Plus 的最佳实践, 见下)
- 引入 Element Plus 并配置自动按需导入
- 开发一个简单的桌面小 Demo
- 配置 GitHub Actions 实现 CI/CD 自动部署到 GitHub Pages
你可以直接 git clone https://github.com/sxzz/element-plus-best-practices.git
https://github.com/sxzz/element-plus-best-practices 是 Element Plus 的最佳实践
可以节省很多搭建环境的时间, 你也可以把你常用的模板托管在 Github 上, 这样需要的使用的时候, 再 git clone 就 OK 了!
一、引入 Element Plus 并配置按需导入
我们先为项目引入适用于桌面端的 UI 框架 —— Element Plus。
pnpm install element-plus
文档: https://element-plus.org/zh-CN/guide/installation.html
为了提升开发效率,我们还需要配置自动导入 Element Plus 的组件和函数:
pnpm install -D unplugin-vue-components unplugin-auto-import
文档: https://element-plus.org/zh-CN/guide/quickstart.html
然后修改 vite.config.js
:
// vite.config.js
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import {ElementPlusResolver} from 'unplugin-vue-components/resolvers'
import tailwindcss from '@tailwindcss/vite'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
AutoImport({
imports: ['vue'],
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
tailwindcss(),
],
})
插件说明:
AutoImport
该插件可以扫描 <script>
和 .js
.ts
, 自动导入Element Plus
的全局函数
// 你的代码
ElMessage.success('Hello')
// AutoImport 自动生成的等效代码
import { ElMessage } from 'element-plus'
ElMessage.success('Hello')
imports: ['vue'],
这行配置可以让应用程序支持自动导入 vue
的 ref
watch
等setup
api
函数
Components
该插件可以扫描<template>
, 自动导入组件
<template>
<ElButton>Click me</ElButton>
</template>
<!-- 原本需要手动 -->
<script>
import { ElButton } from 'element-plus'
</script>
<!-- 使用 Components 插件后,自动生成上述代码 -->
二、开发一个字符分割的小工具
下面是我们要实现的桌面端小工具:
功能说明:
输入一个字符串,如 hzx
,输出为字符数组形式:['h', 'z', 'x']
,并支持一键复制。
虽然如今这种字符处理可以交给 AI 来完成(比如豆包),但它仍是个非常合适的练习案例。
App.vue
核心代码如下:
<script setup>
const input = ref("");
const result = ref("");
// 输入"hzx", 输出 "{'h', 'z', 'x'}"
function splitStringToText(str) {
let content = str.split('') // "hzx" -> ["h", "z", "x"]
.map(ch => `'${ch}'`) // ["h", "z", "x"] -> ["'h'", "'z'", "'x'"]
.join(', ') // ["'h'", "'z'", "'x'"] -> "'h', 'z', 'x'"
return '{' + content + '}';
}
watch(input, (newValue) => {
result.value = splitStringToText(newValue);
}, {immediate: true});
function onCopyBtnClick() {
copyText(result.value);
}
/**
* 复制字符串到剪贴板,并显示提示
* @param {string} text - 要复制的字符串
* @returns {Promise<void>}
*/
async function copyText(text) {
try {
// 检查输入是否为字符串且不为空
if (typeof text !== 'string' || text.trim() === '') {
throw new Error('输入的文本无效');
}
// 使用 Clipboard API 复制文本
await navigator.clipboard.writeText(text);
// 复制成功,显示成功提示
ElMessage({
message: '复制成功!',
type: 'success',
duration: 2000, // 提示显示2秒
});
} catch (error) {
// 复制失败,显示错误提示
ElMessage({
message: '复制失败:' + error.message,
type: 'error',
duration: 3000, // 错误提示显示3秒
});
}
}
</script>
<template>
<div class="app">
<div class="app__container">
<el-input
v-model="input"
class="app__input"
type="textarea"
autosize
placeholder="Please input"
/>
<el-input
v-model="result"
class="app__input"
type="textarea"
readonly
autosize
/>
<el-button type="primary" @click="onCopyBtnClick">复制!</el-button>
</div>
</div>
</template>
<style scoped>
@import "tailwindcss";
.app {
@apply w-screen h-screen flex justify-center items-center;
}
.app__container {
@apply flex flex-col gap-3 w-50;
}
</style>
三、GitHub Actions 自动部署到 GitHub Pages
我们接下来要把项目发布到 GitHub Pages,并实现自动化 CI/CD 流程。
1. 设置 base
假设你的项目仓库地址是:
https://github.com/HHsomeHand/pwa-str-separate
那么在 vite.config.js
中配置:
base: '/pwa-str-separate/'
2. 安装 PWA 插件
pnpm add -D vite-plugin-pwa
并添加到 vite.config.js
:
import { VitePWA } from 'vite-plugin-pwa'
VitePWA({
registerType: 'autoUpdate',
devOptions: {
enabled: false,
},
workbox: {
globPatterns: ['**/*.{mjs,js,css,html,png,jpg,gif,svg,woff,woff2}'],
},
manifest: false
})
3. 设置 favicon 和图标
可以使用 favicon.inbrowser.app 来生成图标, 并记得配置 Start URL
和 icons 路径
, 不然部署在 Github Pages 上时, 访问网页, 控制台会报 404, 找不到 PWA 的图标。
GitHub Actions
GitHub Actions 是一个自动化工具,它会检测你的仓库中是否存在 .github/workflows/[任意名称].yml
文件。当你将代码推送到远程仓库时,GitHub 会检查是否满足触发条件,如果是, 就会分配一台服务器给你, 来执行:
- 下载你的代码
- 运行
pnpm install
pnpm build
构建项目
- 并将结果推送到
gh-pages
分支
部署完成后,你可以设置仓库的 Github Pages 分支为 gh-pages
, 并通过 GitHub Pages 访问你的网站。
配置工作流
在仓库中创建文件 .github/workflows/deploy.yml
(注意 github
和 workflows
拼写不能出错)。文件名可以自定义,没有强制要求。
以下是 deploy.yml
文件的配置内容:
name: Deploy to GitHub Pages
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 8
- name: Install Dependencies
run: pnpm install
- name: Build
run: pnpm build
env:
VITE_BASE_URL: /pwa-str-separate/
- name: Deploy
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
folder: dist
- ubuntu-latest 是分给你的服务器带的系统
- Checkout 是下载你的代码
- Setup Node.js 是安装 Node.js
- Setup pnpm 是安装 pnpm
- Install Dependencies 执行
pnpm install
- Build 执行
pnpm build
- Deploy 就是将打包结果推送到
gh-pages
分支
配置 Github Actions 的权限
我们需要开启 Github Actions 的权限, 使其可以正常读写我们的项目, 并让其可以正常提交内容到我们的gh-pages
分支
向下滚动:
推送到远端服务器
确定 Save保存后, 再git push, 推送我们的代码到服务器, 等 GitHub Actions 构建和部署完毕后, 我们设置 gh-pages
为 GitHub Pages 的展示页面。配置后, 记得点击 Save 保存, 不然配置不会生效。
等待几分钟, 访问https://hhsomehand.github.io/pwa-str-separate/
, 再保存到桌面就OK了!
后续的开发中,只用执行 git push
,GitHub 就会自动为你部署。
你本地下载好的 PWA APP, 也会因为服务器的更新, 而自动更新, 如果本地没有更新, 请刷新页面并检查网络链接。
什么是 CI? 什么是 CD?
CI 是自动打包,如我推送代码到远端git服务器,自动触发GitHub actions,然后帮我打包好了代码。
CD 是自动部署, 这里自动把代码写入gh-page分支,这就算自动部署了。
粗糙地理解: CI 完整的名字是"持续集成". “集成”这个词的字面意思,就是合在一起的意思。“把代码合在一起”就是集成,“把代码合在一起” 也可以抽象地理解为 pnpm build
, 因为打包也相当于把代码合在一起。CD可以自动把结果部署。
PWA Builder 打包
PWA Builder 仅支持打包为MSIX
格式,无法生成单体 exe 文件。其需安装后才能运行,类似apk
。其实我觉得通过浏览器安装到本地已经够用了, 所以这里就不讲了
尾声
感谢你的阅读, 如果遇到问题, 欢迎评论区讨论