weapp-vite 7.5.0 → 7.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.md +14 -6
  2. package/THIRD_PARTY_NOTICES.md +60 -0
  3. package/bin/bootstrap.js +9 -4
  4. package/bin/bootstrap.test.ts +82 -1
  5. package/bin/nodeVersionWarning.js +17 -0
  6. package/bin/nodeVersionWarning.test.ts +30 -0
  7. package/dist/action-BD56SQh4.mjs +254 -0
  8. package/dist/action-CPtgEl6p.mjs +94 -0
  9. package/dist/action-le0bNff_.mjs +1102 -0
  10. package/dist/action-ytG5oFAw.mjs +138 -0
  11. package/dist/action-zmJrU8PC.mjs +245 -0
  12. package/dist/{analyze-ZJUvEdaY.mjs → analyze-DCZo-sJd.mjs} +4 -71
  13. package/dist/artifacts-TrTX9_jj.mjs +104 -0
  14. package/dist/assets-XyhpYtGl.mjs +630 -0
  15. package/dist/auto-import-components/resolvers.d.mts +1 -1
  16. package/dist/auto-import-components/resolvers.mjs +1 -1
  17. package/dist/auto-import-presets/wevu-router.d.mts +1 -1
  18. package/dist/auto-import-presets/wevu-router.mjs +1 -1
  19. package/dist/auto-import-presets/wevu.d.mts +1 -1
  20. package/dist/auto-import-presets/wevu.mjs +1 -1
  21. package/dist/auto-import-presets.d.mts +2 -2
  22. package/dist/auto-import-presets.mjs +2 -2
  23. package/dist/auto-routes.d.mts +1 -3
  24. package/dist/auto-routes.mjs +3 -4
  25. package/dist/{budget-BD7VqLCl.d.mts → budget-DTPngJU0.d.mts} +1 -10
  26. package/dist/budget-_Mu-4GKn.mjs +63 -0
  27. package/dist/builtProject-B145uOt5.mjs +534 -0
  28. package/dist/{package-7swhyLmf.mjs → classifier-CNTJOYQL.mjs} +5 -9
  29. package/dist/cli-acceptance.mjs +3 -4
  30. package/dist/cli.mjs +142 -4569
  31. package/dist/{config-DRGcCi3h.mjs → config-59ZWhCIf.mjs} +1 -2
  32. package/dist/{config-V0L-IAJf.d.mts → config-BNx2BODw.d.mts} +145 -150
  33. package/dist/config.d.mts +2 -2
  34. package/dist/config.mjs +3 -3
  35. package/dist/{constants-DEZdcsMn.mjs → constants-BOe8mgqL.mjs} +2 -4
  36. package/dist/{createCompilerContextInstance-DJH_P_nZ.mjs → createCompilerContextInstance-BXSdH2E8.mjs} +19930 -14019
  37. package/dist/{createContext-BqYzHhY9.mjs → createContext-W0TeXxbo.mjs} +7 -5
  38. package/dist/dashboard/analyze.d.mts +1 -7
  39. package/dist/dashboard/analyze.mjs +3 -1
  40. package/dist/dashboard/vite.d.mts +2 -4
  41. package/dist/dashboard/vite.mjs +1 -2
  42. package/dist/dashboard.d.mts +2 -2
  43. package/dist/dashboard.mjs +1733 -1
  44. package/dist/dashboardTransport-C9290QgS.mjs +15 -0
  45. package/dist/{dashboardViteBridge-Dy3nAD4m.mjs → dashboardViteBridge-B7QgQo94.mjs} +11 -11
  46. package/dist/{dev-fR5GiJRO.mjs → dev-D1QSExwk.mjs} +6 -3
  47. package/dist/devProvider-Bcvz5nu4.mjs +4966 -0
  48. package/dist/docs/README.md +14 -6
  49. package/dist/docs/ai-workflows.md +2 -0
  50. package/dist/docs/mcp.md +11 -1
  51. package/dist/docs/troubleshooting.md +16 -0
  52. package/dist/docs/vue-sfc.md +25 -2
  53. package/dist/docs/weapp-config.md +29 -0
  54. package/dist/docs/wevu-authoring.md +2 -0
  55. package/dist/doctor-worker.mjs +5 -5
  56. package/dist/doctor.d.mts +2 -8
  57. package/dist/doctor.mjs +24 -31
  58. package/dist/engine-Mnnm_ALP.mjs +53 -0
  59. package/dist/file-5eEfbK60.mjs +1 -0
  60. package/dist/{file-sC3jD7Fh.mjs → file-D8mp5GmB.mjs} +50 -26
  61. package/dist/{files-BqxFIPRp.mjs → files-Cy9jURJu.mjs} +1 -2
  62. package/dist/forwardConsole-D2Q0RIqc.mjs +509 -0
  63. package/dist/getInstance-BXNVH7sU.mjs +1 -0
  64. package/dist/{getInstance-DiGSzBNI.mjs → getInstance-DfNlbr-X.mjs} +2 -3
  65. package/dist/history-dKxzoHmN.mjs +774 -0
  66. package/dist/i18n.d.mts +1 -3
  67. package/dist/i18n.mjs +1 -2
  68. package/dist/{index-C9HjUX5c.d.mts → index-DIZJRrvK.d.mts} +1 -24
  69. package/dist/{index-CaXAtb9e.d.mts → index-SnaW3cvA.d.mts} +0 -12
  70. package/dist/index.d.mts +3 -7
  71. package/dist/index.mjs +6 -6
  72. package/dist/{json-BL8Dhhk6.mjs → json-Cvon2mw5.mjs} +1 -2
  73. package/dist/json.d.mts +1 -1
  74. package/dist/json.mjs +1 -1
  75. package/dist/lib-CJyMBzoe.mjs +140 -0
  76. package/dist/{lifecycle-BROTlwSL.mjs → lifecycle-CUo8PMQc.mjs} +123 -33
  77. package/dist/{loadConfig-C3BQhz7F.mjs → loadConfig-CKIdfW4o.mjs} +2 -3
  78. package/dist/loadConfig-D4WGJcYp.mjs +1 -0
  79. package/dist/logBuildAppFinish-DOBoof6S.mjs +54 -0
  80. package/dist/mcp-D88QvQgG.mjs +84 -0
  81. package/dist/{mcp-Cj8Maqo6.mjs → mcp-ovJgl1N9.mjs} +2 -4
  82. package/dist/mcp.d.mts +1 -3
  83. package/dist/mcp.mjs +1 -1
  84. package/dist/mcpClient-C8JzVZ46.mjs +283 -0
  85. package/dist/{processCleanup-B6KA30Zc.mjs → metadata-HlDKtlsu.mjs} +2 -21
  86. package/dist/nodeEnv-zq1EymWj.mjs +6 -0
  87. package/dist/openIde-QoYKhuuM.mjs +643 -0
  88. package/dist/options-Cz8vZ-0w.mjs +33 -0
  89. package/dist/{chunkStrategy-DRA5WpB-.mjs → package-DR62fAzP.mjs} +32 -31
  90. package/dist/path-E1OjBJAl.mjs +43 -0
  91. package/dist/{platform-CnkySBKz.mjs → platform-BiMpsZIb.mjs} +1 -2
  92. package/dist/{pluginHost--CaeyWpA.mjs → pluginHost-vn8Vty1J.mjs} +1 -2
  93. package/dist/processCleanup-DzB64WI8.mjs +18 -0
  94. package/dist/{protocol-vg8HGJ4n.mjs → protocol-HiSJRrSO.mjs} +43 -41
  95. package/dist/reader-wzPH_W8A.mjs +92 -0
  96. package/dist/realpathScope-DwlLaCk3.mjs +22 -0
  97. package/dist/report-PJVyo-UZ.mjs +105 -0
  98. package/dist/{path-doV773b7.mjs → resolvedId-DaxPh_yV.mjs} +5 -50
  99. package/dist/{resolvers-Dod-euqX.mjs → resolvers-CKYqmRD_.mjs} +10 -20
  100. package/dist/resolvers.d.mts +1 -1
  101. package/dist/resolvers.mjs +1 -1
  102. package/dist/{routes-C7fCmf92.d.mts → routes-DvAFX29h.d.mts} +0 -2
  103. package/dist/{runtime-Ee2HY6gR.d.mts → runtime-BL4RjBRa.d.mts} +1 -9
  104. package/dist/runtime-CKtMVERT.mjs +42 -0
  105. package/dist/{runtime-D6VCNhNY.mjs → runtime-DDUCb7pP.mjs} +4 -8
  106. package/dist/runtime.d.mts +1 -1
  107. package/dist/runtime.mjs +1 -1
  108. package/dist/schematics-DikfOjMD.mjs +90 -0
  109. package/dist/{session-PskhD-nZ.mjs → session-COrQJYif.mjs} +81 -21
  110. package/dist/test.d.mts +1 -3
  111. package/dist/test.mjs +54 -30
  112. package/dist/types-BK2EQ3Jm.d.mts +37 -0
  113. package/dist/{types-CgZn5X6j.d.mts → types-e2BMP9NU.d.mts} +1 -4
  114. package/dist/types.d.mts +4 -4
  115. package/dist/{upload-D4msblBf.mjs → upload-Chal5b3w.mjs} +118 -24
  116. package/dist/upload-worker.mjs +3 -5
  117. package/dist/{utils-CJSCgEj6.mjs → utils-CTGSZp4j.mjs} +72 -146
  118. package/dist/vite.d.mts +2 -4
  119. package/dist/vite.mjs +55 -21
  120. package/dist/volar.mjs +1 -2
  121. package/dist/{wevu-BQWUU7br.mjs → wevu-BaihCXO9.mjs} +1 -2
  122. package/dist/wevu-DTtSOyxB.d.mts +3 -0
  123. package/dist/{wevu-router-Dg1LnBlg.mjs → wevu-router-BIoxDbnu.mjs} +1 -2
  124. package/dist/wevu-router-CdWurGQ4.d.mts +3 -0
  125. package/dist/wxs-7V7MPzeW.mjs +1 -0
  126. package/dist/wxs-BdHHXltv.mjs +110 -0
  127. package/package.json +62 -53
  128. package/dist/dashboard-DvqF3Key.mjs +0 -1842
  129. package/dist/devProvider-BGBkw28J.mjs +0 -1050
  130. package/dist/file-DRb4eWqw.mjs +0 -1
  131. package/dist/getInstance-SiE6WZRh.mjs +0 -1
  132. package/dist/loadConfig-VGtBF4qm.mjs +0 -1
  133. package/dist/mcp-D3Yh24Cj.mjs +0 -529
  134. package/dist/wevu-C4KEC5kO.d.mts +0 -5
  135. package/dist/wevu-router-Cg2sIkIE.d.mts +0 -5
@@ -16,13 +16,15 @@
16
16
 
17
17
  ## Node.js 支持范围
18
18
 
19
- 框架及编译依赖链要求 `^22.18.0 || ^24.11.0 || >=26.0.0`:Node 22 至少 22.18.0、Node 24 至少 24.11.0,或 Node 26 及以上版本;不支持 Node 20、23、25。这是 Babel 8 与必需构建依赖支持范围的交集,不能通过关闭 engines 校验恢复旧版本支持。
19
+ 框架及编译依赖链的官方支持范围为 `^22.23.4 || ^24.22.1 || >=26.12.1`:Node 22 至少 22.23.4、Node 24 至少 24.22.1,或 Node 26.12.1 及以上版本。Node 20、23、25 及低于上述最低版本的环境不在官方支持范围内。
20
20
 
21
- 升级已有项目时先升级 Node.js,再重新安装依赖。CLI 会在加载编译依赖前检查实际 Node 版本;`prepare` 也会明确拒绝不支持的环境。直接通过 Vite 或程序 API 消费时同样需要遵守包的 `engines.node`。
21
+ CLI(含 `prepare`)与 Tailwind 集成发现实际 Node 版本超出该范围时,会提示升级并继续尝试执行,不会仅因版本号退出。旧版 Node 若缺少依赖所需的语法或 API,仍可能导致加载或执行失败;直接通过 Vite 或程序 API 消费时也受实际依赖兼容性限制。
22
22
 
23
- `create-weapp-vite` 自身依赖要求更高:Node 22 至少 22.22.2、Node 24 至少 24.15.0,或 Node 26 及以上版本。新建项目按脚手架要求选择 Node,不要将框架最低版本误认为脚手架最低版本。
23
+ 建议升级至受支持 LTS 分支的最新安全补丁版本,再安装或更新依赖。包的 `engines.node` 声明保持不变;如果项目或团队启用了严格 engines 校验,包管理器仍可能拒绝安装。
24
24
 
25
- 发布候选在构建环境中打包,再在独立临时消费者中以严格 engines/peer 校验安装;CI 覆盖 Linux、Windows、macOS 的 Node 22.18.0、24.11.0、26.0.0 及 22/24 当前补丁版本,验证原生和 SFC 构建、prepare 与公开类型。
25
+ `create-weapp-vite` 与框架采用相同的 Node 支持范围;Vite+ 模板要求 `^24.22.1 || >=26.12.1`。
26
+
27
+ 发布候选在构建环境中打包,再在独立临时消费者中以严格 engines/peer 校验安装;CI 覆盖 Linux、Windows、macOS 的 Node 22.23.4、24.22.1、26.12.1 及 22/24 当前补丁版本,验证原生和 SFC 构建、prepare 与公开类型。
26
28
 
27
29
  ## 普通 Vite 与 Vite+
28
30
 
@@ -98,7 +100,7 @@ Hub 的 `/__devframes/__mcp` 聚合端点保持关闭,但与独立模式一样
98
100
 
99
101
  `weapp-vite/dashboard` 是 Node 端共享核心;CLI 独立工作台与 Vite DevTools 复用同一个 `DevframeDefinition` 和 `@weapp-vite/dashboard` 面板。可选适配器位于 `weapp-vite/dashboard/vite`,使用官方 `createPluginFromDevframe`,不会由普通包入口或 CLI 自动加载。
100
102
 
101
- 接入方安装 `@weapp-vite/dashboard`、`@vitejs/devtools` 和 `@vitejs/devtools-kit`。当前接入按 Vite `8.3.0`、DevTools / Kit `0.7.6`、Devframe `1.1.0` 验证;Kit 是可选 peer,宿主依赖不进入小程序产物。
103
+ 接入方安装 `@weapp-vite/dashboard`、`@vitejs/devtools` 和 `@vitejs/devtools-kit`。当前接入使用 Vite `8.3.4`、DevTools / Kit `0.8.0`、Devframe `1.2.5`;Kit 是可选 peer,宿主依赖不进入小程序产物。
102
104
 
103
105
  ```ts
104
106
  import type { DevToolsConfig } from '@vitejs/devtools/config'
@@ -133,7 +135,7 @@ export function createDashboardHost(snapshot: DashboardAnalyzeSnapshot, roots: D
133
135
 
134
136
  每个控制器只同时挂载到一个逻辑宿主。适配器记录成功安装的 Vite 配置身份,并仅在该配置拥有的环境关闭时释放核心。成功重启将所有权移交给新配置,旧实例和未安装的失败候选的清理都不会误释放当前控制器;替换前的资源校验失败时,旧宿主仍可查询和更新。首次 setup 失败或 SDK 安装开始后的失败会释放核心,不承诺回滚部分安装。自行使用 `dashboard.definition` 对接其他 Devframe 宿主时,调用方必须负责最终关闭和启动失败时的 `dashboard.dispose()`。核心不启动服务器,也不拥有外部宿主的认证、Origin 或 MCP 策略;共享宿主不是只读沙箱。
135
137
 
136
- DevTools `0.7.6` 自身存在程序化重启边界:重复使用同一个 `DevTools()` 返回值时,旧实例关闭可能同时关闭新实例的 WebSocket;不安装 Dashboard 也能复现。应在每次重载的 Vite 配置中重新调用 `DevTools()`,不要把该 SDK 插件实例长期缓存在复用的 inline 配置里。上述重启验证使用重新创建的 SDK 宿主和保留的 Dashboard 控制器,不代表修复了上游传输问题。
138
+ DevTools 自身存在程序化重启边界:重复使用同一个 `DevTools()` 返回值时,旧实例关闭可能同时关闭新实例的 WebSocket;不安装 Dashboard 也能复现。应在每次重载的 Vite 配置中重新调用 `DevTools()`,不要把该 SDK 插件实例长期缓存在复用的 inline 配置里。上述重启验证使用重新创建的 SDK 宿主和保留的 Dashboard 控制器,不代表修复了上游传输问题。
137
139
 
138
140
  面板默认位于 `/__weapp-vite/`,自定义目录与应用 `base` 独立。前端复用宿主连接或从页面相对位置发现元数据,复制视图链接保留目录和查询参数但排除认证 fragment。适配器只在开发模式挂载,生产构建不要求可选面板资源,也不导出报告。以上入口仅用于 Node 开发 / 构建宿主,不应导入小程序 AppService。
139
141
 
@@ -590,3 +592,9 @@ const artifact = await buildTestArtifact({ cwd: process.cwd() })
590
592
  ## AI 改动验收
591
593
 
592
594
  通过 `wv accept --inspect --json` 检查环境;审阅配置后运行 `wv accept --trust --json`。现有 MCP 同时提供验收启动、状态、取消和报告工具,无需模型 Key。[接入指南](https://vite.weapp.dev/guide/acceptance)。独立 `weapp-agent` CLI 同仓维护并保留原命令。
595
+
596
+ ## 微信开发者工具多版本
597
+
598
+ 默认使用本机已安装的最新 Stable。用 `wv ide devtools list` 查看安装,`wv ide devtools add "<path-to-cli>"` 登记自定义位置;`wv open --devtools-channel=nightly` 或 `wv build --open --devtools-channel=rc --devtools-version=<version>` 明确选择测试版本。旧 `cliPath` 和路径环境变量继续固定安装,显式渠道/版本可覆盖继承配置。官方版本查询不阻塞默认选择,`--require-official-latest` 可启用严格检查。
599
+
600
+ 仓库包可用 `pnpm e2e:ide:matrix --targets=stable,rc,nightly --suite=ide-smoke` 串行测试已有安装。矩阵记录实际 IDE、基础库和资源清理结果;缺失、未登录、失败或未完成项返回非零。安装与登录由用户完成。同一账号切换安装后可能需要重新扫码;矩阵以非交互模式记录“需要重新登录”并继续其他版本,无需预备多个账号。完整 CLI、编程接口和 MCP 用法见 [weapp-ide-cli 文档](https://vite.weapp.dev/packages/weapp-ide-cli)。
@@ -28,6 +28,8 @@
28
28
 
29
29
  微信不同运行时版本不能统一假定存在 `queueMicrotask`。业务代码应通过共享 ESLint 配置统一接入 `@weapp-vite/eslint` 的 `miniProgramRuntimeRecommended`,模板不要单独增加 workspace 依赖;框架代码应使用显式兼容层,需要 request globals 时明确配置 `weapp.appPrelude.webRuntime`。
30
30
 
31
+ SSE 任务先读 [本地 Web Runtime 配置](./weapp-config.md#apppreludewebruntime),区分 Fetch 的项目级 `networkDefaults.request.enableChunked: true` 与 EventSource 自动分块。不要因存在 `onChunkReceived`、类型声明或 headless 通过就承诺微信流式兼容:还需真实宿主在响应结束前提供真实状态码,并验证服务端保持连接时页面已经显示首条消息。缺少能力时必须保留 `NotSupportedError`,不能假定 200 或静默退回缓冲。第三方解析器在模块初始化时读取 Streams 构造器的问题应检查最终 prelude 与 chunk 绑定;Wevu 清理应在同步 setup 中注册 `onUnload`。示例与边界见 [Web SSE 指南](https://vite.weapp.dev/guide/web-runtime-globals.html#复用-web-sse-写法)。
32
+
31
33
  ## Rust / Native 加速约束
32
34
 
33
35
  当任务涉及 `@weapp-vite/ast-native`、Rust 插件或 native AST 加速时,先把 JS 与 Rust 的通信次数当作主要性能约束之一。
package/dist/docs/mcp.md CHANGED
@@ -391,7 +391,7 @@ MCP 服务端做了以下约束:
391
391
 
392
392
  1. `wv mcp init <client>` 写入失败:先确认目标配置文件可写。
393
393
  2. `wv mcp doctor <client>` 失败:优先看配置文件里是否已经生成 `weapp-vite-*` server 条目。
394
- 3. `weapp-vite mcp` 启动失败:确认 Node 版本符合 `^22.18.0 || ^24.11.0 || >=26.0.0`。
394
+ 3. `weapp-vite mcp` 启动失败:先查看具体的依赖加载或执行错误。Node 版本超出 `^22.23.4 || ^24.22.1 || >=26.12.1` 时,CLI 会提示升级并继续执行;建议升级至受支持 LTS 分支的最新安全补丁版本,避免旧版 Node 缺少依赖所需的语法或 API。
395
395
  4. AI 看不到包内容:检查 `--workspace-root` 是否指向正确仓库根目录。
396
396
  5. 命令执行失败:确认命令在白名单中,并检查子目录权限与脚本名是否存在。
397
397
 
@@ -448,3 +448,13 @@ MCP 服务端做了以下约束:
448
448
  ## 验收任务
449
449
 
450
450
  现有服务提供 weapp_project_inspect、weapp_acceptance_start/status/cancel/report,无需模型 Key。验收与其他运行操作按工程互斥;任务使用独立日志订阅。HTTP 请求共享任务服务,断开单次请求不会丢失任务;服务关闭保存取消结果,重启不重放交互。
451
+
452
+ ## 微信开发者工具安装选择
453
+
454
+ `wv mcp` 和 `weapp mcp` 共用 `weapp-ide-cli` 的安装解析。默认本机最新 Stable,保留路径与旧全局 `cliPath` 固定;RC/nightly 需要明确选择。连接工具与相关 REST 请求支持 `cliPath`、`devtoolsChannel`、`devtoolsVersion`、`requireOfficialLatest`,同层选择必须一致;会话以实际安装身份隔离。
455
+
456
+ ```json
457
+ { "projectPath": "dist/dev/mp-weixin", "devtoolsChannel": "rc", "devtoolsVersion": "2.02.2608080" }
458
+ ```
459
+
460
+ 用 `wv ide devtools list --json` 查看实际渠道、版本和配置目录,用 `wv ide devtools add "<path-to-cli>"` 登记已有安装。`wv open --devtools-channel=nightly` 自动启动的后台 MCP 会继承具体 CLI 路径。官方查询默认仅作提示,`requireOfficialLatest: true` 才启用严格检查。登录保留在各安装实际配置目录中,不复制账号数据。
@@ -14,6 +14,14 @@
14
14
  weapp-vite prepare
15
15
  ```
16
16
 
17
+ ## classic IDE 配置租约阻塞 `dev`
18
+
19
+ 微信小程序的 classic 开发模式会暂时将 `project.private.config.json` 的 `setting.compileHotReLoad` 设为 `false`,并在其同级 `.weapp-vite/ide-classic-project.private.config.json` 保存租约和原始配置。正常退出会恢复该开关;进程被强杀或崩溃后,下次启动会在确认租约持有进程已退出时自动恢复并重新接管,同时保留用户对其他配置的修改。多平台项目以实际生成的 private 配置位置为准。
20
+
21
+ 另一个开发命令仍在运行时会报告占用信息。旧版无进程信息、内容损坏或无法确认进程状态的租约会保留并提示恢复,不会直接覆盖配置或删除记录。
22
+
23
+ 人工恢复前,先根据错误中的项目、进程和文件信息确认该项目的所有开发命令均已退出,并备份当前 private 配置和对应租约。参考租约中可读取的 `original` 恢复 `setting.compileHotReLoad` 的原值或原先不存在的状态,保留其他用户修改;原文缺失或损坏时,从自己的备份或版本记录确认原值。完成配置恢复后,仅将错误中指出的该项目 classic 租约及互斥记录移到备份位置,再运行 `weapp-vite dev`。无法确认进程状态或原配置时保留现场;不要删除整个 `.weapp-vite` 目录或其他项目、IDE 自动化会话的记录。
24
+
17
25
  ## AI 截图失败
18
26
 
19
27
  优先检查:
@@ -70,3 +78,11 @@ pnpm --filter weapp-vite build
70
78
  ## IDE 恢复与窗口保留
71
79
 
72
80
  打开项目、刷新索引或截图重试失败时,CLI 会保留现有开发者工具窗口,只重试目标项目连接;不会自动退出整个应用或按进程名终止宿主。`--no-open-recovery` 可禁用打开后的自动重试。需要真正关闭窗口时,请在 IDE 中明确选择目标项目;`wv close` 失败会返回非零退出码,不会升级为系统级退出。
81
+
82
+ ## 自动化连接清理与 CDP
83
+
84
+ 程序化使用 `@weapp-vite/miniprogram-automator` 或 `weapp-ide-cli` 时,`disconnect()` 返回 `Promise<void>`。同步清理回调应改为返回或 `await miniProgram.disconnect()`;调用时立即拒绝未完成 RPC 并停止订阅,Promise 等待 WebSocket 关闭。独立关闭最多等待 2 秒,超时表示关闭未确认,不能记录窗口、端口租约或快照已经释放。连接断开只影响本连接,受管窗口由持有 owner 的会话 `close()` 确认关闭;重连复用原窗口和 endpoint。
85
+
86
+ SDK 的公开 `send(method, params?, { timeout }?)` 可调用原始自动化协议。`CDP()` 提供 `enable`、`sendCommand(domain, method, params?, options?)`、`listProtocol` 和返回取消订阅函数的 `onEvent`;具体域和命令依赖目标 DevTools。headless 只适配 `Tool.getInfo`、`App.getCurrentPage/getPageStack/callFunction/callWxMethod`,CDP 和其他协议明确报告 `HEADLESS_PROTOCOL_UNSUPPORTED`,不构造真实 IDE 调试证据。
87
+
88
+ 触摸脚本使用标准 `changedTouches` 字段;旧 `changeTouches` 仍兼容,同时传入时以标准字段为准。启动失败诊断会附加已脱敏的 CLI 输出尾部,截断有明确标记;结合原始 `cause` 与 `operation` 阶段、预算和清理状态定位失败。
@@ -128,13 +128,36 @@ defineOptions({ behaviors: [i18n.behavior] })
128
128
 
129
129
  `weapp.vue.template.scopedSlotsRequireProps` 默认 `false`,普通插槽仍使用增强方案。设为 `true` 时,无 scoped props 的内容保留原生 `<slot>`。
130
130
 
131
- 微信目标下,编译后的 Wevu Provider 和 Leaf 使用默认 `setupLifecycle: 'attached'` 时,`<Provider><Leaf /></Provider>` 中的 Leaf 会在 setup 前同步关联最近的插槽承载者。Leaf 的 `inject()` 能取得 Provider 提供的原始对象、ref 和方法;点击调用 action 会更新双方共享状态。具名、普通节点包裹、嵌套和多实例场景遵循同一规则,卸载重建不会沿用旧上下文。
131
+ 原生插槽上下文协议由独立的 `weapp.vue.template.nativeSlotContext` 控制,默认 `false`,**仅在微信小程序目标(`weapp`)下生效**。7.5.0 引入的该能力改为显式开启:在微信目标下,需要时同时配置 `scopedSlotsRequireProps: true` 与 `nativeSlotContext: true`。未配置或显式关闭时,不生成协议标记、声明属性及插槽事件,也不为普通组件注册协议方法、observer 或清理回调;普通 `provide/inject` 与增强插槽语义不变。
132
+
133
+ 支付宝、抖音、百度和 Web 等其他目标即使配置 `nativeSlotContext: true`,也不会启用此协议或生成对应声明属性、事件接收与清理代码,不能获得这里描述的原生插槽最近 Provider 上下文继承。普通 `provide/inject` 和增强插槽仍遵循各平台既有语义。以下启用示例仅适用于微信小程序目标:
134
+
135
+ ```ts
136
+ import { defineConfig } from 'weapp-vite/config'
137
+
138
+ export default defineConfig({
139
+ weapp: {
140
+ vue: {
141
+ template: {
142
+ scopedSlotsRequireProps: true,
143
+ nativeSlotContext: true,
144
+ },
145
+ },
146
+ },
147
+ })
148
+ ```
149
+
150
+ 开启后,编译器会跳过可静态确认与上下文无关的纯展示组件、仅使用 `ref` 的组件及其纯容器,同时移除对应声明属性。直接或间接使用上下文的组件、插槽转发者,以及拥有相关子组件的中间 Wevu 组件仍参与协议;无法确认源码或动态调用行为时保守保留。判断依据包含组件和组合函数依赖,依赖变化时会重新编译引用方,不能仅按当前文件是否导入 `provide/inject` 裁剪。
151
+
152
+ 普通 `<script>` 中跨实例共享的对象/ref 及跨模块共享值不能仅凭初始值判定安全,异步函数和生成器也保守参与;每个实例新建的纯值仍可裁剪。循环解构的默认值和计算键保留实际执行语义,但不会延长 `inject()` 的有效实例上下文。显式组件注册覆盖自动导入时,生成路径和原生/Wevu 身份来自同一个注册结果;仅更新 JSON 不会丢失 barrel 等宿主解析依赖。
153
+
154
+ 显式开启后,微信目标下编译的 Wevu Provider 和 Leaf 使用默认 `setupLifecycle: 'attached'` 时,`<Provider><Leaf /></Provider>` 中的 Leaf 会在 setup 前同步关联最近的插槽承载者。Leaf 的 `inject()` 能取得 Provider 提供的原始对象、ref 和方法;点击调用 action 会更新双方共享状态。具名、普通节点包裹、嵌套和多实例场景遵循同一规则,卸载重建不会沿用旧上下文。
132
155
 
133
156
  这条协议不新增包装节点,不复制注入值,不修改原生 `Component.export` / `selectOwnerComponent()`。显式 `setupLifecycle: 'created'` 或 attached 前的公开实例恢复仍按原时机执行 setup,不提供该保证;未经 Wevu 编译的原生/第三方组件也不自动成为注入承载者。
134
157
 
135
158
  内层 Wevu Provider 即使使用过滤后的 `export()` / `expose()`,其普通模板子组件(含 Options API 局部注册别名)和原生插槽子组件仍共享内层上下文;外部选择器只看到该 Provider 的公开导出,内部父链不依赖公开导出对象。
136
159
 
137
- 已验证环境:微信 DevTools Stable `2.02.2608080`(基础库 `3.17.2`、`3.13.2`)和 `2.02.2608060`(基础库 `3.17.2`),并保留 mpcore 回归;这些结果不代替其他版本组合或真机验证。其他小程序平台及 Web 目标不启用此协议,构建时裁剪其声明属性、事件接收与清理代码,不能由微信或 headless 结果推断支持。`false` / augmented 和实际 scoped props 继续使用既有增强插槽路径。
160
+ 已验证环境:微信 DevTools Stable `2.02.2608080`(基础库 `3.17.2`、`3.13.2`)和 `2.02.2608060`(基础库 `3.17.2`),并保留 mpcore 回归;这些结果不代替其他版本组合或真机验证,也不能由微信或 headless 结果推断其他平台支持。`false` / augmented 和实际 scoped props 继续使用既有增强插槽路径。
138
161
 
139
162
  ## 具名插槽透传 wrapper
140
163
 
@@ -534,6 +534,35 @@ export default defineConfig({
534
534
 
535
535
  不要在 `srcRoot`、路由来源、分包边界都没确认前就先调 chunk 策略。
536
536
 
537
+ ### `appPrelude.webRuntime`
538
+
539
+ 小程序中的 Web API 兼容对象通过 `weapp.appPrelude.webRuntime` 注入;它与浏览器预览使用的 `weapp.web` 分别配置。`targets` 支持 Fetch、三个 Web Streams 构造器、`TextDecoderStream` 和 `EventSource` 等目标,并自动补齐相关依赖。Streams 构造器作为一组选择,保留可用的原生实现,否则使用 `web-streams-polyfill@4.3.0` ponyfill。
540
+
541
+ Fetch 网络增量交付需要项目级启用分块;普通缓冲请求继续可用:
542
+
543
+ ```ts
544
+ export default defineConfig({
545
+ weapp: {
546
+ appPrelude: {
547
+ webRuntime: {
548
+ enabled: true,
549
+ networkDefaults: { request: { enableChunked: true } },
550
+ },
551
+ },
552
+ },
553
+ })
554
+ ```
555
+
556
+ 业务可使用 `response.body.pipeThrough(new TextDecoderStream()).getReader()`,也可单独安装 `eventsource-parser` 接入其 `/stream` 解析器。构建器识别该依赖,并在第三方模块求值前提供构造器及 chunk 内局部绑定;不能等依赖初始化后才安装 `TransformStream`。
557
+
558
+ 全局 `EventSource` 自动开启分块,使用标准 GET 接口、事件监听和重连;POST、自定义鉴权头通过 Fetch,Fetch 本身不自动重试。`wevu/fetch` 复用 `@wevu/web-apis` 的同一实现;独立消费可使用 `@wevu/web-apis/streams` 和 `@wevu/web-apis/eventsource` 子入口。
559
+
560
+ 微信流式传输要求宿主支持 chunk 监听,并在响应结束前提供真实 HTTP 状态码。缺少能力时以 `NotSupportedError` 明确失败,不推断 HTTP 200、不退回完整响应缓冲;EventSource 在此情况下触发 error 并关闭。Response 返回后仍需处理 body 读取失败,`AbortSignal` 和 reader 取消会传递到底层请求。
561
+
562
+ 首版不模拟浏览器 Cookie/CORS,`EventSource` 的 `withCredentials: true` 不受支持;不提供流式上传、`Blob.stream()` 或网络级反压保证。慢消费和不读取的 clone 分支可能增加内存;不通过静默丢块限制队列。开发者工具、真机和其他平台必须分别验证,小程序域名白名单、TLS、后台运行与超时仍由宿主管理。
563
+
564
+ 完整目标与配置见 [Web Runtime 全局对象注入配置](https://vite.weapp.dev/config/web-runtime-globals.html),消费和卸载示例见 [复用 Web SSE 写法](https://vite.weapp.dev/guide/web-runtime-globals.html#复用-web-sse-写法)。
565
+
537
566
  ### `web`
538
567
 
539
568
  Web 重新扫描项目期间,已扫描 Vue SFC 的模板、样式与脚本继续使用上一次成功扫描的完整快照。扫描成功后才切换到新版本;扫描失败会保留旧快照并报告错误,修复后可继续更新。同一文件的正斜杠与反斜杠路径共用缓存,不会混入尚未发布的磁盘内容。
@@ -37,6 +37,8 @@ else if (import.meta.env.PLATFORM === 'web') {
37
37
 
38
38
  这类写法通常会导致时序错误或生命周期不触发。
39
39
 
40
+ Fetch SSE 与 EventSource 也由页面持有:在同步 `setup()` 中注册 `onUnload`,回调调用 `controller.abort()` 或 `source.close()`,不能等请求 `await` 后才注册。Response 返回后,body 流仍可能失败或被取消;reader 使用结束时释放锁,并在异常路径中止活动请求。不要将 controller、reader 或 EventSource 放进可序列化模板状态,也不要假定 `onHide` 等同于页面卸载。`wevu/fetch` 复用 `@wevu/web-apis`,项目配置和严格宿主边界见 [本地 Web Runtime 配置](./weapp-config.md#apppreludewebruntime),完整示例见 [Wevu Fetch SSE](https://vite.weapp.dev/wevu/fetch.html#sse-与响应流)。
41
+
40
42
  ## performance 预设与 setData 诊断
41
43
 
42
44
  `weapp.wevu.preset: 'performance'` 为 app/component 注入 `setData.strategy: 'patch'`、`suspendWhenHidden: true`、`diagnostics: 'fallback'` 和开发态 `highFrequencyWarning`,并默认启用 `autoSetDataPick`。`weapp.wevu.defaults` 的同名字段覆盖预设;`autoSetDataPick` 的显式布尔值也优先。
@@ -1,10 +1,11 @@
1
- import { t as createCompilerContext } from "./createContext-BqYzHhY9.mjs";
2
- import { r as resolveAnalyzeBudgets, t as terminateStaleSassEmbeddedProcess } from "./processCleanup-B6KA30Zc.mjs";
3
- import { r as readDoctorFiles } from "./files-BqxFIPRp.mjs";
1
+ import { t as createCompilerContext } from "./createContext-W0TeXxbo.mjs";
2
+ import { n as resolveAnalyzeBudgets } from "./metadata-HlDKtlsu.mjs";
3
+ import { r as readDoctorFiles } from "./files-Cy9jURJu.mjs";
4
+ import { t as terminateStaleSassEmbeddedProcess } from "./processCleanup-DzB64WI8.mjs";
4
5
  import process from "node:process";
5
6
  import path from "node:path";
6
7
  import { randomUUID } from "node:crypto";
7
- //#region src/doctor/buildWorker.ts
8
+ // src/doctor/buildWorker.ts
8
9
  process.once("message", async (options) => {
9
10
  try {
10
11
  const outputRoot = path.join(options.cwd, ".weapp-vite", "doctor", options.target, randomUUID());
@@ -55,5 +56,4 @@ process.once("message", async (options) => {
55
56
  process.exit(2);
56
57
  }
57
58
  });
58
- //#endregion
59
59
  export {};
package/dist/doctor.d.mts CHANGED
@@ -1,7 +1,6 @@
1
- import { Xn as MpPlatform } from "./config-V0L-IAJf.mjs";
2
- import { i as AnalyzeBudgetConfig } from "./budget-BD7VqLCl.mjs";
1
+ import { Yn as MpPlatform } from "./config-BNx2BODw.mjs";
2
+ import { i as AnalyzeBudgetConfig } from "./budget-DTPngJU0.mjs";
3
3
  import { OperationDiagnostics } from "@weapp-vite/miniprogram-automator";
4
- //#region src/doctor/types.d.ts
5
4
  type DoctorLayer = 'project' | 'source' | 'artifact' | 'runtime';
6
5
  interface DoctorCoverage {
7
6
  target: string;
@@ -133,12 +132,7 @@ interface DoctorAdapters {
133
132
  build: (options: DoctorOptions, target: MpPlatform) => Promise<DoctorArtifactSnapshot>;
134
133
  runtime: (cwd: string, target: MpPlatform, port?: number, options?: DoctorRuntimeProbeOptions) => Promise<DoctorRuntimeEvidence>;
135
134
  }
136
- //#endregion
137
- //#region src/doctor/report.d.ts
138
135
  export declare function formatDoctorReport(report: DoctorReport, format?: 'terminal' | 'json' | 'sarif'): string;
139
- //#endregion
140
- //#region src/doctor/index.d.ts
141
136
  /** 分层收集事实;静态路径永不调用配置加载器、构建或宿主连接。 */
142
137
  export declare function runDoctor(options?: DoctorOptions, adapters?: Partial<DoctorAdapters>): Promise<DoctorReport>;
143
- //#endregion
144
138
  export type { DoctorAdapters, DoctorArtifactSnapshot, DoctorCoverage, DoctorDiagnostic, DoctorFile, DoctorLayer, DoctorOptions, DoctorReport, DoctorRuntimeBundle, DoctorRuntimeEvidence, DoctorRuntimeFact, DoctorRuntimeProbeOptions, DoctorRuntimeStage };
package/dist/doctor.mjs CHANGED
@@ -1,7 +1,8 @@
1
- import { l as getProjectPlatformOptions, m as resolveMiniPlatform, o as getPlatformOutputExtensions } from "./platform-CnkySBKz.mjs";
2
- import { i as createAnalyzeBudgetCheck } from "./analyze-ZJUvEdaY.mjs";
3
- import { n as classifyPackage, t as version } from "./package-7swhyLmf.mjs";
4
- import { n as parseObject, r as readDoctorFiles, t as objectValue } from "./files-BqxFIPRp.mjs";
1
+ import { l as getProjectPlatformOptions, m as resolveMiniPlatform, o as getPlatformOutputExtensions } from "./platform-BiMpsZIb.mjs";
2
+ import { n as version } from "./package-DR62fAzP.mjs";
3
+ import { t as createAnalyzeBudgetCheck } from "./budget-_Mu-4GKn.mjs";
4
+ import { t as classifyPackage } from "./classifier-CNTJOYQL.mjs";
5
+ import { n as parseObject, r as readDoctorFiles, t as objectValue } from "./files-Cy9jURJu.mjs";
5
6
  import process from "node:process";
6
7
  import { constants } from "node:fs";
7
8
  import { fileURLToPath } from "node:url";
@@ -12,15 +13,15 @@ import { createHash } from "node:crypto";
12
13
  import { Parser } from "htmlparser2";
13
14
  import postcss from "postcss";
14
15
  import valueParser from "postcss-value-parser";
15
- import { fork } from "node:child_process";
16
16
  import { connectOpenedAutomator, queryWechatIdeLogin, resolveProjectAutomatorPort } from "weapp-ide-cli";
17
+ import { fork } from "node:child_process";
17
18
  import { createConnection } from "node:net";
18
19
  import { miniProgramRuntimePlugin, wevuCompatibilityPlugin } from "@weapp-vite/eslint";
19
20
  import tsParser from "@typescript-eslint/parser";
20
21
  import { Linter } from "eslint";
21
22
  import vueParser from "vue-eslint-parser";
22
23
  import { OperationLifecycle, classifyOperationError } from "@weapp-vite/miniprogram-automator";
23
- //#region src/doctor/report.ts
24
+ // src/doctor/report.ts
24
25
  function addDiagnostic(report, diagnostic) {
25
26
  const fingerprint = createHash("sha256").update(JSON.stringify([
26
27
  diagnostic.ruleId,
@@ -89,8 +90,7 @@ function formatDoctorReport(report, format = "terminal") {
89
90
  ...report.diagnostics.map((d) => `[${d.severity}] ${d.target} ${d.ruleId} ${d.location?.file ?? ""} ${d.message}\n ${d.suggestion}`)
90
91
  ].join("\n");
91
92
  }
92
- //#endregion
93
- //#region src/doctor/source.ts
93
+ // src/doctor/source.ts
94
94
  function checkDoctorScripts(report, target, files, layer) {
95
95
  const linter = new Linter();
96
96
  let incomplete = false;
@@ -174,8 +174,7 @@ function incompleteCoverage(report, target, layer, check, reason) {
174
174
  reason
175
175
  });
176
176
  }
177
- //#endregion
178
- //#region src/doctor/references.ts
177
+ // src/doctor/references.ts
179
178
  function checkArtifactReferences(report, target, snapshot, classifier) {
180
179
  const files = new Set(snapshot.files.map((file) => file.path));
181
180
  const ext = getPlatformOutputExtensions(target);
@@ -261,8 +260,7 @@ function checkArtifactReferences(report, target, snapshot, classifier) {
261
260
  reason: "覆盖静态脚本、模板和样式引用;动态/外部引用另记 incomplete。"
262
261
  });
263
262
  }
264
- //#endregion
265
- //#region src/doctor/artifact.ts
263
+ // src/doctor/artifact.ts
266
264
  function checkDoctorArtifact(report, target, snapshot) {
267
265
  const files = new Map(snapshot.files.map((file) => [file.path, file]));
268
266
  const ext = getPlatformOutputExtensions(target);
@@ -411,8 +409,7 @@ function checkDoctorArtifact(report, target, snapshot) {
411
409
  checkArtifactReferences(report, target, snapshot, classifier);
412
410
  checkDoctorScripts(report, target, snapshot.files, "artifact");
413
411
  }
414
- //#endregion
415
- //#region src/doctor/build.ts
412
+ // src/doctor/build.ts
416
413
  /** 将显式构建隔离到子进程,避免全局编译上下文和插件日志污染并发 API/JSON 输出。 */
417
414
  async function buildDoctorSnapshot(options, target) {
418
415
  const worker = path.join(path.dirname(fileURLToPath(import.meta.resolve("weapp-vite/package.json"))), "dist/doctor-worker.mjs");
@@ -453,8 +450,7 @@ async function buildDoctorSnapshot(options, target) {
453
450
  });
454
451
  });
455
452
  }
456
- //#endregion
457
- //#region src/doctor/runtimeProbes.ts
453
+ // src/doctor/runtimeProbes.ts
458
454
  /** 仅检查文件及平台执行条件,不执行 CLI 或项目配置。 */
459
455
  async function inspectDoctorCli(cliPath) {
460
456
  try {
@@ -513,8 +509,7 @@ function readDoctorRoute(value) {
513
509
  if (!route || route.startsWith("/") || route.length > 256 || route.includes("..") || /[\\:\s]/.test(route)) return;
514
510
  return route;
515
511
  }
516
- //#endregion
517
- //#region src/doctor/runtime.ts
512
+ // src/doctor/runtime.ts
518
513
  const stages = [
519
514
  "cli-executable",
520
515
  "service-listener",
@@ -636,16 +631,17 @@ async function probeDoctorRuntime(cwd, target, port, options = {}) {
636
631
  ]) record(stage, "not-run", "connection-unavailable");
637
632
  return evidence;
638
633
  }
639
- let released = false;
634
+ let releasing;
640
635
  const release = () => {
641
- if (released) return;
642
- released = true;
643
- try {
644
- session.disconnect();
636
+ releasing ??= (async () => {
637
+ await session.disconnect();
645
638
  record("session-release", "passed", "disconnected");
646
- } catch {
639
+ })().catch((error) => {
640
+ releasing = void 0;
647
641
  record("session-release", "failed", "disconnect-failed");
648
- }
642
+ throw error;
643
+ });
644
+ return releasing;
649
645
  };
650
646
  scope.own(release, "doctor-websocket");
651
647
  const checks = [];
@@ -673,7 +669,7 @@ async function probeDoctorRuntime(cwd, target, port, options = {}) {
673
669
  return true;
674
670
  })]);
675
671
  } finally {
676
- release();
672
+ await scope.step(release, { stage: "session-release" });
677
673
  }
678
674
  for (const stage of ["host-version", "sdk-version"]) if (facts.find((fact) => fact.stage === stage)?.status === "not-run") record(stage, "unknown", "tool-info-unavailable");
679
675
  evidence.checks = checks;
@@ -689,8 +685,7 @@ async function probeDoctorRuntime(cwd, target, port, options = {}) {
689
685
  finalized = true;
690
686
  }
691
687
  }
692
- //#endregion
693
- //#region src/doctor/runtimeReport.ts
688
+ // src/doctor/runtimeReport.ts
694
689
  const suggestions = {
695
690
  "cli-executable": "确认所选 CLI 是可执行文件;不会自动回退到其他安装。",
696
691
  "service-listener": "核对所选安装的服务端口与监听状态;TCP 可达不能证明监听者身份。",
@@ -740,8 +735,7 @@ function appendDoctorRuntimeEvidence(report, target, evidence) {
740
735
  });
741
736
  }
742
737
  }
743
- //#endregion
744
- //#region src/doctor/index.ts
738
+ // src/doctor/index.ts
745
739
  /** 分层收集事实;静态路径永不调用配置加载器、构建或宿主连接。 */
746
740
  async function runDoctor(options = {}, adapters = {}) {
747
741
  const cwd = path.resolve(options.cwd ?? process.cwd());
@@ -844,5 +838,4 @@ async function runDoctor(options = {}, adapters = {}) {
844
838
  });
845
839
  return finishReport(report);
846
840
  }
847
- //#endregion
848
841
  export { formatDoctorReport, runDoctor };
@@ -0,0 +1,53 @@
1
+ import { createRequire } from "node:module";
2
+ import { readFileSync } from "node:fs";
3
+ import { pathToFileURL } from "node:url";
4
+ // src/runtime/viteHost/engine.ts
5
+ function readIdentity(file) {
6
+ const value = JSON.parse(readFileSync(file, "utf8"));
7
+ if (!value || typeof value !== "object" || !("name" in value) || typeof value.name !== "string" || !("version" in value) || typeof value.version !== "string") throw new Error("[weapp-vite] Vite 宿主 package.json 缺少 name/version。");
8
+ return {
9
+ name: value.name,
10
+ version: value.version
11
+ };
12
+ }
13
+ /** 按宿主的真实导出解析引擎,不依赖扁平 node_modules 布局或版本号相等。 */
14
+ function resolveViteHost(importer = import.meta.url) {
15
+ const packagePath = createRequire(importer).resolve("vite/package.json");
16
+ const identity = readIdentity(packagePath);
17
+ const hostRequire = createRequire(packagePath);
18
+ if (identity.name === "@voidzero-dev/vite-plus-core") return {
19
+ kind: "vite-plus",
20
+ packagePath,
21
+ packageVersion: identity.version,
22
+ experimentalPath: hostRequire.resolve("@voidzero-dev/vite-plus-core/rolldown/experimental")
23
+ };
24
+ if (identity.name !== "vite") throw new Error(`[weapp-vite] 不支持的 Vite 宿主:${identity.name}@${identity.version}。`);
25
+ return {
26
+ kind: "vite",
27
+ packagePath,
28
+ packageVersion: identity.version,
29
+ experimentalPath: hostRequire.resolve("rolldown/experimental")
30
+ };
31
+ }
32
+ /** 加载与宿主绑定的引擎;缺失能力时保留原始错误,禁止回退到另一套引擎。 */
33
+ async function loadHostRolldown(importer) {
34
+ let identity;
35
+ try {
36
+ identity = resolveViteHost(importer);
37
+ const runtime = await import(pathToFileURL(identity.experimentalPath).href);
38
+ if (typeof runtime.dev !== "function" || typeof runtime.scan !== "function") throw new TypeError("Rolldown 缺少 dev/scan 能力");
39
+ return runtime;
40
+ } catch (cause) {
41
+ const host = identity ? `${identity.kind}@${identity.packageVersion}` : "vite";
42
+ throw new Error(`[weapp-vite] 无法加载 ${host} 配套的 Rolldown;请检查宿主依赖和 Vite+ alias 配置。`, { cause });
43
+ }
44
+ }
45
+ /** 原生输出写出也绑定宿主引擎,避免 Vite+ 额外加载包内另一套 Rolldown。 */
46
+ async function loadHostRolldownBuild(importer) {
47
+ const identity = resolveViteHost(importer);
48
+ const entry = createRequire(identity.packagePath).resolve(identity.kind === "vite-plus" ? "@voidzero-dev/vite-plus-core/rolldown" : "rolldown");
49
+ const runtime = await import(pathToFileURL(entry).href);
50
+ if (typeof runtime.rolldown !== "function") throw new TypeError(`[weapp-vite] ${identity.kind}@${identity.packageVersion} 缺少 Rolldown 原生写出能力。`);
51
+ return runtime;
52
+ }
53
+ export { loadHostRolldownBuild as n, loadHostRolldown as t };
@@ -0,0 +1 @@
1
+ export { t as extractConfigFromVue } from "./file-D8mp5GmB.mjs";
@@ -1,11 +1,12 @@
1
- import { a as supportedCssLangs, i as scriptExtensions, l as getSourceStyleExtensions, n as configExtensions, o as templateExtensions, p as isSourceTemplateExtension, s as vueExtensions, u as getSourceTemplateExtensions } from "./constants-DEZdcsMn.mjs";
1
+ import { a as supportedCssLangs, i as scriptExtensions, l as getSourceStyleExtensions, n as configExtensions, o as templateExtensions, p as isSourceTemplateExtension, s as vueExtensions, u as getSourceTemplateExtensions } from "./constants-BOe8mgqL.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import process from "node:process";
4
4
  import path from "pathe";
5
5
  import { fs } from "@weapp-core/shared/fs";
6
+ import { createBabelBackendLoader } from "@weapp-vite/ast/babelLoader";
6
7
  import { recursive } from "merge";
7
8
  import { parse } from "vue/compiler-sfc";
8
- //#region src/utils/file/autoRoutes.ts
9
+ // src/utils/file/autoRoutes.ts
9
10
  const nodeRequire = createRequire(import.meta.url);
10
11
  const AUTO_ROUTES_ID = "weapp-vite/auto-routes";
11
12
  const AUTO_ROUTES_VIRTUAL_ID = "virtual:weapp-vite-auto-routes";
@@ -54,7 +55,7 @@ function resolveAutoRoutesMacroImportPath() {
54
55
  }
55
56
  async function resolveAutoRoutesInlineSnapshot(context) {
56
57
  try {
57
- const compilerContext = context ?? (await import("./getInstance-SiE6WZRh.mjs")).getCompilerContext();
58
+ const compilerContext = context ?? (await import("./getInstance-BXNVH7sU.mjs")).getCompilerContext();
58
59
  const service = compilerContext.autoRoutesService;
59
60
  const reference = service?.getReference?.();
60
61
  if (!compilerContext.runtimeState.autoRoutes.loadingAppConfig) await service?.ensureFresh?.();
@@ -84,8 +85,7 @@ function inlineAutoRoutesImports(source, inlineRoutes) {
84
85
  return line;
85
86
  }).join("\n").replace(AUTO_ROUTES_DYNAMIC_IMPORT_RE, `Promise.resolve(${JSON.stringify(inlineRoutes)})`).replace(AUTO_ROUTES_SPECIFIER_RE, JSON.stringify(resolveAutoRoutesMacroImportPath()));
86
87
  }
87
- //#endregion
88
- //#region src/utils/file/entry.ts
88
+ // src/utils/file/entry.ts
89
89
  const pathExistsInFlight = /* @__PURE__ */ new Map();
90
90
  const JS_OR_TS_RE = /\.[jt]s$/;
91
91
  function pathExistsCached(filePath) {
@@ -158,8 +158,27 @@ async function touch(filename) {
158
158
  await fs.close(await fs.open(filename, "w"));
159
159
  }
160
160
  }
161
- //#endregion
162
- //#region src/utils/file/vueConfig.ts
161
+ // src/plugins/utils/sourceSnapshot/registry.ts
162
+ const snapshots = /* @__PURE__ */ new WeakMap();
163
+ function getCompilerSourceSnapshotView(owner) {
164
+ return snapshots.get(owner);
165
+ }
166
+ function replaceCompilerSourceSnapshotView(owner, snapshot) {
167
+ if (snapshot) snapshots.set(owner, snapshot);
168
+ else snapshots.delete(owner);
169
+ }
170
+ function getCompilerSourceSnapshot(owner) {
171
+ return snapshots.get(owner)?.sources;
172
+ }
173
+ function getCompilerSourceResolutions(owner) {
174
+ return snapshots.get(owner)?.resolutions;
175
+ }
176
+ /** 轻量消费者只读取已登记的代际;源码身份由登记方沿用原编译器规则解析。 */
177
+ function readCompilerSourceSnapshotInput(owner, id) {
178
+ return snapshots.get(owner)?.readSource(id);
179
+ }
180
+ // src/utils/file/vueConfig.ts
181
+ const loadVueCompiler = createBabelBackendLoader(() => import("wevu/compiler"));
163
182
  const vueConfigCache = /* @__PURE__ */ new Map();
164
183
  const contextConfigCaches = /* @__PURE__ */ new WeakMap();
165
184
  const configMtimeInFlight = /* @__PURE__ */ new Map();
@@ -194,13 +213,17 @@ async function isVueConfigCacheValid(vueFilePath, cache) {
194
213
  async function extractConfigFromVue(vueFilePath, options) {
195
214
  try {
196
215
  const context = options?.compilerContext;
216
+ const hasExplicitSource = options?.source !== void 0 || options?.readSource !== void 0;
217
+ let snapshotSource;
218
+ if (!hasExplicitSource && context?.configService) snapshotSource = readCompilerSourceSnapshotInput(context.configService, vueFilePath);
219
+ const useDiskCache = !hasExplicitSource && snapshotSource === void 0;
197
220
  const cache = context ? contextConfigCaches.get(context) ?? /* @__PURE__ */ new Map() : vueConfigCache;
198
221
  if (context) contextConfigCaches.set(context, cache);
199
- const cached = options?.force ? void 0 : cache.get(vueFilePath);
222
+ const cached = options?.force || !useDiskCache ? void 0 : cache.get(vueFilePath);
200
223
  let autoRoutesInline;
201
224
  if (cached?.autoRoutesSignature !== void 0) autoRoutesInline = await resolveAutoRoutesInlineSnapshot(context);
202
225
  if (cached && (cached.autoRoutesSignature === void 0 || cached.autoRoutesSignature === JSON.stringify(autoRoutesInline)) && await isVueConfigCacheValid(vueFilePath, cached)) return cached.config;
203
- const content = options?.source ?? (options?.readSource ? await options.readSource() : await fs.readFile(vueFilePath, "utf-8"));
226
+ const content = options?.source ?? (options?.readSource ? await options.readSource() : snapshotSource ?? await fs.readFile(vueFilePath, "utf-8"));
204
227
  if (content === void 0) return;
205
228
  const { descriptor, errors } = parse(content, { filename: vueFilePath });
206
229
  if (errors.length > 0) return;
@@ -218,7 +241,7 @@ async function extractConfigFromVue(vueFilePath, options) {
218
241
  } catch {}
219
242
  const setupContent = descriptor.scriptSetup?.content;
220
243
  if (typeof setupContent === "string" && JSON_MACRO_HINT_RE.test(setupContent)) {
221
- const { extractJsonMacroFromScriptSetup } = await import("wevu/compiler");
244
+ const { extractJsonMacroFromScriptSetup } = await loadVueCompiler();
222
245
  try {
223
246
  const preambleContent = descriptor.script?.content;
224
247
  autoRoutesInline = hasAutoRoutesMacroImport(setupContent) || preambleContent !== void 0 && hasAutoRoutesMacroImport(preambleContent) ? autoRoutesInline ?? await resolveAutoRoutesInlineSnapshot(options?.compilerContext) : void 0;
@@ -230,26 +253,27 @@ async function extractConfigFromVue(vueFilePath, options) {
230
253
  if (jsonBlocks.length === 0) throw error;
231
254
  }
232
255
  }
233
- const normalizedDependencies = [...new Set(macroDependencies.filter((dep) => dep && !NODE_MODULES_RE.test(dep)).map((dep) => path.normalize(dep)))];
234
- const dependencyMtimeMs = /* @__PURE__ */ new Map();
235
- await Promise.all(normalizedDependencies.map(async (dep) => {
236
- const mtime = await getMtimeCached(dep);
237
- if (mtime !== void 0) dependencyMtimeMs.set(dep, mtime);
238
- }));
239
- const fileMtimeMs = await getMtimeCached(vueFilePath);
240
256
  const hasConfig = Object.keys(mergedConfig).length > 0;
241
- cache.set(vueFilePath, {
242
- config: hasConfig ? mergedConfig : void 0,
243
- autoRoutesSignature: autoRoutesInline && JSON.stringify(autoRoutesInline),
244
- fileMtimeMs,
245
- dependencies: normalizedDependencies,
246
- dependencyMtimeMs
247
- });
257
+ if (useDiskCache) {
258
+ const normalizedDependencies = [...new Set(macroDependencies.filter((dep) => dep && !NODE_MODULES_RE.test(dep)).map((dep) => path.normalize(dep)))];
259
+ const dependencyMtimeMs = /* @__PURE__ */ new Map();
260
+ await Promise.all(normalizedDependencies.map(async (dep) => {
261
+ const mtime = await getMtimeCached(dep);
262
+ if (mtime !== void 0) dependencyMtimeMs.set(dep, mtime);
263
+ }));
264
+ const fileMtimeMs = await getMtimeCached(vueFilePath);
265
+ cache.set(vueFilePath, {
266
+ config: hasConfig ? mergedConfig : void 0,
267
+ autoRoutesSignature: autoRoutesInline && JSON.stringify(autoRoutesInline),
268
+ fileMtimeMs,
269
+ dependencies: normalizedDependencies,
270
+ dependencyMtimeMs
271
+ });
272
+ }
248
273
  return hasConfig ? mergedConfig : void 0;
249
274
  } catch (error) {
250
275
  if (process.env.__WEAPP_VITE_DEBUG_VUE_CONFIG__) console.error("[extractConfigFromVue] failed:", vueFilePath, error);
251
276
  return;
252
277
  }
253
278
  }
254
- //#endregion
255
- export { findJsonEntry as a, isJsOrTs as c, touch as d, getAutoRoutesMacroImportCandidates as f, resolveAutoRoutesInlineSnapshot as h, findJsEntry as i, isTemplate as l, inlineAutoRoutesImports as m, changeFileExtension as n, findTemplateEntry as o, hasAutoRoutesMacroImport as p, findCssEntry as r, findVueEntry as s, extractConfigFromVue as t, normalizeFileExtension as u };
279
+ export { hasAutoRoutesMacroImport as _, replaceCompilerSourceSnapshotView as a, findJsEntry as c, findVueEntry as d, isJsOrTs as f, getAutoRoutesMacroImportCandidates as g, touch as h, getCompilerSourceSnapshotView as i, findJsonEntry as l, normalizeFileExtension as m, getCompilerSourceResolutions as n, changeFileExtension as o, isTemplate as p, getCompilerSourceSnapshot as r, findCssEntry as s, extractConfigFromVue as t, findTemplateEntry as u, inlineAutoRoutesImports as v, resolveAutoRoutesInlineSnapshot as y };
@@ -1,7 +1,7 @@
1
1
  import path from "node:path";
2
2
  import { readFile, readdir } from "node:fs/promises";
3
3
  import { createHash } from "node:crypto";
4
- //#region src/doctor/files.ts
4
+ // src/doctor/files.ts
5
5
  const excluded = /* @__PURE__ */ new Set([
6
6
  "node_modules",
7
7
  ".git",
@@ -41,5 +41,4 @@ function parseObject(text) {
41
41
  if (!value) throw new Error("需要 JSON 对象");
42
42
  return value;
43
43
  }
44
- //#endregion
45
44
  export { parseObject as n, readDoctorFiles as r, objectValue as t };