--- url: /packages/mcp.md --- # @weapp-vite/mcp `@weapp-vite/mcp` 是一个 MCP 示例服务包,用于展示如何基于 MCP SDK 注册工具并通过 stdio 传输响应调用。 > 该包以教学和验证为主,不是面向生产的完整服务框架。 ## 何时使用 * 你要快速理解 MCP 服务端最小结构 * 你要验证 MCP Client 与 stdio 服务联调流程 * 你要基于示例改造自己的工具服务 ## 安装 ```bash pnpm add @weapp-vite/mcp ``` ## 运行示例 ```bash pnpm --filter @weapp-vite/mcp start ``` 包内示例包含两个工具: * `calculate-bmi` * `fetch-weather` ## 二次开发建议 直接修改 `packages/mcp/src/index.ts`: * 新增工具与参数 schema(zod) * 调整服务 `name/version` * 接入真实业务 API 与鉴权逻辑 --- --- url: /packages/volar.md --- # @weapp-vite/volar `@weapp-vite/volar` 为 weapp-vite 项目提供 Volar 语言服务能力,重点增强 `` 配置块的补全与校验。 ## 何时使用 * 你在 `.vue` 文件里使用 `` 自定义块 * 你希望拿到配置字段的类型提示和错误检查 * 你在 VSCode + Volar 环境下做小程序配置开发 ## 安装说明 通常不需要单独安装。使用 `weapp-vite` 时会自动带上该能力。 ```bash pnpm add -D @weapp-vite/volar ``` ## 主要能力 * `` 块配置提示与校验 * JSON Schema 语义支持 * 依据路径自动推断 `App/Page/Component` 配置类型 * 支持 `json/jsonc/json5` 与 js/ts 配置表达 ## 推荐阅读 * [JSON 配置智能提示](/guide/json-intelli-sense) * [使用 TS/JS 生成 JSON](/guide/json-enhance) --- --- url: /packages/web.md --- # @weapp-vite/web `@weapp-vite/web` 是实验性的 H5 运行时与 Vite 插件,用于把小程序模板能力映射到浏览器环境做验证。 > 当前仍是 POC 阶段,适合技术验证,不建议直接作为生产方案。 ## 何时使用 * 你要在浏览器快速验证小程序页面逻辑 * 你要做模板编译、事件桥接、路由行为的实验 * 你要为小程序 DSL 做 Web 演示或调试 ## 安装 ```bash pnpm add -D @weapp-vite/web ``` ## Vite 插件接入 ```ts import { weappWebPlugin } from '@weapp-vite/web' import { defineConfig } from 'vite' export default defineConfig({ plugins: [ weappWebPlugin({ srcDir: 'src', runtime: { executionMode: 'compat', }, }), ], }) ``` ## 运行时能力 包内同时导出运行时 API,例如: * `defineComponent` * `registerApp` / `registerPage` / `registerComponent` * `navigateTo` / `navigateBack` / `getCurrentPages` * `request` / `showToast` 等 polyfill API ## 能力边界 * 支持 `wx:if` / `wx:for` / 插值等常见语法 * 支持小程序到 DOM 事件桥接(如 `bindtap`) * 样式与 API 兼容度仍在持续补齐 --- --- url: /packages/weapi.md --- # @wevu/api `@wevu/api` 提供跨平台小程序 API 封装,默认推荐 Promise 调用方式,同时兼容传统回调风格。 ## 何时使用 * 你希望在业务层统一调用 `wx/my/tt` 等平台能力 * 你希望优先使用 Promise,减少回调嵌套 * 你希望按平台显式注入适配器 ## 安装 ```bash pnpm add @wevu/api ``` ## Promise 风格(推荐) ```ts import { wpi } from '@wevu/api' const res = await wpi.request({ url: 'https://example.com', method: 'GET', }) ``` ## 回调风格(兼容) ```ts import { wpi } from '@wevu/api' wpi.request({ url: 'https://example.com', success(res) { console.log(res) }, }) ``` ## 显式注入平台 ```ts import { createWeapi } from '@wevu/api' const api = createWeapi({ adapter: wx, platform: 'wx', }) ``` ## 行为说明 * 仅在未传回调时返回 Promise * `*Sync` 与 `onXxx/offXxx` 直连宿主 API * 缺失 API 时,Promise 风格会 `reject`,回调风格会触发 `fail` --- --- url: /packages/wevu-compiler.md --- # @wevu/compiler `@wevu/compiler` 是 Wevu 的编译能力底座,提供 Vue SFC 与小程序模板的解析、转换和输出能力。 ## 何时使用 * 你要在非 Vite 场景复用 Wevu 编译链路 * 你要独立处理 SFC 的 script/template/style/config * 你要在构建阶段做页面特性分析与注入 ## 安装 ```bash pnpm add @wevu/compiler ``` ## 最小示例:编译 SFC ```ts import { compileSfc } from '@wevu/compiler' const result = await compileSfc(sourceCode, 'pages/index/index.vue', { isPage: true, json: { kind: 'page' }, }) console.log(result.script) console.log(result.template) console.log(result.style) ``` ## 常用导出 * `compileSfc` / `compileVueFile` * `compileTemplate` / `compileStyle` * `collectWevuPageFeatureFlags` * `injectWevuPageFeaturesInJs` ## 与 weapp-vite 的关系 `weapp-vite` 在上层整合构建流程,`@wevu/compiler` 提供底层编译能力。若你只是常规业务开发,优先看 [weapp-vite 指引](/guide/)。 --- --- url: /deep/init.md --- # `weapp-vite init` 做了什么? `weapp-vite init` 是在现有原生项目上接入 weapp-vite 的最快方式。它会检查当前目录结构、补齐必需的配置文件,然后提示你后续可以手动调整的地方。本节逐步拆解各项改动,方便团队在需要时自行定制或纯手动迁移。 > \[!TIP] > 如果你更倾向于完全手工搭建,也可以把下面每一小节视为 Checklist,按需执行对应步骤。 ## 1. 修改 `project.config.json` * 设置 `miniprogramRoot` 指向 weapp-vite 产物目录(默认 `dist`),确保微信开发者工具预览/上传的始终是编译后的文件。 * 统一 `npm` 构建相关字段,避免与 weapp-vite 的自动 npm 策略冲突。 > 手工迁移时,记得在开发者工具中重新选择项目根目录或刷新配置,使其指向新的 `dist` 路径。 ## 2. 更新 `package.json` * 添加 `pnpm dev`、`pnpm build`、`pnpm open` 等脚本,与 weapp-vite CLI 对齐。 * 安装基础依赖(`weapp-vite`、`typescript`、`@types` 系列)以及推荐的工具链。 脚本示例: ```json { "scripts": { "dev": "weapp-vite dev", "build": "weapp-vite build", "open": "weapp-vite open", "lint": "eslint . --ext .ts,.js --fix" } } ``` ## 3. 新增 `tsconfig.json` 与 `vite-env.d.ts` * `tsconfig.json` 提供 TypeScript 编译基础配置,并启用小程序类型提示。 * `vite-env.d.ts` 声明 weapp-vite 自动注入的全局类型,避免在编辑器中出现缺失提示。 如果项目暂不使用 TypeScript,也建议保留这些文件,以便后续随时开启类型支持。 ## 4. 生成 `vite.config.[m]ts` * 创建标准的 `vite.config.ts`(或 `vite.config.mts`)并写入 weapp-vite 默认配置。 * 默认配置中包含 `weapp: { srcRoot: '.', subPackages: [] }` 等常用字段,你可以在此基础上继续补充别名、插件等设置。 ```ts import { defineConfig } from 'weapp-vite/config' export default defineConfig({ weapp: { srcRoot: '.', }, }) ``` > \[!IMPORTANT] > 若项目目录结构特殊(例如 `app.json` 位于 `miniprogram/`),请记得修改 `srcRoot`,并结合 [基础目录与资源收集配置](/config/paths.md) 进行调优。 ## 5. 更新 `.gitignore` * 添加 `dist/`、`node_modules/`、临时缓存等条目,避免编译产物误入版本库。 * 如果项目已有 `.gitignore`,脚手架会合并新条目而非覆盖原内容。 ## 6. 其他辅助文件 * 视情况添加 `README` 提示、`pnpm-workspace.yaml`(在 Monorepo 场景下)等文件。 * 对于 SCSS/Tailwind 等需要额外配置的工具,脚手架会保留注释提示下一步应该如何开启。 *** 完成 `weapp-vite init` 后,建议依次执行: 1. `pnpm install` 安装依赖; 2. `pnpm dev --open` 验证项目能在微信开发者工具中正常运行; 3. 参考 [快速开始](/guide/) 继续进行页面开发或自定义配置。 如需还原或自定义初始化流程,可直接查看源码:[`@weapp-core/init`](https://github.com/weapp-vite/weapp-vite/tree/main/@weapp-core/init)。 --- --- url: /blog/announce.md --- ![bg](./assets/release4.png) # `weapp-vite` 发布:重塑小程序开发体验! 大家好,我是[`ice breaker`](https://github.com/sonofmagic),也是[`weapp-tailwindcss`](https://github.com/sonofmagic/weapp-tailwindcss)项目的作者。 今天,我非常高兴地宣布`weapp-vite`项目的正式发布,这标志着我在`vite`框架应用与探索上的一个阶段性成果。 `weapp-vite`不仅是我对`vite`技术深入理解和实践的产物,更是我在小程序开发领域的一次创新尝试。该项目旨在结合`vite`的极速构建与热重载能力,为小程序开发者带来更加高效、流畅的开发体验。 通过`weapp-vite`,我们希望能够为小程序开发者提供一种全新的解决方案,让开发过程更加便捷、灵活。同时,我们也期待与广大开发者共同探索`vite`在小程序领域的更多可能性,共同推动小程序开发技术的进步与发展。 ## 什么是 `weapp-vite`? `weapp-vite` 是对 `vite` 的封装,专为小程序开发设计。 它保留了 `vite` 的强大配置和插件系统,同时针对小程序的开发流程进行了优化,支持 `ts`、`postcss`、`sass`、`less` 等现代前端技术栈,让小程序开发更加高效、便捷。 ## 诞生背景 ### 原生小程序开发的痛点 在深入探索小程序开发的过程中,我深刻体会到了原生小程序开发方式所带来的不便与局限。繁琐的构建流程、有限的工具支持,使得开发体验难以令人满意。同时,跨端框架如`uni-app`、`tarojs`等,虽然提供了多平台兼容的能力,但其基于`vue`、`react`等Web框架的写法,对于追求原生体验的开发者来说,显得过于沉重与冗余。此外,尽管这些框架开源,但源代码的复杂性往往让人望而却步,难以深入理解和定制。 ### 差异化加剧的挑战 随着小程序生态的不断发展,各平台之间的差异日益显著。微信小程序凭借其持续的技术投入和创新,如`skyline`、`Donut`等项目的推进,展现出了强大的生命力和未来潜力。然而,这也对开发者提出了更高的要求,需要更加紧密地跟随官方技术动态,以充分利用平台优势。与此同时,其他平台也在不断探索和进步,但市场的竞争与变化使得开发者在选择和适配上面临更多挑战。 ### 轻量化与灵活性的追求 鉴于上述痛点与挑战,我萌生了打造一款既轻量化又灵活的小程序开发解决方案的想法。`weapp-vite`应运而生,它保留了`vite`的极速构建与灵活配置优势,同时针对小程序开发流程进行了深度优化。通过引入编译插件系统,`weapp-vite`允许开发者以原生小程序语法为基础,轻松扩展至其他平台,实现所见即所得的跨端开发体验。 ### `weapp-vite`的优势 * **轻量级构建**:专注于小程序开发的核心需求,提供极简的构建流程与配置选项。 * **灵活扩展**:利用`vite`的插件生态与编译插件系统,轻松实现功能的定制与增强。 * **高度自定义**:支持对小程序语法的深度自定义与转换,满足不同平台的开发需求。 * **紧跟官方步伐**:以原生小程序语法为基础,确保与官方技术动态保持同步。 综上所述,`weapp-vite`的诞生旨在解决原生小程序开发的痛点,提升开发效率与灵活性,同时保持对技术前沿的敏锐洞察与响应。我们期待与广大开发者携手共进,共同探索小程序开发的无限可能。 ## 快速开始 ### 创建与初始化 1. 在微信开发者工具中创建一个新的 `js`/`ts` 项目。 ![](../images/create-project.png) 2. 确保项目根目录下有 `package.json`,若无则运行 `npm init -y` > 假如你创建的是一个 `ts` 项目,你需要在 `vite.config.ts` 里的 `weapp.srcRoot` 配置项,指明使用的是 `'./miniprogram'` 目录,详见本页下方 3. 安装 weapp-vite 并执行初始化命令 ```sh npm i -D weapp-vite # 执行初始化命令 npx weapp-vite init ``` 于是就初始化成功了!然后再执行一下安装包的命令,去安装智能提示的类型定义 ```sh npm i ``` 这样微信开发小程序的智能提示(`types`),就也被安装进来 ## 语言默认支持 你可以直接使用 `typescript`,把 `js` 改成 `ts` 后缀即可,也可以通过安装 `sass` / `less`,并把 `index.wxss` 的后缀名改成相应的后缀来支持样式预处理器,比如 `scss` / `less` 。 ## 开发与构建 * 开发模式:使用 `npm run dev` 启动开发服务器,实时监听文件变化并自动编译。 * 构建模式:通过 `npm run build` 进行生产环境的构建,包括代码压缩等优化。 * 构建 npm:`npm run build-npm` 用于微信开发者工具中的 npm 构建,输出至 `dist/miniprogram_npm`。 * 打开微信开发者工具:`npm run open` 直接启动微信开发者工具,便捷调试。 ## 配置项 配置项可以与 `vite` 通用,同时加入了 `weapp-vite` 的扩展: `vite.config.ts`: ```ts import { defineConfig } from 'weapp-vite/config' export default defineConfig({ // 其他的配置同 weapp: { // 用来配置监听 app.json 所在的目录 // 比如默认情况下 ts 创建的项目,app.json 所在为 './miniprogram' srcRoot: './miniprogram', // weapp-vite options }, }) ``` ![Image](https://pic4.zhimg.com/80/v2-ebc9231004dc0d7582a21d3af7acd302.png) 你可以在 `defineConfig` 使用其他的 `vite` 插件,比如 `weapp-tailwindcss` ## 关于 `weapp-vite` 的承诺与展望 在过去的三年里,`weapp-tailwindcss` 不仅见证了小程序开发社区的蓬勃发展,也陪伴了无数开发者从初识到精通的旅程。这份历程教会了我耐心、细致与不懈追求。现在,我将这份恒心带入 `weapp-vite`,致力于打造一个更加高效、灵活且易于使用的小程序开发解决方案。 ## 期待大家的加入 `weapp-vite` 刚刚起步,虽已初具雏形,但仍有许多待完善之处。我诚挚邀请各位开发者加入我们的行列,共同推动项目的成长: * 报告错误:如果您遇到任何错误或问题,请提`issue`并提供完善的错误信息和复现方式。 * 建议:有增强 `weapp-vite` 的想法吗?请提 `issue` 来分享您的建议。 * 文档:如果您对文档有更好的见解或者更棒的修辞方式,欢迎 `pr`。 * 代码:任何人的代码都不是完美的,我们欢迎你通过 `pr` 给代码提供更好的质量与活力。 ## 未来展望 展望未来,`weapp-vite` 将不断进化以适应小程序开发的最新趋势。我们将持续关注各平台小程序的更新迭代,确保 `weapp-vite` 能够无缝兼容并充分利用这些新特性。同时,我们也期待与广大开发者建立更加紧密的联系,听取大家的意见与建议,共同推动 `weapp-vite` 的发展与完善。 ## 尾言 感谢每一位对 `weapp-tailwindcss` 及 `weapp-vite` 给予关注与支持的朋友。让我们携手并进,在小程序开发的道路上不断前行,共创辉煌! [GitHub 项目地址](https://github.com/sonofmagic/weapp-tailwindcss/tree/main/packages/weapp-vite) --- --- url: /ai.md description: 统一的 AI 学习入口,聚合 llms 语料与 weapp-vite / wevu 技能安装方式。 --- --- --- url: /packages/rolldown-require/options.md --- # API & options > Language: English | [中文](/packages/rolldown-require/options.zh) `rolldown-require` exposes three APIs: `bundleRequire`, `bundleFile`, and `loadFromBundledFile`. Prefer the one-stop `bundleRequire`, which resolves the entry, bundles with rolldown, writes the temp output, loads it, and returns: * `mod`: the executed module (automatically unwraps `default` if present) * `dependencies`: the file paths touched during bundling ## Common options ### filepath / cwd * `filepath` is required and accepts relative or absolute paths. * `cwd` defaults to `process.cwd()` for resolving the relative entry and `tsconfig`. ### format * If omitted, format is inferred from extension and `package.json.type` (`.mjs`/`.mts`/`type:module` -> `esm`, `.cjs`/`.cts` -> `cjs`). * Pass `cjs`/`esm` to skip inference, e.g. force ESM for `.js`. ### require Customize how the temp output is loaded: `(outfile, { format }) => any`. * ESM: `import(outfile)` (temp file or data URL is written during bundling) * CJS: compiles the source via a temporary `_require.extensions` hook Use this to plug in your own loader, add custom `import` logic for ESM output, or inject mocks in tests. ### rolldownOptions Pass through parts of rolldown options: * `input`: add plugins, `resolve` rules, transforms, etc. Internally `platform: 'node'` and `treeshake: false` are fixed, and `define` injects `__dirname`/`__filename`/`import.meta.url`. * `output`: merged with defaults; `format` is overridden by the `format` option, `inlineDynamicImports` is always `true`. > Avoid overriding `platform`, `input`, or `inlineDynamicImports`, otherwise resolution/dependency collection may break. ### external Forwarded to rolldown. The plugin already externalizes most `node_modules` deps while keeping JSON inlined; use this option to exclude or force-inline specific deps. ### tsconfig * Auto-searches upward for `tsconfig.json` and reads `paths` for alias resolution during bundling. * Pass a string to set the path explicitly; pass `false` to disable tsconfig handling. ### getOutputFile Customize where the temp output is written (defaults to `node_modules/.rolldown-require` or the system temp dir with a random suffix). Handy for writing to a debuggable location. ### preserveTemporaryFile Temp files are cleaned after CJS load or ESM import by default. Set to `true` (or `BUNDLE_REQUIRE_PRESERVE`) to keep them for inspection. ### cache Disabled when `false`/unset. Pass `true` or an object to enable persistent + memory cache; see [Loading flow & cache](/packages/rolldown-require/cache) for details. ## Example configuration ```ts import { bundleRequire } from 'rolldown-require' const { mod } = await bundleRequire({ cwd: process.cwd(), filepath: './tooling/config.ts', format: 'esm', tsconfig: './tsconfig.node.json', external: ['fsevents'], cache: { enabled: true, dir: './node_modules/.rolldown-require-cache', onEvent: e => console.log('[rolldown-require cache]', e), }, rolldownOptions: { input: { plugins: [ myCustomPlugin(), ], }, }, }) ``` This setup will: 1. Bundle `tooling/config.ts` as ESM using the specified `tsconfig`. 2. Mark `fsevents` as external while keeping the default externalization behaviour for others. 3. Cache the temp output in the given directory and emit cache events via `onEvent`. --- --- url: /packages/rolldown-require/options.zh.md --- # API 与选项说明 > 语言: [English](/packages/rolldown-require/options) | 中文 `rolldown-require` 暴露了 `bundleRequire` / `bundleFile` / `loadFromBundledFile` 三个 API,但推荐优先使用一站式的 `bundleRequire`。它会完成入口解析、rolldown 打包、临时产物生成与最终加载,并返回: * `mod`: 已执行的模块(若存在 `default`,会自动返回 `default`) * `dependencies`: 打包阶段命中的文件路径列表 ## 常用选项 ### filepath / cwd * `filepath` 必填,支持相对路径或绝对路径。 * `cwd` 默认使用 `process.cwd()`,用于解析相对入口和 `tsconfig`。 ### format * 不传则自动根据后缀与 `package.json.type` 推断(`.mjs`/`.mts`/`type:module` -> `esm`,`.cjs`/`.cts` -> `cjs`)。 * 手动传入 `cjs`/`esm` 可跳过推断,例如希望强制以 ESM 方式加载 `.js`。 ### require 自定义产物的加载方式,签名为 `(outfile, { format }) => any`。默认行为: * ESM:`import(outfile)`(在打包时会写入临时文件或 data: URL) * CJS:通过 `_require.extensions` 临时钩子编译并 `require` 源文件 典型用途:接入你自己的 loader、为 ESM 产物追加自定义 `import` 逻辑,或在测试环境中注入 mock。 ### rolldownOptions 允许透传部分 rolldown 选项: * `input`: 可加入自定义插件、`resolve` 规则、`transform` 等。内部会固定 `platform: 'node'`、`treeshake: false`,并注入 `define` 保持 `__dirname`/`__filename`/`import.meta.url`。 * `output`: 会与内部默认项合并,但 `format` 会被 `format` 选项覆盖,`inlineDynamicImports` 固定为 `true`。 > 避免覆写 `platform`、`input` 或 `inlineDynamicImports`,否则可能导致运行时与依赖收集异常。 ### external 传递给 rolldown 的 `external` 配置。插件会自动外部化大部分 `node_modules` 依赖并保留 JSON 内联;通过该选项可进一步排除或强制内联特定依赖。 ### tsconfig * 默认自动向上查找 `tsconfig.json` 并读取 `paths`,让打包阶段能解析别名。 * 传入字符串可指定路径;传入 `false` 可禁用 `tsconfig` 解析。 ### getOutputFile 自定义临时产物的落盘路径(默认生成到 `node_modules/.rolldown-require` 或系统临时目录,并带随机后缀)。可用于将产物写入更易调试的位置。 ### preserveTemporaryFile 默认会在 CJS 加载完成或 ESM 加载后清理临时文件。将其设为 `true`(或设置环境变量 `BUNDLE_REQUIRE_PRESERVE`)可保留产物,便于问题排查。 ### cache `false`/未设置时关闭缓存。传入 `true` 或配置对象可以打开持久化 + 内存缓存,详见 [加载流程与缓存策略](/packages/rolldown-require/cache.zh)。 ## 组合示例 ```ts import { bundleRequire } from 'rolldown-require' const { mod } = await bundleRequire({ cwd: process.cwd(), filepath: './tooling/config.ts', format: 'esm', tsconfig: './tsconfig.node.json', external: ['fsevents'], cache: { enabled: true, dir: './node_modules/.rolldown-require-cache', onEvent: e => console.log('[rolldown-require cache]', e), }, rolldownOptions: { input: { plugins: [ myCustomPlugin(), ], }, }, }) ``` 上述配置会: 1. 强制以 ESM 格式打包 `tooling/config.ts` 并使用指定的 `tsconfig` 解析路径。 2. 将 `fsevents` 标记为外部依赖,其余依赖遵循默认外部化策略。 3. 把临时产物缓存到指定目录,并通过 `onEvent` 输出命中/失效信息。 --- --- url: /wevu/vue-sfc/class-style.md --- # class/style 绑定能力 `weapp-vite + wevu` 在小程序侧对齐 Vue 3 的 `:class` / `:style` 绑定语法,支持字符串、数组、对象与嵌套组合,并会输出小程序可识别的字符串 class/style。 ```vue ``` ## 运行时模式 `class/style` 的运行时有两种实现,默认使用 JS: * **WXS 运行时**:编译产物中注入 `__weapp_vite.cls/style` helper(WXS 文件),模板中调用 `__weapp_vite.cls()` / `__weapp_vite.style()`。 * **JS 运行时**:编译期注入 `computed`,在逻辑层计算字符串 class/style。 配置项: ```ts // weapp-vite.config.ts export default defineConfig({ weapp: { vue: { template: { classStyleRuntime: 'js', // 'auto' | 'wxs' | 'js' classStyleWxsShared: true, // 是否复用 WXS helper }, }, }, }) ``` 默认 `js` 会在逻辑层注入 `computed` 来计算 class/style 字符串。 若配置为 `auto`,会在平台支持 WXS(`weapp.wxs !== false` 且 `outputExtensions.wxs` 存在)时启用 WXS,否则回退到 JS。若手动指定 `wxs` 但平台不支持,会回退到 JS 并输出中文告警。 `classStyleWxsShared` 默认开启:主包与非独立分包共享一份 `__weapp_vite_class_style.wxs`,独立分包会各自生成一份。关闭后会按页面目录生成,方便手动控制拷贝或排查问题。 ## 实现细节与限制 * **v-show 拼接**:`v-show` 会被拼接到 style(`display: none`),与 Vue 行为一致。 * **v-for 下 index 注入**:JS 运行时需要稳定索引,若模板未提供 `index`,编译器会自动注入 `wx:for-index="__wv_index_N"`。 * **对象 v-for**:JS 运行时会按 `Object.keys` 枚举顺序生成映射结果,确保索引与渲染一致。 * **表达式安全**:不使用 `eval/new Function/with`。表达式由编译器解析并重写标识符(包括作用域插槽 `__wvOwner` / `__wvSlotPropsData`),解析失败会输出中文告警并回退为空字符串。 > 建议:优先保持表达式为可解析的 JS/TS 表达式,避免非常规语法或依赖运行时动态生成的表达式字符串。 --- --- url: /packages/create-weapp-vite.md --- # create-weapp-vite `create-weapp-vite` 是官方脚手架,用于快速创建小程序工程,并在模板中对齐 `weapp-vite` / `wevu` 的版本组合。 ## 何时使用 * 你想快速初始化新项目 * 你希望通过模板统一团队目录结构与依赖版本 * 你要在 CI 或自动化脚本里做非交互创建 ## 快速开始 ```bash pnpm create weapp-vite # 或 npx create-weapp-vite ``` ### 非交互模式 ```bash pnpm create weapp-vite my-app wevu ``` 第二个参数是模板名,内部对应 `TemplateName` 枚举。 ## 可编程 API ```ts import { createProject, TemplateName } from 'create-weapp-vite' await createProject('my-app', TemplateName.wevu) ``` ## 可选模板(当前实现) * `default` * `wevu` * `tailwindcss` * `vant` * `tdesign` * `wevu-tdesign` * `wevu-retail` ## 与主文档的关系 * 工程创建后,日常开发请转到 [指引](/guide/) 与 [配置](/config/)。 --- --- url: /wevu/component.md --- # defineComponent(组件) `defineComponent()` 是对原生 `Component()` 的一层封装/增强:在组件 `lifetimes.created` 阶段初始化运行时并同步执行 `setup()`;`setup()` 返回对象会合并到组件实例,模板可直接使用。 > 注意:小程序在 `created` 阶段禁止调用 `setData`。因此 wevu 会在 `created` 阶段**缓冲**由响应式更新产生的 `setData`,并在首次安全时机(组件 `attached` / 页面 `onLoad`)再统一 flush。 此外,`defineComponent` 的 `data` **必须是函数**(与 Vue 3 一致,和小程序原生对象写法不同)。原因是原生小程序会在实例化时拷贝 `data` 对象以隔离实例;wevu 需要为每个实例创建独立的响应式 state/代理与快照 diff,因此要求返回新对象,避免共享引用污染与 diff 不稳定。 这页主要回答两类问题: * “我原来写 `Component({ ... })` 的字段,放到 `defineComponent({ ... })` 里怎么写?” * “组件/页面生命周期到底什么时候触发?为什么 created 里更新不生效?” ## 页面也用 defineComponent(统一模型) 在 wevu 里,页面与组件都通过 `Component()` 注册,这是统一模型的一部分: * 页面特有能力(滚动/分享/触底/下拉刷新等)通过 wevu 的页面 hooks 注册(详见 `/wevu/runtime`)。 * 小程序“按需派发”的页面事件,需要对应页面方法存在才会触发;配合 weapp-vite 构建时,通常由编译阶段自动补齐 `features.enableOnXxx`(详见 `/wevu/vue-sfc`)。 ## 原生 Component 选项在 wevu 的写法 结论先说:除了 `data / computed / methods / watch / setup / props` 这些由 wevu 接管的“增强选项”外,其余原生 `Component({ ... })` 的字段,都可以**直接写到** `defineComponent({ ... })` 里(wevu 会透传给原生 `Component()`)。 下面按你列出的字段逐项对照(类型定义可参考 `miniprogram-api-typings` 中的 `WechatMiniprogram.Component.*`)。 | 原生字段 | wevu 写法 | 说明 | | ------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `behaviors` | `defineComponent({ behaviors: [...] })` | 原样透传给 `Component()`。 | | `data` | `defineComponent({ data: () => ({ ... }) })` 或 `setup()` return 非函数字段 | `data` 必须是函数(Vue 3 一致);`setup()` 返回的非函数字段会进入运行时 state。原生小程序会拷贝对象避免实例间共享,而 wevu 需创建独立响应式 state/快照 diff。 | | `methods` | `defineComponent({ methods: { ... } })` 或 `setup()` return 函数 | `methods` 与 `setup()` 返回函数都会成为实例方法;同名时原生 `methods` 会在 wevu 包装后仍可执行(内部会先尝试运行 wevu 方法)。 | | `definitionFilter` | `defineComponent({ definitionFilter(defFields, arr) { ... } })` | 原生组件扩展能力,wevu 不改写,直接透传。 | | `export` | `defineComponent({ export() { return ... } })` 或 `setup(_, { expose }) { expose({ ... }) }` | 原生导出用于 `behavior: wx://component-export`:wevu 默认会把 `setup()` 里 `expose({ ... })` 的结果作为 `export()` 返回值,因此通常无需再手写 `export()`;若同时提供了 `export()`,会与 `expose()` 结果浅合并(`export()` 优先级更高)。 | | `externalClasses` | `defineComponent({ externalClasses: [...] })` | 原样透传。 | | `lifetimes` | 推荐用 `setup()` + wevu hooks;也可写 `defineComponent({ lifetimes: { ... } })` | `lifetimes.ready/detached/moved/error` 会被 wevu 包装以派发对应 hook,但你的原生回调仍会被调用;`lifetimes.created` 用于执行 wevu 的 `setup()`,并会在后续首次安全时机(`attached/onLoad`)flush 缓冲的 `setData`。 | | `observers` | 推荐用 `watch()`/`watchEffect()` 或 `defineComponent({ watch: { 'a.b': fn } })`;也可写 `defineComponent({ observers: { ... } })` | `observers` 是原生数据监听器(支持更复杂的表达式/通配),wevu 不改写,直接透传;wevu 的 `watch` 是基于运行时代理的路径监听(更像 Vue 的 `watch` 选项)。 | | `options` | `defineComponent({ options: { ... } })` | 原生 `ComponentOptions`(`multipleSlots/styleIsolation/pureDataPattern/virtualHost/...`)。注意:wevu 默认会把 `options.multipleSlots` 置为 `true`(用户显式传入则以用户为准)。 | | `pageLifetimes` | 推荐用 `onShow/onHide/onResize`;也可写 `defineComponent({ pageLifetimes: { ... } })` | `show/hide/resize` 会被 wevu 包装以派发 hook;其他字段按原生透传执行。 | | `properties` | 推荐:`props`;也可:`defineComponent({ properties: { ... } })` | `props` 会被 wevu 规范化为原生 `properties`;如果同时传了 `props` 与 `properties`,以 `props` 生成的 `properties` 为准。 | | `relations` | `defineComponent({ relations: { ... } })` | 原样透传。 | > 小提示:如果你在 wevu 里需要使用“原生 this”(例如访问 `this.setData`、`this.triggerEvent`、`selectComponent` 等),可以在 `setup(props, ctx)` 里通过 `ctx.instance` 访问小程序实例。 ## lifetimes / pageLifetimes 对应的 hooks > 说明:wevu 的 `onXXX()` 必须在 `setup()` **同步阶段**注册;由于 wevu 会在 `lifetimes.created` 内执行 `setup()`,因此你可以在 `setup()` 里注册所有 wevu hooks(包括 `onBeforeMount` 等)。 ### lifetimes(组件生命周期) | 小程序字段 | 回调名 | 对应 wevu hook | 说明 | | -------------------- | ---------- | -------------------------- | ------------------------------------------------------------------------------ | | `lifetimes.created` | `created` | `setup()` | wevu 在此阶段 mount 并执行 `setup()`(`setData` 会被延迟到 `attached/onLoad`) | | `lifetimes.attached` | `attached` | - | 组件进入节点树;wevu 会在此阶段 flush `created` 阶段缓冲的 `setData` | | `lifetimes.ready` | `ready` | `onReady` / `onMounted` | 组件就绪(内部做了重复触发去重) | | `lifetimes.moved` | `moved` | `onMoved` | 组件移动(例如在节点树中被移动) | | `lifetimes.detached` | `detached` | `onUnload` / `onUnmounted` | detached 时 teardown,并触发 `onUnload` | | `lifetimes.error` | `error` | `onError` | 组件错误(参数透传原生回调) | ### pageLifetimes(页面对组件的影响) | 小程序字段 | 回调名 | 对应 wevu hook | 说明 | | ---------------------- | -------- | -------------------------- | ------------------------------------ | | `pageLifetimes.show` | `show` | `onShow` / `onActivated` | 所在页面显示 | | `pageLifetimes.hide` | `hide` | `onHide` / `onDeactivated` | 所在页面隐藏 | | `pageLifetimes.resize` | `resize` | `onResize` | 所在页面尺寸变化(参数透传原生回调) | --- --- url: /config/js.md --- # JS 配置 {#js-config} `weapp-vite` 内置集成了 `vite-tsconfig-paths`,用于读取 `tsconfig.json/jsconfig.json` 的 `paths/baseUrl`,把别名映射到 Vite/Rolldown 流程中。 \[\[toc]] ## `weapp.tsconfigPaths` {#weapp-tsconfigpaths} * **类型**:`TsconfigPathsOptions | false` * **默认值**:`undefined`(按需自动启用) 启用规则: * 当 `tsconfig.json` 或 `jsconfig.json` **存在 `paths` 或 `baseUrl`** 时,会自动启用该插件; * 若你显式配置 `weapp.tsconfigPaths`,则以你的配置为准; * 传入 `false` 可完全禁用(适合没有别名需求、追求更快启动的项目)。 ```ts import { defineConfig } from 'weapp-vite/config' import type { PluginOptions } from 'vite-tsconfig-paths' const tsconfigOptions: PluginOptions = { projects: ['./tsconfig.base.json'], extensions: ['.ts', '.js', '.vue'], exclude: ['**/__tests__/**'], } export default defineConfig({ weapp: { tsconfigPaths: tsconfigOptions, }, }) ``` ### 与 `resolve.alias` 的关系 * `weapp.tsconfigPaths` 负责把 **tsconfig 的 paths/baseUrl** 转成 Vite alias。 * 你仍然可以在 `resolve.alias` 中补充或覆盖特定映射,两者可共存。 ```ts export default defineConfig({ resolve: { alias: { '@shared': '/packages/shared/src', }, }, weapp: { tsconfigPaths: { projects: ['./tsconfig.base.json'], }, }, }) ``` ### 常见问题 * **修改 `paths` 没生效?** 需要重启 `pnpm dev`,并确认 tsconfig 在 `projects` 列表内。 * **JSON 别名怎么配?** JSON 使用 `weapp.jsonAlias`(见 [JSON 配置](/config/json.md#weapp-jsonalias)),与 JS/TS 别名相互独立。 *** 更多 alias 实战与疑难排查,请参考 [路径别名指南](/guide/alias)。 --- --- url: /config/json.md --- # JSON 配置 {#json-config} `weapp-vite` 支持原生 `json/jsonc`,并提供 **JSON 别名** 与 **JSON 合并策略**,方便在 `app.json / page.json / component.json` 中复用配置。 \[\[toc]] ## `weapp.jsonAlias` {#weapp-jsonalias} * **类型**:`{ entries?: Record | { find: string | RegExp; replacement: string }[] }` * **默认值**:`undefined` * **作用范围**:**仅作用于 `usingComponents`**(其他字段保持原样)。 ```ts import path from 'node:path' import { defineConfig } from 'weapp-vite/config' export default defineConfig({ weapp: { jsonAlias: { entries: [ { find: '@/components/', replacement: path.resolve(import.meta.dirname, 'src/components/') }, { find: /^@icons\//, replacement: path.resolve(import.meta.dirname, 'src/assets/icons/') }, ], }, }, }) ``` JSON/JSONC 中可直接使用别名: ```jsonc { "usingComponents": { "nav-bar": "@/components/navigation-bar", "logo-icon": "@icons/logo" } } ``` 构建产物会转换为相对路径: ```json { "usingComponents": { "nav-bar": "../../components/navigation-bar", "logo-icon": "../../assets/icons/logo" } } ``` > \[!TIP] > `replacement` 推荐使用**绝对路径**,避免因工作目录变化导致解析失败。 ## `weapp.json.defaults` {#weapp-json-defaults} * **类型**:`{ app?: Record; page?: Record; component?: Record }` * **默认值**:`undefined` * **作用**:给 app/page/component JSON 注入统一默认值。 ```ts import { defineConfig } from 'weapp-vite/config' export default defineConfig({ weapp: { json: { defaults: { app: { entryPagePath: 'pages/index/index', }, page: { navigationStyle: 'custom', }, component: { styleIsolation: 'apply-shared', }, }, }, }, }) ``` 说明: * 默认值会在生成 `.json` 产物时合并。 * 页面/组件自身的 JSON(或 SFC `` / 宏)会覆盖默认值。 ## `weapp.json.mergeStrategy` {#weapp-json-merge-strategy} * **类型**:`'deep' | 'assign' | 'replace' | (target, source, ctx) => Record | void` * **默认值**:`'deep'` ```ts export default defineConfig({ weapp: { json: { mergeStrategy: 'assign', }, }, }) ``` 函数策略会收到上下文: ```ts export default defineConfig({ weapp: { json: { mergeStrategy(target, source, ctx) { if (ctx.kind === 'page' && ctx.stage === 'defaults') { return { ...target, ...source } } return { ...source, ...target } }, }, }, }) ``` 常见 `ctx.stage`:`defaults` / `json-block` / `auto-using-components` / `component-generics` / `macro` / `emit` / `merge-existing`。 *** 需要配置脚本别名?请前往 [JS 配置](/config/js.md#weapp-tsconfigpaths)。 --- --- url: /guide/json-intelli-sense.md --- # JSON 配置文件的智能提示 给 `app.json`、`page.json` 等文件加上 `$schema` 字段后,VS Code、微信开发者工具等编辑器就能提供: * 字段补全 * 取值提示 * 错误校验 这页提供现成的 Schema 地址,复制到文件开头即可用。 > \[!TIP] > 使用 weapp-vite 的脚手架(`pnpm g`)生成的页面/组件,默认已经包含对应的 `$schema`,你只需确认编辑器支持 JSON Schema 即可。工作区已在 `.vscode/settings.json` 里把在线地址映射到本地 `node_modules/@weapp-core/schematics/schemas/*.json`,既保留短链接又支持离线补全。 ## 如何添加 `$schema` 在目标配置文件的开头写入对应的 `$schema` 字段,例如: ```jsonc { "$schema": "https://vite.icebreaker.top/page.json", "navigationBarTitleText": "Home" } ``` `$schema` 只在编辑器里生效;构建阶段会自动剥离,不会影响最终产物。 ## 常用 Schema 列表 | 文件 | `$schema` 地址 | | ---------------- | ----------------------------------------------- | | 组件 `component.json` | `"https://vite.icebreaker.top/component.json"` | | 页面 `page.json` | `"https://vite.icebreaker.top/page.json"` | | 应用 `app.json` | `"https://vite.icebreaker.top/app.json"` | | `sitemap.json` | `"https://vite.icebreaker.top/sitemap.json"` | | `theme.json` | `"https://vite.icebreaker.top/theme.json"` | 直接复制右侧的地址粘贴即可。如果编辑器支持“悬浮后复制按钮”,也可以将整行复制下来放入文件中。VS Code 用户无需修改 `$schema`,工作区设置会自动将在线地址重定向到本地 Schema 文件。 ## 效果展示 ![vscode-json-intel](/vscode-json-intel.png) ## 常见问题 * **需要联网吗?** 默认 `$schema` 仍是在线地址,但 VS Code 会把它映射到本地 `node_modules/@weapp-core/schematics/schemas/*.json`,离线也能补全。如果换用其他编辑器,可手动做类似映射或直接改成本地路径。 * **生成器能输出本地 `$schema` 吗?** 可以,通过环境变量 `WEAPP_SCHEMA_BASE=file:///<你的项目绝对路径>/node_modules/@weapp-core/schematics/schemas` 让 `@weapp-core/schematics` 生成时使用本地 Schema(非必需,仅想让文件自带本地路径时启用)。 * **脚手架已生成 `$schema`,但仍没有提示?** 请确认编辑器启用了 JSON Schema 支持:VS Code 需安装官方小程序扩展或开启原生 JSON 支持;微信开发者工具需升级到较新的版本。 * **和 `json.ts` / `json.js` 配合?** 可以。在脚本文件里同样可以导出 `$schema` 字段,weapp-vite 在构建时会一并剥离。 --- --- url: /packages/rolldown-require/cache.md --- # Loading flow & cache > Language: English | [中文](/packages/rolldown-require/cache.zh) This page outlines how `bundleRequire` bundles, writes, and loads under the hood, plus practical cache settings. ## End-to-end flow 1. **Resolve entry**: turn `filepath` + `cwd` into an absolute path and infer `format` from the extension/`package.json.type` (overrideable). 2. **Bundle with rolldown**: * Fix `platform: 'node'`, `inlineDynamicImports: true`, `treeshake: false` to emit a single entry output and collect dependencies. * Inject `__dirname`/`__filename`/`import.meta.url` so runtime code sees the real source path. * Externalize most `node_modules` via the externalize-deps plugin, keep JSON inlined, and respect `module-sync` conditions. 3. **Execute the temp output**: * ESM: write a temp `.mjs`/`.cjs` or data URL, then `import()` it. * CJS: compile the source via a temporary `_require.extensions` hook. 4. **Return results**: provide `mod` plus `dependencies` (excluding the entry) for watching or debugging. ## Externalization & resolution * Resolution aligns with Vite/rolldown: same main-field priority and `tsconfig` path support (when enabled). * Node built-ins and `node:`/`npm:` namespace imports are marked external. * Dependencies inside nested `node_modules` under the entry directory are inlined to keep the temp output runnable. * JSON resources are always handled by rolldown (never externalized). ## Temp output control * Defaults to the nearest `node_modules/.rolldown-require`; falls back to the system temp dir. Filenames include a random hash to avoid contention. * Customize the path via `getOutputFile`; set `preserveTemporaryFile: true` to skip cleanup for direct inspection. * If all disk attempts fail for ESM, it falls back to a `data:` URL. ## Cache strategy Caching is off by default. Set `cache: true` or pass an object to enable persistent + in-memory cache: * **Location**: nearest `node_modules/.rolldown-require-cache`, else `os.tmpdir()/rolldown-require-cache`; override with `cache.dir`. * **Cache key**: entry path, `mtime`/`size`, `format`, `tsconfig` path, Node version, and a hash of `rolldownOptions`. * **Validation**: after a hit, each entry/dependency `mtime`/`size` is compared; any change invalidates the cache. * **Memory cache**: on by default (`cache.memory !== false`); returns the loaded module directly to avoid extra fs I/O. * **Reset & events**: * `cache.reset: true` removes prior code/meta before writing. * `cache.onEvent` receives `hit`/`miss`/`store`/`skip-invalid`; `skip-invalid.reason` may be `missing-entry`, `format-mismatch`, `stale-deps`, etc. Example: log cache events and set a custom directory ```ts await bundleRequire({ filepath: './config/vite.config.ts', cache: { enabled: true, dir: './.cache/rolldown-require', onEvent: (e) => { console.log(`[cache] ${e.type}`, e) }, }, }) ``` ## Debugging tips * Watch `dependencies` to decide when to call `bundleRequire` again. * Pair with `preserveTemporaryFile: true` to inspect temp code, or compare `*.code.mjs/cjs` directly inside the cache dir. * To debug suspicious hits, temporarily set `cache.reset: true` or disable cache entirely. * When the entry extension and `package.json.type` disagree, pass `format` explicitly to avoid Node/rolldown differences. --- --- url: /integration/miniprogram-computed.md --- # miniprogram-computed 集成 `miniprogram-computed` 的用法基本和官方一致。需要注意的是:为了确保构建产物里依赖齐全,建议把它的运行时依赖也显式安装到项目里(避免构建时被裁剪/遗漏)。 ## 安装 ```sh pnpm add miniprogram-computed fast-deep-equal rfdc ``` > \[!TIP] > `miniprogram-computed` 是运行时要用的库,更推荐放在 `dependencies` 而不是 `devDependencies`。 ## 使用方式 ```ts import { ComponentWithComputed } from 'miniprogram-computed' // js 中也可以使用 import { behavior as computedBehavior } from 'miniprogram-computed' ComponentWithComputed({ data: { a: 1, b: 1, }, computed: { sum(data) { // 注意: computed 函数中不能访问 this ,只有 data 对象可供访问 // 这个函数的返回值会被设置到 this.data.sum 字段中 return data.a + data.b }, }, methods: { onTap() { this.setData({ a: this.data.b, b: this.data.a + this.data.b, }) }, }, }) ``` 相关 `issues`: 1. [miniprogram-computed](https://github.com/weapp-vite/weapp-vite/issues/65) 2. [fast-deep-equal和rfdc可以放在peer-dependencies里面吗?](https://github.com/wechat-miniprogram/computed/issues/87) --- --- url: /guide/npm.md --- # npm 自动构建 `weapp-vite` 会尽量帮你把“npm 依赖怎么进小程序”这件事自动化:默认提供 **2 种自动策略**,以及 **1 个手动触发**命令。 ::: tip 配置速记 若需要关闭自动打包、切换缓存策略或为特定依赖覆写 Vite 库模式的构建选项,请在 `vite.config.ts` 中调整 [`weapp.npm`](/config/npm.md#weapp-npm)。 ::: ## 自动构建 自动构建时会发生两类事情(你不需要手动二选一,框架会按规则处理): 1. **把依赖构建到 `miniprogram_npm`**(适合保留 `require('xxx')` 的形式) 2. **把依赖内联进页面/组件脚本**(适合减少 npm 目录或处理非运行时依赖) ### 1. 构建到 `miniprogram_npm`(来自 `dependencies`) 你在 `package.json.dependencies` 里声明的依赖,会在构建时被打包成小程序可用的格式,并输出到 `project.config.json` 的 `miniprogramNpmDistDir` 目录下(也就是 `miniprogram_npm/`)。 ### 2. 内联到脚本产物(不在 `dependencies` 的依赖) 没有出现在 `package.json.dependencies` 里的依赖(例如写在 `devDependencies`、或来自 monorepo 更上层的依赖),在被 `import`/`require` 后会被构建器打包并**内联**到对应的页面/组件脚本里。 ### 详细解释 看一个最常见的例子: ```json { "dependencies": { "lodash": "^4.17.21" }, "devDependencies": { "lodash-es": "^4.17.21" } } ``` 其中 `lodash` 在 `dependencies`,`lodash-es` 在 `devDependencies`。在页面里分别引入它们时,weapp-vite 的处理方式不同: * **`dependencies` → 构建 `miniprogram_npm`**:产物保留 `require('lodash')`,依赖会被同步到 `miniprogram_npm`,保持最小化的页面代码。 ```js const lodash = require('lodash') Page({ data: { num0: lodash.add(1, 1), }, }) ``` * **`devDependencies` → 内联到页面脚本**:开发依赖会在构建时转成普通 JavaScript,并直接合并进页面入口,避免额外的 npm 目录。 ```js var add = /* lodash-es add 的实现主体 */ Page({ data: { num1: add(2, 2), }, }) ``` > \[!TIP] > 实际内联出来的代码会比示例长得多(可能包含工具函数等),但你不需要手动维护。只要把依赖放在合适的字段里,weapp-vite 会自动选择“进 `miniprogram_npm`”还是“直接内联”。 ### 怎么选(建议) * **运行时确实要用、并且希望复用的库**:放进 `dependencies`,让它进 `miniprogram_npm`。 * **仅开发/构建期使用的工具**:放进 `devDependencies`。 * **想减少 `miniprogram_npm`,接受包体变大**:也可以把运行时依赖放到非 `dependencies`,让它被内联(不推荐作为默认策略)。 ## 手动构建 执行命令 `weapp-vite npm` 会调用「微信开发者工具 → 工具 → 构建 npm」,手动构建 `miniprogram_npm`。 这相当于你在开发者工具里手动点了一遍“构建 npm”。 > `weapp-vite npm` 别名 `weapp-vite build:npm` / `weapp-vite build-npm` --- --- url: /config/npm.md --- # npm 配置 {#config-npm} `weapp-vite` 会自动把 **dependencies** 里的依赖构建成 `miniprogram_npm/`,而把 **devDependencies** 视为“仅构建期依赖”,直接内联进产物。 \[\[toc]] ## 依赖分类规则(默认) ```jsonc { "dependencies": { "lodash": "^4.17.21" }, "devDependencies": { "lodash-es": "^4.17.21" } } ``` * 引入 `lodash` ⇒ 产物保留 `require('lodash')`,并生成 `miniprogram_npm/lodash`。 * 引入 `lodash-es` ⇒ 相关实现会被打包并内联到页面/组件脚本。 > \[!TIP] > 建议团队统一约定:**运行时依赖放 `dependencies`**,构建期依赖放 `devDependencies`。 ## `weapp.npm` {#weapp-npm} * **类型**: ```ts { enable?: boolean cache?: boolean buildOptions?: (options: NpmBuildOptions, meta: { name: string; entry: InputOption }) => NpmBuildOptions | undefined } ``` * **默认值**:`{ enable: true, cache: true }` ```ts import { defineConfig } from 'weapp-vite/config' export default defineConfig({ weapp: { npm: { enable: true, cache: true, buildOptions(options, { name }) { if (name === 'lodash') { return { ...options, build: { ...options.build, target: 'es2018', }, } } return options }, }, }, }) ``` 字段说明: * `enable`:关闭后 **不会自动构建** `miniprogram_npm`。如果你的代码仍保留 `require('pkg')`,需要自行处理(如 devtools 构建 npm)。 * `cache`:是否启用 npm 构建缓存(缓存目录:`node_modules/weapp-vite/.cache/`)。 * `buildOptions`:为单个包覆写 Vite 库模式构建参数。 ## 手动构建命令 如需在命令行触发开发者工具的 npm 构建: ```json { "scripts": { "build:npm": "weapp-vite build:npm", "npm": "weapp-vite npm" } } ``` > \[!NOTE] > 该命令依赖 **weapp-ide-cli**,请确保微信开发者工具已开启“服务端口”。 ## 常见问题 * **npm 构建内容未更新**:尝试将 `cache` 设为 `false`,或清理 `node_modules/weapp-vite/.cache/`。 * **分包体积过大**:结合 `weapp.subPackages.*.dependencies` 裁剪独立分包依赖。 *** 下一步:需要分包能力?请前往 [分包配置](./subpackages.md)。 --- --- url: /packages/rolldown-require.md --- # rolldown-require Guide > Language: English | [中文](/packages/rolldown-require/index.zh) `rolldown-require` bundles and then loads config files of any flavor (TS / MJS / CJS / JSX, etc.) using `rolldown`, so CLI tools or Node scripts can execute them safely. Its API mirrors `bundle-require` while reusing `rolldown` resolution and plugins to stay close to `rolldown-vite` runtime behaviour. ## What problems it solves * **Cross-format loading**: infers entry module type automatically and works with ESM/CJS/TypeScript and more. * **Consistent resolution**: follows Vite/rolldown resolution and externalization (including `module-sync`), avoiding require/import mismatches. * **Source context preserved**: restores `__dirname`, `__filename`, and `import.meta.url` after bundling so temp output matches the source path. * **Observable dependencies**: returns the dependency list from bundling, ready for watchers or cache validation. * **Optional caching**: built-in persistent + in-memory cache to speed up repeated config loads. ## Install ```sh pnpm add rolldown-require rolldown -D # or npm / yarn / bun ``` > `rolldown` is a peer dependency and must be installed alongside. ## Quick start ```ts import { bundleRequire } from 'rolldown-require' const { mod, dependencies } = await bundleRequire({ filepath: './vite.config.ts', cache: true, // optional: enable cache for faster reruns }) // mod is the executed module (default export is unwrapped automatically) // dependencies can drive a watcher to decide when to re-bundle ``` `bundleRequire` will: 1. Infer ESM/CJS from the entry path (override with `format` if needed). 2. Bundle the entry with `rolldown`, externalizing most `node_modules` to match `rolldown-vite` behaviour. 3. Execute the temp output (ESM via `import()`, CJS via `require`) and return the module plus dependency list. ## How it differs from bundle-require * Uses `rolldown` as the bundler, matching the ecosystem and respecting conditional exports and module-sync flags. * Injects file-scope variables so changing the temp output path does not break `__dirname`/`__filename`. * Supports optional persistent and memory cache to reuse the same bundle across cold and warm starts. ## Next steps * See [API & options](/packages/rolldown-require/options) for defaults and scenarios. * Read [Loading flow & cache](/packages/rolldown-require/cache) for externalization details, temp files, and debugging tips. --- --- url: /packages/rolldown-require/index.zh.md --- # rolldown-require 使用指南 > 语言: [English](/packages/rolldown-require/) | 中文 `rolldown-require` 是基于 `rolldown` 的「打包再加载」工具,帮助 CLI 或 Node 脚本安全地执行任意格式的配置文件(`ts` / `mjs` / `cjs` / JSX 等)。API 与 `bundle-require` 保持相似,却复用了 `rolldown` 的解析与插件生态,更贴近 `rolldown-vite` 的运行时行为。 ## 它解决什么问题 * **跨格式加载**:自动判定入口模块类型,支持 ESM/CJS/TypeScript 等多种后缀。 * **一致的解析策略**:沿用 Vite/rolldown 的解析与外部化逻辑(含 `module-sync` 条件),避免 `require`/`import` 行为不一致。 * **源码上下文保持**:在打包后恢复 `__dirname`、`__filename`、`import.meta.url`,让临时产物与源文件路径一致。 * **依赖可观察**:返回打包时命中的依赖列表,可直接用于文件监听或缓存校验。 * **可选缓存**:内置持久化 + 进程内缓存,重复加载配置时可显著缩短启动时间。 ## 安装 ```sh pnpm add rolldown-require rolldown -D # 或 npm / yarn / bun 等等 ``` > `rolldown` 是 peer 依赖,需要一同安装。 ## 快速开始 ```ts import { bundleRequire } from 'rolldown-require' const { mod, dependencies } = await bundleRequire({ filepath: './vite.config.ts', cache: true, // 可选:启用缓存,重复执行更快 }) // mod 即为被加载的模块(默认导出会被解包) // dependencies 可用于 watcher,决定何时重新 bundle ``` `bundleRequire` 会: 1. 基于入口路径推断 ESM/CJS 格式,并支持通过 `format` 手动覆盖。 2. 使用 `rolldown` 打包入口文件,排除大多数 `node_modules` 依赖,保持解析结果与 `rolldown-vite` 一致。 3. 写入临时产物后执行(ESM 用 `import()`,CJS 用 `require`),最终返回模块与依赖列表。 ## 和 bundle-require 的区别 * 换用 `rolldown` 作为打包引擎,更贴合 rolldown 生态,也能利用它的条件导出、模块同步标记等能力。 * 内置文件作用域变量注入,避免因为临时产物路径改变而让 `__dirname`/`__filename` 失真。 * 支持可选的持久化/内存缓存,冷启动和多次加载都能复用同一份 bundle。 ## 下一步 * 查阅 [API 与选项说明](/packages/rolldown-require/options.zh) 理解各配置项的默认值与适用场景。 * 参考 [加载流程与缓存策略](/packages/rolldown-require/cache.zh) 了解外部化、临时文件与调试技巧。 --- --- url: /wevu/store.md --- # Store(状态管理) wevu 内置了类 Pinia 的 Store: * 用 `defineStore()` 定义 Store * 用 `useXxx()` 获取**单例**实例 * 用 `storeToRefs()` 解构 state/getter,避免丢失响应式 :::tip 导入约定 运行时 API 均从 `wevu` 主入口导入;不支持 `wevu/store` 子路径;`wevu/compiler` 仅供 weapp-vite 等编译侧工具使用(非稳定用户 API)。 ::: ## 导入与核心 API * `defineStore(id, setup | options)`:定义 Store,返回 `useXxx()` 获取单例实例。 * `storeToRefs(store)`:将 state/getter 包装为 `ref`,函数保持原样,解构不丢失响应式。 * `createStore()`:可选的插件入口;只有需要插件时才调用(见下文)。 ## Setup Store 示例(推荐) ```ts // stores/counter.ts import { computed, defineStore, ref } from 'wevu' export const useCounter = defineStore('counter', () => { const count = ref(0) const doubled = computed(() => count.value * 2) const inc = () => count.value++ return { count, doubled, inc } }) ``` 特点: * 你可以返回任意字段;函数会被当作 action(除 `$` 开头的保留字段)。 * `$patch/$subscribe/$onAction` 等基础 API 会自动合并进返回对象。 ## Options Store 示例 ```ts // stores/user.ts import { defineStore } from 'wevu' export const useUser = defineStore('user', { state: () => ({ name: '', age: 0 }), getters: { label(state) { return `${state.name}:${state.age}` }, canVote() { return this.age >= 18 }, }, actions: { grow() { this.age += 1 }, }, }) ``` ## 在页面/组件中使用 ```ts // pages/counter/index.ts import { defineComponent, storeToRefs } from 'wevu' import { useCounter } from '@/stores/counter' export default defineComponent({ setup() { const counter = useCounter() const { count, doubled } = storeToRefs(counter) counter.$subscribe((mutation) => { console.log('[counter]', mutation.type, mutation.storeId) }) return { count, doubled, inc: counter.inc } }, }) ``` 要点: * Store 是单例,在页面/组件 `setup` 里调用 `useXxx()` 即可复用。 * 解构 state/getter 请使用 `storeToRefs`,actions 可以直接解构。 ## 插件与订阅 * 默认无需插件即可使用;只有当你需要统一扩展所有 Store 时再调用 `createStore()` 并注册插件。 * 插件需在第一次 `useXxx()` 之前注册。`createStore()` 会记录为全局单例,之后创建的 Store 会自动应用插件(插件参数为 `{ store }`)。 ```ts import { createStore, defineStore } from 'wevu' const manager = createStore() manager.use(({ store }) => { store.$onAction((ctx) => { ctx.after(res => console.log('[after]', ctx.name, res)) ctx.onError(err => console.error('[error]', ctx.name, err)) }) store.$subscribe((mutation, state) => { console.log(`[${store.$id}]`, mutation.type, state) }) }) // 之后定义的任何 store 都会自动套用上述插件 export const useCart = defineStore('cart', { state: () => ({ items: [] as Array<{ id: string, count: number }> }), actions: { add(id: string, count = 1) { const found = this.items.find(i => i.id === id) if (found) { found.count += count } else { this.items.push({ id, count }) } }, }, }) ``` ## 持久化(storage)与初始化顺序 Store 是单例,适合承载登录态、用户偏好、缓存索引等“跨页面共享”的状态。常见诉求是把部分 state 持久化到本地存储(`wx.setStorageSync` / `wx.setStorage`)。 推荐做法: * 只持久化必要字段(避免把大对象/列表直接塞进 storage) * 统一在插件中处理(避免每个 store 手写重复逻辑) * 注意初始化顺序:在第一次 `useXxx()` 之前完成“读取 → 回填” 示例(简化版,仅展示形态): ```ts import { createStore, defineStore } from 'wevu' const manager = createStore() manager.use(({ store }) => { const key = `wevu:${store.$id}` try { const raw = wx.getStorageSync(key) if (raw) { store.$patch(JSON.parse(raw)) } } catch {} store.$subscribe((_mutation, state) => { try { wx.setStorageSync(key, JSON.stringify(state)) } catch {} }) }) export const usePrefs = defineStore('prefs', { state: () => ({ theme: 'light' as 'light' | 'dark' }), }) ``` :::warning 注意 上面示例直接读取/写入 `wx` 存储,必须在小程序运行时执行;如果你在 Node/Vitest 环境跑测试,需要 stub `wx` 或把持久化逻辑封装到可替换的 adapter。 ::: ## Store 实例 API * `$id`:当前 Store 的唯一标识。 * `$state`(Options Store):读取/替换整个 state;赋值会做浅合并并触发 `patch object`。 * `$patch(patch | fn)`:批量修改;Setup/Options Store 均可用,支持对象合并或回调方式。 * `$reset()`(Options Store):将 state 重置为初始值。 * `$subscribe((mutation, state) => void)`:订阅变更,返回取消订阅函数;`mutation.type` 为 `patch object` 或 `patch function`。 * `$onAction(({ name, store, args, after, onError }) => void)`:订阅 action 调用,支持成功/失败回调。 * `storeToRefs(store)`:将所有非函数字段转换为可写 `ref`,函数保持原样,避免解构丢失响应式。 ## TypeScript 与最佳实践 * Setup Store 会自动推导返回对象的类型;Options Store 可通过泛型精确声明 `state/getters/actions`。 * Store 文件按功能域组织(例如 `stores/user.ts`、`stores/cart.ts`),Store ID 使用小写单数。 * 避免直接解构 state:使用 `storeToRefs`;actions 可以直接解构。 * SSR/HMR/Devtools:wevu 面向小程序运行环境,暂未提供这些 Web 专属能力。 ## 常见问题 * 不要从 `wevu/store` 导入,所有 API 均在 `wevu` 主入口。 * 不需要为了使用 store 先调用 `createStore()`;仅在使用插件时才需要。 --- --- url: /integration/tailwindcss.md --- # Tailwindcss 集成 ## 直接使用模板(推荐) 如果你是新项目,直接用官方模板创建即可,模板已集成 Tailwind CSS: ```sh pnpm create weapp-vite ``` ## 手动集成 如果你要在现有项目里手动接入 Tailwind CSS,请按下面文档操作: * https://tw.icebreaker.top/docs/quick-start/native/install --- --- url: /integration/tdesign.md --- # tdesign-miniprogram 集成 在 `weapp-vite` 项目里接入 `tdesign-miniprogram` 的整体思路很简单: * 安装依赖 * 按官方文档完成基础配置 * (可选)开启 weapp-vite 的自动导入组件,让你不用手写 `usingComponents` 官方快速开始: ## 安装包 ```sh pnpm add tdesign-miniprogram ``` 如果你的 `tdesign-miniprogram` 版本 `>= 1.9.0`,还需要安装 `tslib`: ```sh pnpm add -D tslib ``` ## 构建成功后勾选 `将 JS 编译成 ES5` 在微信开发者工具的“详情”里勾选 `将 JS 编译成 ES5`(按官方建议配置即可)。 ## 修改 app.json 将 `app.json` 中的 `"style": "v2"` 移除(按官方要求)。 ## 修改 tsconfig.json (与官方文档不同) 如果你用 TypeScript 开发,建议在 `tsconfig.json` 里补上 `paths`,让编辑器能正确跳转到组件源码(避免路径报红): ```json { "paths": { "tdesign-miniprogram/*": ["./node_modules/tdesign-miniprogram/miniprogram_dist/*"] } } ``` ## 使用组件 以按钮组件为例:在页面/组件的 JSON 里引入对应组件,然后在 WXML 里使用。 ```json { "usingComponents": { "t-button": "tdesign-miniprogram/button/button" } } ``` WXML: ```html 按钮 ``` ## 自动导入组件 如果你不想手写 `usingComponents`,可以开启 weapp-vite 的自动导入组件:之后你在 WXML 里写 `` 这类标签,构建器会自动补齐注册信息。 ::: code-group ```ts [vite.config.ts] import { TDesignResolver } from 'weapp-vite/auto-import-components/resolvers' // [!code highlight] import { defineConfig } from 'weapp-vite/config' export default defineConfig({ weapp: { autoImportComponents: { resolvers: [TDesignResolver()], // [!code highlight] }, }, }) ``` ::: > \[!TIP] > 旧版本 weapp-vite 可能仍支持 `weapp.enhance.autoImportComponents`,但该写法已废弃,建议使用上面的顶层 `weapp.autoImportComponents`。 --- --- url: /dashboard.md --- --- --- url: /integration/vant.md --- # Vant Weapp 集成 官方文档: ## 安装 ```sh pnpm i @vant/weapp ``` ## 修改 app.json 将 `app.json` 中的 `"style": "v2"` 移除(按官方要求)。 ## 修改 tsconfig.json (与官方文档不同) 如果你用 TypeScript 开发,建议在 `tsconfig.json` 里补上 `paths`,让编辑器能正确跳转到 Vant 组件源码(避免路径报红): ```json { "paths": { "@vant/weapp/*": ["./node_modules/@vant/weapp/dist/*"] } } ``` ## 使用组件 以按钮组件为例:在页面/组件的 JSON 里引入对应组件,然后在 WXML 里使用。 ```json { "usingComponents": { "van-button": "@vant/weapp/button/index" } } ``` WXML: ```html 按钮 ``` ## 自动导入组件 如果你不想手写 `usingComponents`,可以开启 weapp-vite 的自动导入组件:之后你在 WXML 里写 ``,构建器会自动补齐注册信息。 ::: code-group ```ts [vite.config.ts] import { VantResolver } from 'weapp-vite/auto-import-components/resolvers' // [!code highlight] import { defineConfig } from 'weapp-vite/config' export default defineConfig({ weapp: { autoImportComponents: { resolvers: [VantResolver()], // [!code highlight] }, }, }) ``` ::: > \[!TIP] > 旧版本 weapp-vite 可能仍支持 `weapp.enhance.autoImportComponents`,但该写法已废弃,建议使用顶层 `weapp.autoImportComponents`。 --- --- url: /packages/vite-plugin-performance.md --- # vite-plugin-performance `vite-plugin-performance` 用于包装一个或多个 Vite 插件,并统计每个生命周期 Hook 的执行耗时。 ## 何时使用 * 你要定位构建慢点来自哪个插件/Hook * 你要为插件性能监控打点 * 你要在不改插件实现的前提下测量耗时 ## 安装 ```bash pnpm add -D vite-plugin-performance ``` ## 最小示例 ```ts import { defineConfig } from 'vite' import Inspect from 'vite-plugin-inspect' import { wrapPlugin } from 'vite-plugin-performance' export default defineConfig({ plugins: [ wrapPlugin(Inspect(), { threshold: 50, }), ], }) ``` ## 常用选项 * `hooks`: 指定要统计的 Hook,或传 `'all'` * `threshold`: 仅输出大于等于阈值的耗时 * `silent`: 关闭默认日志 * `logger`: 自定义日志输出 * `formatter`: 自定义日志格式 * `onHookExecution`: 每次统计完成后的回调 ## 相关导出 * `wrapPlugin` * `DEFAULT_PLUGIN_HOOKS` * `DEFAULT_THRESHOLD` --- --- url: /wevu/vue-sfc/vue3-vs-weapp-sfc.md --- # Vue 3 SFC vs weapp-vite SFC:写法对比 这篇文档聚焦“写法层面”的相同与不同:当你用 weapp-vite + wevu 写 `.vue`,哪些和 Vue 3 SFC 一样,哪些因为小程序编译/运行时而发生变化。 ## 相同点(写法层面) * **SFC 结构一致**:`