uniapp-vue3 架构与工程化解决方案大全

61 阅读5分钟

uniapp-vue3 架构与工程化解决方案总结

本项目基于 Vite + Vue 3 + UniApp 构建,针对 SaaS 模式下的 单仓库多租户(Multi-Tenant) 场景进行了深度定制。通过自定义构建脚本与运行时架构,解决了小程序开发中常见的多应用维护、动态资源丢失、多语言,多主题切换等核心痛点。


1. 核心架构:单仓库多应用 (Monorepo-like)

痛点分析

在 SaaS 业务中,需要为几十甚至上百个客户(租户)打包独立的小程序。传统做法通常涉及:

  • 代码冗余:为每个客户维护独立分支或仓库,核心业务逻辑同步困难(O(N) 维护成本)。
  • 配置混乱:发版时需手动修改 appid、接口地址等,极易出现人为失误(如发错版、环境混淆)。

解决方案

采用 配置驱动构建 的架构模式:

  1. 差异化配置管理:所有客户的差异化信息(AppID、接口环境、特有页面)独立存储在 scripts/setting/ 目录下。
  2. 构建时动态注入
    • Manifest 重写:构建脚本 scripts/build/index.js 会在编译前读取指定客户配置,自动覆写 manifest.json 中的 appid
    • Pages 动态合并:基于 scripts/build/baseConfig.ts 定义公共页面,构建时动态合并客户特有的 subPackages,实现“按需打包”,有效控制包体积。

2. 动态资源构建:强制扫描与入口注入

痛点分析

Vite/Rollup 的 Tree Shaking 机制极其严格。对于未被显式引用的文件(例如:按需加载的国际化 JSON、通过后端下发路径加载的动态组件),打包时会被直接丢弃,导致运行时报错。

解决方案

vite.config.ts 中实现自定义扫描逻辑:

  • Glob 扫描:使用 fast-glob 扫描 src/**/i18n/index.ts(国际化文件)和 src/asyncUtils/**/*.{js,ts,vue}(异步工具库)。
  • 强制入口注入:通过 rollupOptions.input 将扫描到的文件显式添加到构建入口中。
    // vite.config.ts 示例逻辑
    const extraFiles = glob.sync(['src/**/i18n/index.ts', 'src/asyncUtils/**/*.{js,ts,vue}']);
    // ...将其加入 rollupOptions.input
    
  • 效果:确保了所有动态资源在构建产物中永久存在,彻底解决了“本地运行正常,打包后文件丢失”的顽疾。

3. 国际化:分包异步加载 (Lazy-Load i18n)

痛点分析

随着业务增长,主包的语言包文件(zh.json/en.json)体积越来越大,影响小程序启动速度。且不同分包的翻译内容耦合在一起,维护困难。

解决方案

  • 分包策略:将翻译文件分散在各个分包中(如 src/subPackageScanQrOrder/i18n/index.ts)。
  • 运行时自动加载
    • src/store/i18/index.ts 中建立分包映射表 i18nMap
    • 利用路由拦截或页面生命周期,调用 mergeLocalMessageByRouter(hashPath),根据当前访问的路径按需加载对应的语言包。
  • 效果:显著减小主包体积,实现“访问哪个业务模块,加载哪份语言包”。

4. UI 工程化:自动主题切换

痛点分析

不同租户或不同业务模块(如“电商主页”需蓝色商务风,“扫码点餐”需红色营销风)对 UI 风格有不同要求。

解决方案

基于 CSS 变量 + 路由监听 的动态主题系统:

  1. 主题定义:在 src/store/useStyle/theme/ 下定义多套主题配置(light, dark, red),包含颜色变量与 CSS 变量。
  2. 配置规则:在 src/utils/env.ts 中配置主题映射规则(例如:subPackageScanQrOrder 模块强制使用 red 主题)。
  3. 自动切换
    • 应用启动时(App.ku.vue),监听路由参数 hashPath
    • 调用 useStyles().switchThemeByRouter() 自动匹配并应用相应主题。
  • 效果:用户在不同业务模块间跳转时,系统自动完成主题色、圆角、间距的无缝切换。

5. 开发体验:环境变量与可视化工具

痛点分析

  • 代码中硬编码(Hardcode)导致环境切换困难。
  • 几十个配置 ID 难以记忆,命令行操作繁琐。

解决方案

  • 全链路环境变量
    • 构建脚本通过 scripts/choreJS/defineEnv.js 将配置注入 process.env
    • 前端代码统一通过 process.env.SITE_CHANNEL_TYPE 等变量访问,代码中无任何敏感信息
  • 可视化构建服务
    • 提供 scripts/server.js 本地服务(默认端口 3003)。
    • 开发者可通过 Web 界面直接点击选择配置并触发构建,无需记忆复杂的 CLI 命令。

6. 全局交互:统一弹窗

痛点分析

传统弹窗组件需要在每个页面单独引入,代码冗余且无法在 Store/纯 JS 文件中调用。

解决方案

  • 全局单例:在根组件 App.ku.vue 中挂载 <HjModal />
  • Store 驱动:通过 Pinia Store (src/store/hjModal/index.ts) 管理弹窗状态。
  • 命令式调用:支持在任何地方通过 useModalStore().confirm(...) 唤起弹窗。
  • 能力增强:不仅支持基础 Alert/Confirm,还封装了支持翻页、富文本展示的“公告模式”,适应复杂的通知场景。