UNPKG

weapp-vite

Version:

weapp-vite 一个现代化的小程序打包工具

379 lines (285 loc) 12.4 kB
# Weapp Config ## 入口位置 `weapp-vite` 的小程序配置通常放在: ```ts import { defineConfig } from 'weapp-vite/config' export default defineConfig({ weapp: { srcRoot: 'src', }, }) ``` ## 高频配置项 ### `srcRoot` 源码根目录。排查输出缺页、找不到入口、自动路由异常时先确认它。 ### `autoRoutes` 适合希望用约定生成页面路由的项目。启用后要保持 pages 目录与输出约定稳定。 ### `buildScope` 用于只构建主包和指定分包。常用在大项目里只调试某几个业务分包: ```bash wv dev --scope main,packages/order wv build --scope packages/order ``` 也可以写在配置里: ```ts export default defineConfig({ weapp: { buildScope: { includeMainPackage: true, include: ['packages/order'], }, }, }) ``` `main` 表示主包,`packages/order` 匹配 `app.json.subPackages[].root`。启用后,产物 `app.json.subPackages` 只保留参与 scope 的分包,`preloadRule`、自动路由和 typed router 也会按同一范围裁剪。发布前建议再跑不带 scope 的完整构建。 ### 分包异步模块 跨分包 JS 使用微信官方 callback 或 Promise API```ts require('../../packages/order/modules/price', onLoaded, onError) const moduleExport = await require.async('../../packages/order/modules/price') ``` `weapp-vite` 会把 callback 写法规范化为 `void require.async(path).then(onLoaded, onError)`,并确保静态路径目标作为异步 chunk 输出,避免被当成同步 CommonJS 依赖提升到主包。源码路径带 `.ts` 等扩展名时,调用参数会同步改为实际 `.js` 产物路径。路径必须是静态相对字面量,目标 root 也必须存在于最终 `app.json.subPackages`;使用自动路由的自定义 root 时,同时声明 `weapp.subPackages.<root>`。 希望保留标准 `import()` 写法时,可以选择微信原生分包模式: ```ts export default defineConfig({ weapp: { chunks: { dynamicImports: 'native', }, }, }) const moduleExport = await import('../../packages/order/modules/price.ts') ``` `native` 只转换微信构建中跨入已声明普通分包的静态相对导入,并将路径规范化为 `.js`。动态表达式、裸模块、同包导入、独立分包目标以及非微信构建继续保留 bundler 动态导入。默认的 `preserve` 不做转换;历史 `inline` 已废弃,当前会回退为 `preserve` 并输出一次警告。 跨包自定义组件不走这套 JS API。组件继续使用 `usingComponents``componentPlaceholder`,由微信基础库负责下载后的占位替换。 ### `autoImportComponents` 适合用目录扫描自动注册组件的项目。组件重名时要先解决命名冲突,不要让自动引入规则长期处于歧义状态。 ### `routeRules` 用于给页面路由追加规则,例如 layout、运行时行为等。它属于项目级编排,而不是组件内部语义。 ### `vue.template.htmlTagToWxml` 适合从 Web/Vue 模板迁移到小程序 `.vue` 的项目。开启后,会把常见 HTML 标签映射成小程序内置标签,例如 `div -> view``span -> text``img -> image``a -> navigator`,也包含 `br/hr` 这类容易在迁移时“消失”的标签。 ### `vue.template.htmlTagToWxmlTagClass` 默认开启。仅当 `htmlTagToWxml` 发生标签映射时,为输出节点追加原标签名 class,例如 `h3 -> <view class="h3">``br -> <view class="br" />`。 如果你的迁移策略是“先跑通,再用 CSS 逐步恢复默认外观”,这个开关很有价值;如果不希望产物里自动带这层语义 class,可以显式设为 `false`### `vue.template.formatWxml` 控制 `.vue` / JSX 编译生成的 WXML 是否格式化。默认 `auto`:开发态开启,生产构建关闭。显式设为 `true` 可始终输出带缩进和换行的 WXML,显式设为 `false` 可始终保持紧凑输出。 格式化只处理标签层级缩进,含文本内容的元素会保持单行,避免重排文本空白语义。 ### `vue.template.slotFallbackWrapper` 用于配置普通具名插槽 fallback 的真实 wrapper。微信平台默认使用内部 `virtualHost` 组件;需要回到旧版 `view` 行为时,可配置 `vue.template.slotFallbackWrapperStrategy: 'view'` 或显式 `slotFallbackWrapper: 'view'`。 当组件把自己的默认 `<slot />` 继续透传到子组件的具名插槽时,编译器不能生成 `<slot slot="header" />`,也不能稳定使用 `<block slot="header"><slot /></block>`。真实 WeChat DevTools 运行时中,`block` 路径会丢失转发内容。因此微信平台默认产物是: ```wxml <weapp-slot-wrapper slot="header"> <slot /> </weapp-slot-wrapper> ``` 全局配置示例: ```ts import { defineConfig } from 'weapp-vite/config' export default defineConfig({ weapp: { vue: { template: { slotFallbackWrapper: { tag: 'view', attrs: { class: 'slot-wrapper', }, rules: [ { component: 'IssueCard', slot: 'header', tag: 'cover-view' }, { componentName: 'HelloWorld', slot: 'header', tag: 'cover-view' }, { component: 'IssueCard', slot: 'footer', attrs: { class: 'slot-footer' } }, { component: /^Van/, slot: ['title', 'label'], tag: 'view' }, ], }, }, }, }, }) ``` `component` 匹配使用处模板标签名,例如 `<IssueCard>` 对应 `IssueCard``<issue-card>` 对应 `issue-card`。如果要按子组件自己的名字匹配,让子组件写静态 `defineOptions({ name: 'HelloWorld' })`,然后使用 `componentName: 'HelloWorld'``componentName` 需要编译器能解析到被引用的 Vue SFC;原生小程序组件或第三方小程序组件继续用 `component`。 组件内也可以用静态属性覆盖。`slot-wrapper` 是当前组件所有普通具名插槽的默认 wrapper: ```vue <template> <IssueCard slot-wrapper="cover-view"> <template #header> <slot /> </template> <template #footer> <slot name="footer" /> </template> </IssueCard> </template> ``` 产物: ```wxml <IssueCard> <cover-view slot="header"> <slot /> </cover-view> <cover-view slot="footer"> <slot name="footer" /> </cover-view> </IssueCard> ``` `slot-wrapper-<slotName>` 覆盖指定具名插槽。单个 slot 的覆盖更推荐直接写在对应的 `<template #xxx>` 上: ```vue <template> <IssueCard slot-wrapper="cover-view"> <template #header> <slot /> </template> <template #footer slot-wrapper="view"> <slot name="footer" /> </template> </IssueCard> </template> ``` 产物: ```wxml <IssueCard> <cover-view slot="header"> <slot /> </cover-view> <view slot="footer"> <slot name="footer" /> </view> </IssueCard> ``` 也可以把单个 slot 的覆盖配置写在对应的 `<template #xxx>` 上。这个写法最靠近 slot 内容,也更适合单个 slot 的局部策略: ```vue <template> <IssueCard slot-wrapper="cover-view"> <template #header slot-wrapper="text" slot-wrapper-class="slot-header"> <slot /> </template> <template #footer> <slot name="footer" /> </template> </IssueCard> </template> ``` `<template #header>` 上的 `slot-wrapper` / `slot-wrapper-class` / `slot-wrapper-style` / `slot-single-root-no-wrapper` 是该 slot 的就近覆盖,优先级高于父组件标签上的默认值和 `slot-wrapper-header`。 组件内还可以把 class/style 加到生成的 wrapper 上: ```vue <template> <IssueCard slot-wrapper="cover-view"> <template #header slot-wrapper="cover-view" slot-wrapper-class="slot-default" slot-wrapper-style="padding: 8px"> <slot /> </template> <template #footer slot-wrapper="view" slot-wrapper-class="slot-footer" slot-wrapper-style="margin-top: 12px" > <slot name="footer" /> </template> </IssueCard> </template> ``` ```wxml <IssueCard> <cover-view slot="header" class="slot-default" style="padding: 8px"> <slot /> </cover-view> <view slot="footer" class="slot-footer" style="margin-top: 12px"> <slot name="footer" /> </view> </IssueCard> ``` 也支持 `:slot-wrapper-class="headerClass"` / `:slot-wrapper-style="headerStyle"` 这类动态绑定;单个 slot 更推荐写成 `<template #footer :slot-wrapper-class="footerClass">` 这种就近覆盖。参数名必须是静态的。 `slot-single-root-no-wrapper-<slotName>` 可以让指定插槽在单根真实节点场景下尽量下推 `slot="..."````vue <template> <IssueCard slot-single-root-no-wrapper-icon> <template #icon> <image src="/assets/icon.png" /> </template> </IssueCard> </template> ``` 产物: ```wxml <IssueCard> <image slot="icon" src="/assets/icon.png" /> </IssueCard> ``` 如果插槽内容是转发 `<slot />`,即使配置了 `slot-single-root-no-wrapper-header`,仍会保留 wrapper: ```wxml <IssueCard> <view slot="header"> <slot /> </view> </IssueCard> ``` `block` 不允许作为 wrapper,会回退到 `view` 并输出 warning。自定义 wrapper 必须是目标小程序运行时可渲染、并且能承载当前 slot 内容的真实节点或组件。例如下面的写法会生成 `text` 包裹 `view`,这不适合真实运行时: ```vue <template> <IssueCard> <template #header slot-wrapper="text"> <view>Header</view> </template> </IssueCard> </template> ``` ```wxml <IssueCard> <text slot="header"> <view>Header</view> </text> </IssueCard> ``` ### `layout` 页面 layout 既可能来自项目级规则,也可能来自页面侧 `definePageMeta`。排查时先确认是哪一层生效。 ### `chunks.sharedStrategy` 常见策略: - `duplicate`:偏向分包首开性能 - `hoist`:偏向共享抽取与包体控制 不要在 `srcRoot`、路由来源、分包边界都没确认前就先调 chunk 策略。 ### `hmr.runtime` 默认值为 `auto`。微信项目会在 `wv dev` 启动时根据开发者工具设置自动选择 HMR 运行时,也可显式锁定状态保持型热更新: ```ts export default defineConfig({ weapp: { hmr: { runtime: 'stateful-experimental', }, }, }) ``` 安全的 JavaScript/Vue 更新会保留当前 Page/Component 实例、route/query、输入和可序列化 data/setup ref,并替换原生 Page、原生 Component 与 wevu 方法。CSS、资源、JSON/配置、不兼容模块图或补丁失败会回退完整构建与当前路由重载。 `auto``project.private.config.json``setting.compileHotReLoad` 严格为 `true` 时选择 `stateful-experimental`,否则选择 `classic`;非微信平台也会回退到 `classic`。该判断只在启动时执行,修改开发者工具设置后需要重启 `wv dev`。启动日志会显示最终模式、选择来源,以及通过 DevTools 热重载开关或 `weapp.hmr.runtime` 切换模式的方法。显式配置 `classic``stateful-experimental` 始终优先。 状态保持模式目前只支持微信小程序,需要微信开发者工具开启服务端口和热重载。需要既有写盘/刷新行为时显式配置 `classic`### `hmr.logLevel` / `hmr.profileJson` 排查开发态热更新慢、共享 chunk 回退或 DevTools 热重载不稳定时,可以临时打开: ```ts export default defineConfig({ weapp: { hmr: { logLevel: 'concise', profileJson: '.tmp/weapp-vite-hmr-profile.jsonl', }, }, }) ``` - `logLevel: 'default' | 'concise' | 'verbose'` 控制终端诊断详细程度。 - `profileJson: boolean | string` 控制是否输出 JSONL profile,字符串表示自定义输出路径。 ### `mcp` `weapp.mcp` 默认启用,但默认不自动启动服务。AI 客户端接入优先走 CLI```bash wv mcp init codex wv mcp print codex wv mcp doctor codex ``` ## CLI 与 IDE 命令 `weapp-vite` 原生命令优先,IDE 相关命令通过 `weapp-ide-cli` 透传。 例如: ```bash weapp-vite build weapp-vite preview --project ./dist/build/mp-weixin weapp-vite ide preview --project ./dist/build/mp-weixin ``` ## 继续阅读 - 项目结构与 `AGENTS.md`:[`project-structure.md`](./project-structure.md) - wevu 运行时写法:[`wevu-authoring.md`](./wevu-authoring.md) - Vue SFC 宏与模板:[`vue-sfc.md`](./vue-sfc.md)