Skip to content

构建期插件

两个 vite 插件。它们在 build / dev 里跑,坑的共同点是:行为发生在构建时, 出问题的现象却在运行时,而且一个会真的往生产发东西。

components-upload

@hiapi/hiapi-cloud-components-upload · 0.2.1 · 源码 hiapi-cloud-components-upload/

把前端产物发布到应用商店。装在 vite.config.tsplugins 里,在 closeBundle 阶段上传。

build 会真的发版

pnpm build 跑到最后就是一次真实的应用商店发布,不是"打个包"。 本地验证前先确认 disable:

  • shop-web:硬编码 disable: true(安全)
  • shop-admin:默认会上传,靠环境变量关 —— SHOP_ADMIN_NO_UPLOAD=1 pnpm build
  • 其余工程自己看 vite.config.ts
ts
UploadPlugin({
  server: 'https://appstore.cloud.adinz.com/api/v1/releases/frontend',
  project: pkg.name,          // 必须等于 package.json.name
  appId: 'P-10003',
  appSecret: '...',           // 妥善保管,防止恶意上报
  files: [`dist/build/h5/${pkg.name}.umd.js`],
  version: pkg.version,
  disable: true,
  pageDir: pkg.pages,         // 页面目录约定,如 'subShop'
  componentDir: pkg.components, // 组件目录约定,如 'hiapi-shop'
  remark: '商城 C 端组件与页面',
  menus: [...],               // 管理后台类应用:菜单自描述
  micro: {name: 'HiapiCloudShopAdmin', activeRule: '/micro-apps/shop'},
  i18nDir: 'src/i18n',        // 默认值
  iconDir: 'src/assets/svg',  // 默认值
})

选项

字段说明
server / appId / appSecret上传地址与鉴权
project必须等于 package.json.name,装修器按 window[project][component] 取组件
files要上传的产物
pageDir / componentDir页面 / 组件目录名,服务端据此归类
menus菜单自描述(menuId/pid/label/langCode/icon/secured/url/accountType/sort),随发布上报
microqiankun 注册信息,管理后台类应用必填,主应用据此动态 registerMicroApps
i18nDir菜单文案从这里抽 <dir>/<lang>/*.json
iconDir菜单图标 svg 目录
disable禁用上传
pages已废弃,传了完全没有效果

pages 静态清单已经死了

页面链接改为运行期实时获取:子应用实现框架的 AppLinkProvider SPI (links() / options()),装修器打开链接选择器时由 hiapi-cloud-public 实时调用。 public 侧的入库路径(AppStoreLogic.reloadPages)已删除

静态清单的问题是发版之后就不会再变,而且表达不了带参数的页面 (商品详情、设备详情、指定类目 —— 必须先选出具体是哪一个)。

字段保留只是为了不让各子应用的构建立刻报错。看到工程里还留着 pages: [...], 那是历史残留,不要以为改它有用。参见子应用接入

组件清单是怎么被解析出来的

插件把 src/components/index.ts 复制进 zip,跑一遍 removeImports() (把所有 import 替换成 const X = null),然后当模块求值,取 widgetExport 具名导出或 default 导出。

所以注册表必须是字面量对象

import.meta.glob 自动聚合会在 removeImports() 那一步得到空对象 —— 装修器里一个组件都看不到,而本地开发一切正常。别"优化"成 glob。

dynamic-renderer

@hiapi/hiapi-cloud-dynamic-renderer · 0.0.8 · 源码 uniapp/hiapi-cloud-dynamic-renderer/

扫组件目录,生成 DynamicRenderer.vue —— 一个按 item.component 名字分发渲染的组件。

ts
dynamicRendererPlugin({
  dst: 'src/layouts/DynamicRenderer.vue',   // 默认
  dirs: 'src/components/**/*.vue',          // 默认
  property: true,                            // 同时生成 `-property` 分支
})

DynamicRenderer.vue 是生成产物,不要手改

改了下次构建就被覆盖。要改渲染逻辑,改的是生成器插件里的模板 (uniapp/hiapi-cloud-dynamic-renderer 的 content 模板),然后发版、下游升版本、重新生成。

新建组件目录后必须重启 dev server

插件的文件列表 fg.sync(dirs)启动时的快照。watcher 触发的重新生成拿不到新增文件 —— 现象是新组件在画布上静默空白,而代码看着完全正确。

组件名由目录推导成 kebab:src/components/hiapi-shop/product-list/index.vuehiapi-shop-product-listproperty: true 时同一目录的 property.vuehiapi-shop-product-list-property

两条注册链路都要走

链路文件负责
自动src/layouts/DynamicRenderer.vue(生成)按组件名渲染
手写src/components/index.tsUMD 导出 + 装修器元信息(data/styles 默认值 = 组件契约)

漏了后者:装修器左侧看不到这个组件。 漏了前者(忘了重启 dev):画布上是空白。

schema.component 必须等于目录推导出的 kebab 名,schema.project 必须等于 package.json.name —— 对不上时装修器 window[project][component] 取不到组件,静默空白

构建脚本的一个反直觉现实

shop-webpnpm build:h5build.lib.entry 指向 src/components/index.ts, 所以它只构建 widget UMD 包 —— src/subShop/pages/** 从来没被它编译过。

"build 通过"不代表页面能跑:2026-08-22 有一次三个页面 import 了一个根本没创建成功的 文件,build 照样绿。页面的编译验证只能靠 dev server 按需编译:

bash
pnpm dev:h5
# 另一个终端,逐个请求改动过的文件(vite 会在这时才转换它)
curl --noproxy '*' -o /dev/null -w '%{http_code}\n' http://localhost:5373/src/subShop/pages/order/confirm.vue
# 200 = 编译通过;500 = 有错(比如 Failed to resolve import)

其它 uniapp 工程同理,先看自己的 vite.config.ts 有没有 build.lib