[{"data":1,"prerenderedAt":4},["ShallowReactive",2],{"doc-\u002Fzh-Hans\u002Fcmtx\u002Fdev-guide\u002FDEV-002-esm-cjs-wasm-bundling-guide\u002F":3},"\u003Ch1 id=\"dev-002%3A-esm%2Fcjs%2Fwasm-%E6%89%93%E5%8C%85%E6%8C%87%E5%8D%97\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#dev-002%3A-esm%2Fcjs%2Fwasm-%E6%89%93%E5%8C%85%E6%8C%87%E5%8D%97\">#\u003C\u002Fa> DEV-002: ESM\u002FCJS\u002FWASM 打包指南\u003C\u002Fh1>\n\u003Ch2 id=\"1.-esm-%E4%B8%8E-cjs-%E6%A0%B8%E5%BF%83%E5%8C%BA%E5%88%AB\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#1.-esm-%E4%B8%8E-cjs-%E6%A0%B8%E5%BF%83%E5%8C%BA%E5%88%AB\">#\u003C\u002Fa> 1. ESM 与 CJS 核心区别\u003C\u002Fh2>\n\u003Ch3 id=\"1.1.-%E5%9F%BA%E6%9C%AC%E5%AF%B9%E6%AF%94\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#1.1.-%E5%9F%BA%E6%9C%AC%E5%AF%B9%E6%AF%94\">#\u003C\u002Fa> 1.1. 基本对比\u003C\u002Fh3>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>特性\u003C\u002Fth>\n\u003Cth>CommonJS (CJS)\u003C\u002Fth>\n\u003Cth>ES Modules (ESM)\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>导入语法\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>require()\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>import\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>导出语法\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>module.exports\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>export\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>文件标识\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>.cjs\u003C\u002Fcode> 或 \u003Ccode>package.json\u003C\u002Fcode> 无 \u003Ccode>&quot;type&quot;: &quot;module&quot;\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>.mjs\u003C\u002Fcode> 或 \u003Ccode>package.json\u003C\u002Fcode> 有 \u003Ccode>&quot;type&quot;: &quot;module&quot;\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>模块变量\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>__dirname\u003C\u002Fcode>, \u003Ccode>__filename\u003C\u002Fcode>, \u003Ccode>require\u003C\u002Fcode>, \u003Ccode>module\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>import.meta\u003C\u002Fcode>, \u003Ccode>globalThis._importMeta_.url\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>加载方式\u003C\u002Ftd>\n\u003Ctd>同步\u003C\u002Ftd>\n\u003Ctd>异步\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Node.js 版本\u003C\u002Ftd>\n\u003Ctd>所有版本\u003C\u002Ftd>\n\u003Ctd>v12.2+ (v14.13+ 稳定)\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Ch3 id=\"1.2.-node.js-22-%E4%B8%AD%E7%9A%84%E9%87%8D%E8%A6%81%E5%8F%98%E5%8C%96\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#1.2.-node.js-22-%E4%B8%AD%E7%9A%84%E9%87%8D%E8%A6%81%E5%8F%98%E5%8C%96\">#\u003C\u002Fa> 1.2. Node.js 22 中的重要变化\u003C\u002Fh3>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>特性\u003C\u002Fth>\n\u003Cth>状态\u003C\u002Fth>\n\u003Cth>说明\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Ccode>globalThis._importMeta_.dirname\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Stable\u003C\u002Ftd>\n\u003Ctd>Node.js 20.11+ 支持，获取当前文件所在目录\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>globalThis._importMeta_.filename\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Stable\u003C\u002Ftd>\n\u003Ctd>Node.js 20.11+ 支持，获取当前文件完整路径\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>require()\u003C\u002Fcode> 在 ESM 中\u003C\u002Ftd>\n\u003Ctd>Stable\u003C\u002Ftd>\n\u003Ctd>Node.js 22 稳定支持，通过 \u003Ccode>createRequire()\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>globalThis._importMeta_.resolve()\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Stable\u003C\u002Ftd>\n\u003Ctd>解析模块路径\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Chr>\n\u003Ch2 id=\"2.-%E6%A8%A1%E5%9D%97%E8%B7%AF%E5%BE%84%E8%8E%B7%E5%8F%96%E6%96%B9%E5%BC%8F%E5%AF%B9%E6%AF%94\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#2.-%E6%A8%A1%E5%9D%97%E8%B7%AF%E5%BE%84%E8%8E%B7%E5%8F%96%E6%96%B9%E5%BC%8F%E5%AF%B9%E6%AF%94\">#\u003C\u002Fa> 2. 模块路径获取方式对比\u003C\u002Fh2>\n\u003Ch3 id=\"2.1.-cjs-%E4%B8%AD%E7%9A%84%E8%B7%AF%E5%BE%84%E8%8E%B7%E5%8F%96\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#2.1.-cjs-%E4%B8%AD%E7%9A%84%E8%B7%AF%E5%BE%84%E8%8E%B7%E5%8F%96\">#\u003C\u002Fa> 2.1. CJS 中的路径获取\u003C\u002Fh3>\n\u003Cpre data-lang=\"javascript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F CJS 原生支持\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">console.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">log\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(__dirname); \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F 当前文件所在目录\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">console.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">log\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(__filename); \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F 当前文件完整路径\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3 id=\"2.2.-esm-%E4%B8%AD%E7%9A%84%E8%B7%AF%E5%BE%84%E8%8E%B7%E5%8F%96\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#2.2.-esm-%E4%B8%AD%E7%9A%84%E8%B7%AF%E5%BE%84%E8%8E%B7%E5%8F%96\">#\u003C\u002Fa> 2.2. ESM 中的路径获取\u003C\u002Fh3>\n\u003Cpre data-lang=\"javascript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 方式 1：使用 globalThis._importMeta_.url（所有 Node.js ESM 版本）\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { fileURLToPath } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"node:url\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { dirname } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"node:path\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> __filename\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> fileURLToPath\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">meta\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">.url);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> __dirname\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> dirname\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(__filename);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 方式 2：使用 globalThis._importMeta_.dirname（Node.js 20.11+）\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { dirname } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"node:path\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> __dirname\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">meta\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">.dirname; \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F 直接获取目录\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3 id=\"2.3.-%E8%BF%81%E7%A7%BB%E6%96%B9%E5%90%91%E5%AF%B9%E6%AF%94\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#2.3.-%E8%BF%81%E7%A7%BB%E6%96%B9%E5%90%91%E5%AF%B9%E6%AF%94\">#\u003C\u002Fa> 2.3. 迁移方向对比\u003C\u002Fh3>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>方向\u003C\u002Fth>\n\u003Cth>难度\u003C\u002Fth>\n\u003Cth>说明\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Cstrong>CJS → ESM\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd>低到中\u003C\u002Ftd>\n\u003Ctd>用 \u003Ccode>globalThis._importMeta_.dirname\u003C\u002Fcode> 或 \u003Ccode>fileURLToPath(globalThis._importMeta_.url)\u003C\u002Fcode> 替代 \u003Ccode>__dirname\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Cstrong>ESM → CJS\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd>中到高\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>import.meta\u003C\u002Fcode> 在 CJS 不可用，需要构建时转换\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Ch3 id=\"2.4.-%E5%85%B3%E9%94%AE%E7%BB%93%E8%AE%BA\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#2.4.-%E5%85%B3%E9%94%AE%E7%BB%93%E8%AE%BA\">#\u003C\u002Fa> 2.4. 关键结论\u003C\u002Fh3>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>把 CJS 的 \u003Ccode>__dirname\u003C\u002Fcode> 迁移到 ESM 通常更容易；反向把 ESM 的 \u003Ccode>import.meta\u003C\u002Fcode> 在纯 CJS 里原生可用则不可行，需要构建时转换或把模块改为 ESM。\u003C\u002Fstrong>\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Chr>\n\u003Ch2 id=\"3.-tsdown-shims-%E6%9C%BA%E5%88%B6\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#3.-tsdown-shims-%E6%9C%BA%E5%88%B6\">#\u003C\u002Fa> 3. tsdown Shims 机制\u003C\u002Fh2>\n\u003Ch3 id=\"3.1.-%E4%BB%80%E4%B9%88%E6%98%AF-shims\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#3.1.-%E4%BB%80%E4%B9%88%E6%98%AF-shims\">#\u003C\u002Fa> 3.1. 什么是 Shims\u003C\u002Fh3>\n\u003Cp>Shims 是构建工具自动注入的兼容代码，让源码在不同输出格式（CJS\u002FESM）中都能正确运行。\u003C\u002Fp>\n\u003Ch3 id=\"3.2.-tsdown-shims%3A-true-%E7%9A%84%E8%A1%8C%E4%B8%BA\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#3.2.-tsdown-shims%3A-true-%E7%9A%84%E8%A1%8C%E4%B8%BA\">#\u003C\u002Fa> 3.2. tsdown \u003Ccode>shims: true\u003C\u002Fcode> 的行为\u003C\u002Fh3>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>输出格式\u003C\u002Fth>\n\u003Cth>自动注入的 shim\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Cstrong>CJS\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>globalThis._importMeta_.url\u003C\u002Fcode>、\u003Ccode>globalThis._importMeta_.dirname\u003C\u002Fcode>、\u003Ccode>globalThis._importMeta_.filename\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Cstrong>ESM\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>__dirname\u003C\u002Fcode>、\u003Ccode>__filename\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Ch3 id=\"3.3.-%E4%BD%BF%E7%94%A8%E7%A4%BA%E4%BE%8B\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#3.3.-%E4%BD%BF%E7%94%A8%E7%A4%BA%E4%BE%8B\">#\u003C\u002Fa> 3.3. 使用示例\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>源码（统一使用 \u003Ccode>__dirname\u003C\u002Fcode>）：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { join } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"node:path\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">function\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> locateWasmFile\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">()\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">:\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> string\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> |\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> null\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    try\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">        \u002F\u002F shims: true 时，__dirname 在 ESM 和 CJS 中都可用\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">        \u002F\u002F - CJS: 原生 __dirname\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">        \u002F\u002F - ESM: tsdown 自动注入 shim\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        return\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> join\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(__dirname, \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"..\u002Fpkg\u002Fcmtx_fpe_wasm_bg.wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">catch\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        return\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> null\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cstrong>tsdown 配置：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { defineConfig } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"tsdown\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> default\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> defineConfig\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    entry: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"src\u002Findex.ts\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    format: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"esm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"cjs\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">], \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F 双格式输出\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    shims: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">true\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F 启用 shims\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    platform: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"node\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    target: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"node22\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3 id=\"3.4.-shims-%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#3.4.-shims-%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9\">#\u003C\u002Fa> 3.4. Shims 注意事项\u003C\u002Fh3>\n\u003Col>\n\u003Cli>\u003Cstrong>不要手动检测 \u003Ccode>import.meta\u003C\u002Fcode>\u003C\u002Fstrong>：如 \u003Ccode>typeof import.meta !== &quot;undefined&quot;\u003C\u002Fcode>，这会导致构建警告\u003C\u002Fli>\n\u003Cli>\u003Cstrong>优先使用 \u003Ccode>__dirname\u003C\u002Fcode>\u003C\u002Fstrong>：因为 CJS 原生支持，ESM 有 shim\u003C\u002Fli>\n\u003Cli>\u003Cstrong>shims 会自动 tree-shake\u003C\u002Fstrong>：未使用的 shim 不会增加体积\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Chr>\n\u003Ch2 id=\"4.-typescript-%E9%85%8D%E7%BD%AE%E6%A0%87%E5%87%86%E5%8C%96\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#4.-typescript-%E9%85%8D%E7%BD%AE%E6%A0%87%E5%87%86%E5%8C%96\">#\u003C\u002Fa> 4. TypeScript 配置标准化\u003C\u002Fh2>\n\u003Ch3 id=\"4.1.-tsdown-%E5%8F%96%E4%BB%A3-tsc-%E4%BD%9C%E4%B8%BA%E7%94%9F%E4%BA%A7%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#4.1.-tsdown-%E5%8F%96%E4%BB%A3-tsc-%E4%BD%9C%E4%B8%BA%E7%94%9F%E4%BA%A7%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7\">#\u003C\u002Fa> 4.1. tsdown 取代 tsc 作为生产构建工具\u003C\u002Fh3>\n\u003Cp>CMTX 项目中，\u003Ccode>tsdown\u003C\u002Fcode> 已取代 \u003Ccode>tsc\u003C\u002Fcode> 作为生产构建工具。\u003Ccode>tsdown\u003C\u002Fcode> 基于 Rolldown（Rust 实现的打包器），提供更快的构建速度和更完整的打包能力（shims、copy、dts 生成等）。\u003C\u002Fp>\n\u003Ch3 id=\"4.2.-tsconfig.json-%E7%9A%84%E5%AE%9A%E4%BD%8D\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#4.2.-tsconfig.json-%E7%9A%84%E5%AE%9A%E4%BD%8D\">#\u003C\u002Fa> 4.2. tsconfig.json 的定位\u003C\u002Fh3>\n\u003Cp>\u003Ccode>tsconfig.json\u003C\u002Fcode> 在 CMTX 项目中\u003Cstrong>仅用于类型检查\u003C\u002Fstrong>（\u003Ccode>tsc --noEmit\u003C\u002Fcode>），不参与生产构建。生产构建完全由 \u003Ccode>tsdown.config.ts\u003C\u002Fcode> 控制。\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>用途\u003C\u002Fth>\n\u003Cth>工具\u003C\u002Fth>\n\u003Cth>配置文件\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>类型检查\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>tsc --noEmit\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>tsconfig.json\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>生产构建\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>tsdown\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>tsdown.config.ts\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Ch3 id=\"4.3.-%E5%85%B3%E9%94%AE%E7%BA%A6%E6%9D%9F\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#4.3.-%E5%85%B3%E9%94%AE%E7%BA%A6%E6%9D%9F\">#\u003C\u002Fa> 4.3. 关键约束\u003C\u002Fh3>\n\u003Cul>\n\u003Cli>\u003Ccode>tsconfig.json\u003C\u002Fcode> 中的 \u003Ccode>module\u003C\u002Fcode>\u002F\u003Ccode>moduleResolution\u003C\u002Fcode> 设置仍需与 ESM\u002FCJS 输出格式保持一致（使用 \u003Ccode>NodeNext\u003C\u002Fcode>）\u003C\u002Fli>\n\u003Cli>\u003Ccode>tsdown.config.ts\u003C\u002Fcode> 中的 \u003Ccode>format\u003C\u002Fcode>、\u003Ccode>shims\u003C\u002Fcode>、\u003Ccode>platform\u003C\u002Fcode>、\u003Ccode>target\u003C\u002Fcode> 等选项决定最终输出\u003C\u002Fli>\n\u003Cli>不要通过 \u003Ccode>tsconfig.json\u003C\u002Fcode> 的 \u003Ccode>outDir\u003C\u002Fcode>\u002F\u003Ccode>declaration\u003C\u002Fcode> 来控制构建输出，这些由 tsdown 管理\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Chr>\n\u003Ch2 id=\"5.-wasm-%E5%A4%84%E7%90%86%E6%96%B9%E5%BC%8F\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#5.-wasm-%E5%A4%84%E7%90%86%E6%96%B9%E5%BC%8F\">#\u003C\u002Fa> 5. WASM 处理方式\u003C\u002Fh2>\n\u003Ch3 id=\"5.1.-tsdown-%E4%B8%AD%E7%9A%84-wasm-%E6%94%AF%E6%8C%81\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#5.1.-tsdown-%E4%B8%AD%E7%9A%84-wasm-%E6%94%AF%E6%8C%81\">#\u003C\u002Fa> 5.1. tsdown 中的 WASM 支持\u003C\u002Fh3>\n\u003Cp>tsdown 本身不内建 WASM 处理，可通过以下两种方式：\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>copy + 运行时加载\u003C\u002Fstrong>（CMTX 当前采用的方案）：通过 \u003Ccode>copy\u003C\u002Fcode> 配置将 WASM 文件复制到 \u003Ccode>dist\u002F\u003C\u002Fcode>，运行时使用 \u003Ccode>readFileSync\u003C\u002Fcode> 加载\u003C\u002Fli>\n\u003Cli>\u003Cstrong>rolldown-plugin-wasm\u003C\u002Fstrong>（CMTX 曾尝试，已弃用）：自动内联或复制 WASM，但不支持自定义输出路径\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch3 id=\"5.2.-%E4%B8%A4%E7%A7%8D-wasm-%E5%A4%84%E7%90%86%E6%96%B9%E5%BC%8F%E5%AF%B9%E6%AF%94\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#5.2.-%E4%B8%A4%E7%A7%8D-wasm-%E5%A4%84%E7%90%86%E6%96%B9%E5%BC%8F%E5%AF%B9%E6%AF%94\">#\u003C\u002Fa> 5.2. 两种 WASM 处理方式对比\u003C\u002Fh3>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>方式\u003C\u002Fth>\n\u003Cth>优点\u003C\u002Fth>\n\u003Cth>缺点\u003C\u002Fth>\n\u003Cth>适用场景\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Cstrong>copy + 运行时加载\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd>灵活、路径完全可控\u003C\u002Ftd>\n\u003Ctd>需手动处理路径\u003C\u002Ftd>\n\u003Ctd>所有场景（推荐）\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Cstrong>rolldown-plugin-wasm\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd>自动处理路径、支持内联\u003C\u002Ftd>\n\u003Ctd>不支持自定义输出路径\u003C\u002Ftd>\n\u003Ctd>简单场景，无路径定制需求\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Ch3 id=\"5.3.-%E6%8E%A8%E8%8D%90%E6%96%B9%E6%A1%88%EF%BC%9Acopy-%2B-%E8%BF%90%E8%A1%8C%E6%97%B6%E5%8A%A0%E8%BD%BD\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#5.3.-%E6%8E%A8%E8%8D%90%E6%96%B9%E6%A1%88%EF%BC%9Acopy-%2B-%E8%BF%90%E8%A1%8C%E6%97%B6%E5%8A%A0%E8%BD%BD\">#\u003C\u002Fa> 5.3. 推荐方案：copy + 运行时加载\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>配置示例：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { defineConfig } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"tsdown\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> default\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> defineConfig\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    entry: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"src\u002Findex.ts\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    format: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"esm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"cjs\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    shims: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">true\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    copy: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"pkg\u002Fcmtx_fpe_wasm_bg.wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cstrong>源码中加载：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { readFileSync } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"node:fs\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { join } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"node:path\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">function\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> locateWasmFile\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">()\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">:\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> string\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> |\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> null\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    try\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        return\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> join\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(__dirname, \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"..\u002Fpkg\u002Fcmtx_fpe_wasm_bg.wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">catch\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        return\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> null\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> async\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> function\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> loadWASM\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">()\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">:\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> Promise\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">&#x3C;\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">void\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> wasmPath\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> locateWasmFile\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    if\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> (wasmPath) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> wasmBuffer\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> readFileSync\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(wasmPath);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        await\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> init\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">({ module_or_path: wasmBuffer });\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3 id=\"5.4.-wasm-%E5%A4%84%E7%90%86%E5%86%B3%E7%AD%96\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#5.4.-wasm-%E5%A4%84%E7%90%86%E5%86%B3%E7%AD%96\">#\u003C\u002Fa> 5.4. WASM 处理决策\u003C\u002Fh3>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>场景\u003C\u002Fth>\n\u003Cth>推荐方式\u003C\u002Fth>\n\u003Cth>原因\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>VS Code 扩展（CJS 单输出）\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>copy + 手动加载\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>路径完全可控，避免插件路径解析缺陷\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>双格式库（CJS + ESM）\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>copy + 运行时加载\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>保持 WASM 文件独立，灵活加载\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>浏览器应用\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>copy + 运行时加载\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>使用 \u003Ccode>fetch()\u003C\u002Fcode> 加载 WASM 文件\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Ch3 id=\"5.5.-cmtx-wasm-%E6%9E%B6%E6%9E%84\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#5.5.-cmtx-wasm-%E6%9E%B6%E6%9E%84\">#\u003C\u002Fa> 5.5. CMTX WASM 架构\u003C\u002Fh3>\n\u003Cp>CMTX 项目包含两个 WASM 包，均使用 Rust + wasm-pack 构建：\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>包名\u003C\u002Fth>\n\u003Cth>功能\u003C\u002Fth>\n\u003Cth>构建工具\u003C\u002Fth>\n\u003Cth>输出\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Ccode>@cmtx\u002Ffpe-wasm\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>FF1 格式保留加密\u003C\u002Ftd>\n\u003Ctd>Rust + wasm-pack\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>pkg\u002Fcmtx_fpe_wasm_bg.wasm\u003C\u002Fcode> (~58KB)\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>@cmtx\u002Fautocorrect-wasm\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Autocorrect 拼写检查\u003C\u002Ftd>\n\u003Ctd>Rust + wasm-pack\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>pkg\u002Fautocorrect_wasm_bg.wasm\u003C\u002Fcode> (~2.5MB)\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp>\u003Cstrong>tsdown \u003Ccode>copy\u003C\u002Fcode> 配置\u003C\u002Fstrong>：两个包均通过 tsdown 的 \u003Ccode>copy\u003C\u002Fcode> 选项将 WASM 文件复制到 \u003Ccode>dist\u002F\u003C\u002Fcode> 目录：\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F fpe-wasm\u002Ftsdown.config.ts\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> default\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> defineConfig\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    copy: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"pkg\u002Fcmtx_fpe_wasm_bg.wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F autocorrect-wasm\u002Ftsdown.config.ts\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> default\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> defineConfig\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    copy: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"pkg\u002Fautocorrect_wasm_bg.wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cstrong>VS Code 扩展特殊处理\u003C\u002Fstrong>：VS Code 扩展不能依赖 WASM 包的自动加载（bundled 代码中 \u003Ccode>__dirname\u003C\u002Fcode> 指向错误路径），必须在 \u003Ccode>extension.ts\u003C\u002Fcode> 中手动检测生产\u002F开发模式路径并加载 WASM 文件（详见第 7.3 节）。\u003C\u002Fp>\n\u003Chr>\n\u003Ch2 id=\"6.-%E5%B8%B8%E8%A7%81%E8%AD%A6%E5%91%8A%E4%B8%8E%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#6.-%E5%B8%B8%E8%A7%81%E8%AD%A6%E5%91%8A%E4%B8%8E%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88\">#\u003C\u002Fa> 6. 常见警告与解决方案\u003C\u002Fh2>\n\u003Ch3 id=\"6.1.-empty_import_meta-%E8%AD%A6%E5%91%8A\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#6.1.-empty_import_meta-%E8%AD%A6%E5%91%8A\">#\u003C\u002Fa> 6.1. EMPTY_IMPORT_META 警告\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>警告信息：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre>\u003Ccode>Warning: `import.meta` may not be a valid syntax with the `cjs` output format.\nThis `import.meta` will be replaced with an empty object (`{}`) automatically.\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cstrong>原因：\u003C\u002Fstrong> 源码中直接使用了 \u003Ccode>import.meta\u003C\u002Fcode> 语法，当输出 CJS 时，tsdown 会发出警告。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>错误做法：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 不要这样写\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">if\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> (\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">typeof\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">meta\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> !==\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"undefined\"\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> &#x26;&#x26;\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">meta\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">.url) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">    \u002F\u002F ...\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cstrong>正确做法：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 使用 __dirname（tsdown shims 会自动处理）\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { join } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"node:path\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">function\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> locateFile\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">()\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">:\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> string\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> |\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> null\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    return\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> join\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(__dirname, \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"..\u002Fpath\u002Fto\u002Ffile\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cstrong>配置：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> default\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> defineConfig\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    shims: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">true\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F 启用 shims\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3 id=\"6.2.-ineffective_dynamic_import-%E8%AD%A6%E5%91%8A\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#6.2.-ineffective_dynamic_import-%E8%AD%A6%E5%91%8A\">#\u003C\u002Fa> 6.2. INEFFECTIVE_DYNAMIC_IMPORT 警告\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>警告信息：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre>\u003Ccode>Warning: X is dynamically imported by Y but also statically imported by Z,\ndynamic import will not move module into another chunk.\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cstrong>原因：\u003C\u002Fstrong> 同一个模块同时被静态和动态导入，导致动态导入无法将模块分离到独立 chunk。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>错误做法：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F index.ts - 静态导出\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { builtInRules } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \".\u002Frules\u002Fbuilt-in\u002Findex.js\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F engine.ts - 动态导入\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\".\u002Fbuilt-in\u002Findex.js\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">).\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">then\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(({ \u003C\u002Fspan>\u003Cspan style=\"color:#E36209\">builtInRules\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> }) \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">=>\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">    \u002F\u002F ...\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cstrong>正确做法：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F rules\u002Findex.ts - 提供异步加载函数\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> async\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> function\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> loadBuiltInRules\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">() {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">builtInRules\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">=\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\".\u002Fbuilt-in\u002Findex.js\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    return\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> builtInRules;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F engine.ts - 使用异步加载\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> async\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> function\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> createDefaultRuleEngine\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">() {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> engine\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> createRuleEngine\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> builtInRules\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> loadBuiltInRules\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    engine.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">registerMany\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(builtInRules);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    return\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> engine;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3 id=\"6.3.-missing_export-%E8%AD%A6%E5%91%8A\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#6.3.-missing_export-%E8%AD%A6%E5%91%8A\">#\u003C\u002Fa> 6.3. MISSING_EXPORT 警告\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>警告信息：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre>\u003Ccode>Warning: &quot;builtInRules&quot; is not exported by &quot;src\u002Frules\u002Findex.ts&quot;.\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cstrong>原因：\u003C\u002Fstrong> 尝试导入一个未导出的成员。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>解决方案：\u003C\u002Fstrong> 确保所有导入的成员都已正确导出，或改为使用异步加载函数。\u003C\u002Fp>\n\u003Chr>\n\u003Ch2 id=\"7.-%E9%A1%B9%E7%9B%AE%E9%85%8D%E7%BD%AE%E7%A4%BA%E4%BE%8B\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#7.-%E9%A1%B9%E7%9B%AE%E9%85%8D%E7%BD%AE%E7%A4%BA%E4%BE%8B\">#\u003C\u002Fa> 7. 项目配置示例\u003C\u002Fh2>\n\u003Ch3 id=\"7.1.-fpe-wasm-%E5%8C%85%EF%BC%88%E5%8F%8C%E6%A0%BC%E5%BC%8F%E8%BE%93%E5%87%BA%E5%BA%93%EF%BC%89\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#7.1.-fpe-wasm-%E5%8C%85%EF%BC%88%E5%8F%8C%E6%A0%BC%E5%BC%8F%E8%BE%93%E5%87%BA%E5%BA%93%EF%BC%89\">#\u003C\u002Fa> 7.1. fpe-wasm 包（双格式输出库）\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>package.json：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"json\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">{\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#005CC5\">    \"name\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"@cmtx\u002Ffpe-wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#005CC5\">    \"type\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"module\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#005CC5\">    \"main\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\".\u002Fdist\u002Findex.cjs\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#005CC5\">    \"module\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\".\u002Fdist\u002Findex.mjs\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#005CC5\">    \"exports\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">: {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#005CC5\">        \".\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">: {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#005CC5\">            \"types\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\".\u002Fdist\u002Findex.d.ts\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#005CC5\">            \"import\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\".\u002Fdist\u002Findex.mjs\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#005CC5\">            \"require\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\".\u002Fdist\u002Findex.cjs\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">        }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    },\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#005CC5\">    \"files\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"dist\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"README.md\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"CHANGELOG.md\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">]\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cstrong>tsdown.config.ts：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { defineConfig } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"tsdown\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> default\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> defineConfig\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    entry: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"src\u002Findex.ts\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    format: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"esm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"cjs\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    dts: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">true\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    clean: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">true\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    platform: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"node\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    target: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"node22\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    shims: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">true\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F 启用 shims 支持 __dirname\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    copy: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"pkg\u002Fcmtx_fpe_wasm_bg.wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">], \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F 复制 WASM 文件到 dist\u002Fpkg\u002F\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cstrong>源码（src\u002Findex.ts）：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { readFileSync, existsSync } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"node:fs\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { join } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"node:path\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">function\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> locateWasmFile\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">()\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">:\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> string\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> |\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> null\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    try\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">        \u002F\u002F shims: true 时，__dirname 在 ESM 和 CJS 中都可用\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> wasmPath\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> join\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(__dirname, \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"..\u002Fpkg\u002Fcmtx_fpe_wasm_bg.wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        if\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> (\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">existsSync\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(wasmPath)) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">            return\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> wasmPath;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">        }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        return\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> null\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">catch\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        return\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> null\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cstrong>输出结构：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre>\u003Ccode>packages\u002Ffpe-wasm\u002F\n├── pkg\u002F                          # wasm-pack 输出\n│   ├── cmtx_fpe_wasm.js\n│   ├── cmtx_fpe_wasm_bg.wasm\n│   └── cmtx_fpe_wasm.d.ts\n├── dist\u002F                         # tsdown 输出\n│   ├── index.mjs\n│   ├── index.cjs\n│   ├── index.d.ts\n│   └── pkg\u002F                      # 复制的 WASM\n│       └── cmtx_fpe_wasm_bg.wasm\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3 id=\"7.2.-rule-engine-%E5%8C%85%EF%BC%88%E5%8F%8C%E6%A0%BC%E5%BC%8F%E8%BE%93%E5%87%BA%E5%BA%93%EF%BC%89\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#7.2.-rule-engine-%E5%8C%85%EF%BC%88%E5%8F%8C%E6%A0%BC%E5%BC%8F%E8%BE%93%E5%87%BA%E5%BA%93%EF%BC%89\">#\u003C\u002Fa> 7.2. rule-engine 包（双格式输出库）\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>tsdown.config.ts：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { defineConfig } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"tsdown\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> default\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> defineConfig\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    entry: {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">        index: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"src\u002Findex.ts\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">        node: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"src\u002Fnode\u002Findex.ts\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    },\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    format: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"esm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"cjs\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    dts: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">true\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    clean: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">true\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    platform: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"node\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    target: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"node22\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    shims: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">true\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cstrong>异步加载模式（避免 INEFFECTIVE_DYNAMIC_IMPORT）：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F rules\u002Findex.ts\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> async\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> function\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> loadBuiltInRules\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">() {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">builtInRules\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">=\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\".\u002Fbuilt-in\u002Findex.js\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    return\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> builtInRules;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 不静态导出 builtInRules\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3 id=\"7.3.-vs-code-%E6%89%A9%E5%B1%95%EF%BC%88cjs-%E5%8D%95%E8%BE%93%E5%87%BA%EF%BC%89\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#7.3.-vs-code-%E6%89%A9%E5%B1%95%EF%BC%88cjs-%E5%8D%95%E8%BE%93%E5%87%BA%EF%BC%89\">#\u003C\u002Fa> 7.3. VS Code 扩展（CJS 单输出）\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>tsdown.config.ts：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { defineConfig } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"tsdown\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { wasm } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"rolldown-plugin-wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> default\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> defineConfig\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    entry: {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">        extension: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"src\u002Fextension.ts\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    },\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    plugins: [\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6F42C1\">        wasm\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">            targetEnv: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"node\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">        }),\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    ],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    format: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"cjs\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    clean: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">true\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    platform: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"node\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    target: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"node22\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    shims: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">false\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F VS Code 扩展不使用 shims，手动处理路径\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    sourcemap: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">true\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    fixedExtension: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">false\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    deps: {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">        neverBundle: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"vscode\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">        alwaysBundle: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\u002F\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">^\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">@cmtx\u003C\u002Fspan>\u003Cspan style=\"color:#22863A;font-weight:bold\">\\\u002F\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\u002F\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    },\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cstrong>WASM 加载（extension.ts）：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> *\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> as\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> fs \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"node:fs\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> *\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> as\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> path \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"node:path\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { loadWASM } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"@cmtx\u002Ffpe-wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">async\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> function\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> loadWasmExtension\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"color:#E36209\">context\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">:\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> vscode\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">ExtensionContext\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">)\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">:\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> Promise\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">&#x3C;\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">void\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">    \u002F\u002F 生产模式路径（打包后）\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> productionPath\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> path.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">join\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">        context.extensionPath,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#032F62\">        \"dist\u002Fnode_modules\u002F@cmtx\u002Ffpe-wasm\u002Fcmtx_fpe_wasm_bg.wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    );\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">    \u002F\u002F 开发模式路径（F5 调试）\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">    \u002F\u002F context.extensionPath = \u002Fworkspace\u002Fpackages\u002Fvscode-extension\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">    \u002F\u002F WASM 文件位于 \u002Fworkspace\u002Fpackages\u002Ffpe-wasm\u002Fpkg\u002F\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> developmentPath\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> path.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">join\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">        context.extensionPath,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#032F62\">        \"..\u002Ffpe-wasm\u002Fpkg\u002Fcmtx_fpe_wasm_bg.wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    );\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">    \u002F\u002F 选择存在的路径\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> wasmPath\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> fs.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">existsSync\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(productionPath)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        ?\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> productionPath\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        :\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> fs.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">existsSync\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(developmentPath)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">          ?\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> developmentPath\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">          :\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> null\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    if\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> (wasmPath) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> wasmBuffer\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> fs.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">readFileSync\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(wasmPath);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">        await\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> loadWASM\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">({ data: wasmBuffer });\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">else\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">        console.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">error\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\">\"WASM file not found\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch4 id=\"7.3.1.-7.3.1-vs-code-%E6%89%A9%E5%B1%95-wasm-%E8%B7%AF%E5%BE%84%E8%AF%A6%E8%A7%A3\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#7.3.1.-7.3.1-vs-code-%E6%89%A9%E5%B1%95-wasm-%E8%B7%AF%E5%BE%84%E8%AF%A6%E8%A7%A3\">#\u003C\u002Fa> 7.3.1. 7.3.1 VS Code 扩展 WASM 路径详解\u003C\u002Fh4>\n\u003Cp>\u003Cstrong>问题背景：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>VS Code 扩展在开发模式（F5 调试）和生产模式（vsce package）下，\u003Ccode>context.extensionPath\u003C\u002Fcode> 指向不同的目录，导致 WASM 文件路径需要分别处理。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>路径差异：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>模式\u003C\u002Fth>\n\u003Cth>\u003Ccode>context.extensionPath\u003C\u002Fcode>\u003C\u002Fth>\n\u003Cth>WASM 文件位置\u003C\u002Fth>\n\u003Cth>相对路径\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Cstrong>开发模式（F5）\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>\u002Fworkspace\u002Fpackages\u002Fvscode-extension\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>\u002Fworkspace\u002Fpackages\u002Ffpe-wasm\u002Fpkg\u002F\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>..\u002Ffpe-wasm\u002Fpkg\u002F\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Cstrong>生产模式（vsce）\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>\u002Fpath\u002Fto\u002Finstalled\u002Fextension\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>dist\u002Fnode_modules\u002F@cmtx\u002Ffpe-wasm\u002F\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>dist\u002Fnode_modules\u002F@cmtx\u002Ffpe-wasm\u002F\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp>\u003Cstrong>关键代码解析：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 开发模式：从 vscode-extension 目录向上一级到 packages\u002F，再进入 fpe-wasm\u002Fpkg\u002F\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> developmentPath\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> path.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">join\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    context.extensionPath, \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F \u002Fworkspace\u002Fpackages\u002Fvscode-extension\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#032F62\">    \"..\u002Ffpe-wasm\u002Fpkg\u002Fcmtx_fpe_wasm_bg.wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 结果：\u002Fworkspace\u002Fpackages\u002Ffpe-wasm\u002Fpkg\u002Fcmtx_fpe_wasm_bg.wasm\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 生产模式：WASM 文件被打包到 dist\u002Fnode_modules\u002F@cmtx\u002Ffpe-wasm\u002F\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> productionPath\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> path.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">join\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    context.extensionPath, \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F \u002Fpath\u002Fto\u002Finstalled\u002Fextension\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#032F62\">    \"dist\u002Fnode_modules\u002F@cmtx\u002Ffpe-wasm\u002Fcmtx_fpe_wasm_bg.wasm\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cstrong>为什么使用 \u003Ccode>..\u002Ffpe-wasm\u002Fpkg\u002F\u003C\u002Fcode>？\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Ccode>rolldown-plugin-wasm\u003C\u002Fcode> 不支持自定义输出路径配置\u003C\u002Fli>\n\u003Cli>开发模式下，WASM 文件不会被复制到 \u003Ccode>vscode-extension\u002Fdist\u002F\u003C\u002Fcode> 目录\u003C\u002Fli>\n\u003Cli>需要通过相对路径从 \u003Ccode>vscode-extension\u002F\u003C\u002Fcode> 导航到 \u003Ccode>fpe-wasm\u002Fpkg\u002F\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Ccode>path.join()\u003C\u002Fcode> 会自动规范化 \u003Ccode>..\u003C\u002Fcode> 路径\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>\u003Cstrong>\u003Ccode>fpe-wasm\u003C\u002Fcode> 包的 \u003Ccode>locateWasmFile()\u003C\u002Fcode> 在 bundled 代码中的行为：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>在 VS Code 扩展的 bundled 代码中，\u003Ccode>fpe-wasm\u003C\u002Fcode> 包的 \u003Ccode>locateWasmFile()\u003C\u002Fcode> 函数使用 \u003Ccode>__dirname + &quot;..\u002Fpkg\u002F&quot;\u003C\u002Fcode> 来定位 WASM 文件。但是：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Ccode>__dirname\u003C\u002Fcode> 通过 \u003Ccode>getDirname$1()\u003C\u002Fcode> 获取，指向 bundled 文件所在目录（\u003Ccode>vscode-extension\u002Fdist\u002F\u003C\u002Fcode>）\u003C\u002Fli>\n\u003Cli>\u003Ccode>__dirname + &quot;..\u002Fpkg\u002F&quot;\u003C\u002Fcode> 会解析到 \u003Ccode>vscode-extension\u002Fpkg\u002F\u003C\u002Fcode>（错误）\u003C\u002Fli>\n\u003Cli>实际 WASM 文件在 \u003Ccode>packages\u002Ffpe-wasm\u002Fpkg\u002F\u003C\u002Fcode>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>因此，VS Code 扩展必须在 \u003Ccode>extension.ts\u003C\u002Fcode> 中手动加载 WASM，不能依赖 \u003Ccode>fpe-wasm\u003C\u002Fcode> 包的自动加载。\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>\u003Cstrong>使用异步加载：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre data-lang=\"typescript\" class=\"shiki github-light\" style=\"background-color:#fff;color:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\"> { loadBuiltInRules, createRuleEngine } \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">from\u003C\u002Fspan>\u003Cspan style=\"color:#032F62\"> \"@cmtx\u002Frule-engine\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> async\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> function\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> applyPreset\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">()\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\">:\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> Promise\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">&#x3C;\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\">void\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> engine\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> createRuleEngine\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5\"> builtInRules\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\"> loadBuiltInRules\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">    engine.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1\">registerMany\u003C\u002Fspan>\u003Cspan style=\"color:#24292E\">(builtInRules);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">    \u002F\u002F ...\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Chr>\n\u003Ch2 id=\"8.-wasm-%E4%BD%93%E7%A7%AF%E4%B8%8E-vsix-%E6%89%93%E5%8C%85%E5%BD%B1%E5%93%8D\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#8.-wasm-%E4%BD%93%E7%A7%AF%E4%B8%8E-vsix-%E6%89%93%E5%8C%85%E5%BD%B1%E5%93%8D\">#\u003C\u002Fa> 8. WASM 体积与 VSIX 打包影响\u003C\u002Fh2>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>考虑因素\u003C\u002Fth>\n\u003Cth>说明\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>VSIX 包体积\u003C\u002Ftd>\n\u003Ctd>WASM 文件（fpe-wasm ~58KB + autocorrect-wasm ~2.5MB）会被打包进 VSIX\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>加载时间\u003C\u002Ftd>\n\u003Ctd>大型 WASM 文件加载时间会增加，建议保持懒加载模式\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>内存占用\u003C\u002Ftd>\n\u003Ctd>WASM 加载后会占用内存，需注意 Extension Host 的内存限制\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Chr>\n\u003Ch2 id=\"9.-%E5%86%B3%E7%AD%96%E6%B5%81%E7%A8%8B%E5%9B%BE\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#9.-%E5%86%B3%E7%AD%96%E6%B5%81%E7%A8%8B%E5%9B%BE\">#\u003C\u002Fa> 9. 决策流程图\u003C\u002Fh2>\n\u003Ch3 id=\"9.1.-%E9%80%89%E6%8B%A9%E6%A8%A1%E5%9D%97%E8%B7%AF%E5%BE%84%E8%8E%B7%E5%8F%96%E6%96%B9%E5%BC%8F\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#9.1.-%E9%80%89%E6%8B%A9%E6%A8%A1%E5%9D%97%E8%B7%AF%E5%BE%84%E8%8E%B7%E5%8F%96%E6%96%B9%E5%BC%8F\">#\u003C\u002Fa> 9.1. 选择模块路径获取方式\u003C\u002Fh3>\n\u003Cpre>\u003Ccode>你的项目需要输出什么格式？\n├── 只输出 CJS\n│   └── 使用 __dirname（原生支持）\n├── 只输出 ESM（Node ≥ 20.11）\n│   └── 使用 globalThis._importMeta_.dirname\n├── 只输出 ESM（Node &lt; 20.11）\n│   └── 使用 fileURLToPath(globalThis._importMeta_.url)\n└── 输出 CJS + ESM（双格式）\n    └── 使用 __dirname + tsdown shims: true\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3 id=\"9.2.-%E9%80%89%E6%8B%A9-wasm-%E5%A4%84%E7%90%86%E6%96%B9%E5%BC%8F\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#9.2.-%E9%80%89%E6%8B%A9-wasm-%E5%A4%84%E7%90%86%E6%96%B9%E5%BC%8F\">#\u003C\u002Fa> 9.2. 选择 WASM 处理方式\u003C\u002Fh3>\n\u003Cpre>\u003Ccode>你的项目类型？\n├── VS Code 扩展（CJS 单输出）\n│   └── copy + 手动加载（详见第 7.3 节 VS Code 扩展）\n├── 双格式库（CJS + ESM）\n│   └── copy + 运行时加载（__dirname + shims: true）\n└── 浏览器应用\n    └── copy + fetch 运行时加载\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3 id=\"9.3.-%E8%A7%A3%E5%86%B3%E6%9E%84%E5%BB%BA%E8%AD%A6%E5%91%8A\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#9.3.-%E8%A7%A3%E5%86%B3%E6%9E%84%E5%BB%BA%E8%AD%A6%E5%91%8A\">#\u003C\u002Fa> 9.3. 解决构建警告\u003C\u002Fh3>\n\u003Cpre>\u003Ccode>遇到的警告？\n├── EMPTY_IMPORT_META\n│   └── 改为使用 __dirname + shims: true\n├── INEFFECTIVE_DYNAMIC_IMPORT\n│   └── 改为使用异步加载函数（loadXxx）\n└── MISSING_EXPORT\n    └── 检查导入的成员是否已正确导出\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Chr>\n\u003Ch2 id=\"10.-%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5%E6%80%BB%E7%BB%93\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#10.-%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5%E6%80%BB%E7%BB%93\">#\u003C\u002Fa> 10. 最佳实践总结\u003C\u002Fh2>\n\u003Ch3 id=\"10.1.-%E6%A8%A1%E5%9D%97%E8%B7%AF%E5%BE%84\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#10.1.-%E6%A8%A1%E5%9D%97%E8%B7%AF%E5%BE%84\">#\u003C\u002Fa> 10.1. 模块路径\u003C\u002Fh3>\n\u003Col>\n\u003Cli>\u003Cstrong>双格式输出\u003C\u002Fstrong>：源码使用 \u003Ccode>__dirname\u003C\u002Fcode> + \u003Ccode>shims: true\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Cstrong>纯 ESM\u003C\u002Fstrong>：使用 \u003Ccode>globalThis._importMeta_.dirname\u003C\u002Fcode>（Node ≥ 20.11）\u003C\u002Fli>\n\u003Cli>\u003Cstrong>纯 CJS\u003C\u002Fstrong>：使用 \u003Ccode>__dirname\u003C\u002Fcode>\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch3 id=\"10.2.-wasm-%E5%A4%84%E7%90%86\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#10.2.-wasm-%E5%A4%84%E7%90%86\">#\u003C\u002Fa> 10.2. WASM 处理\u003C\u002Fh3>\n\u003Col>\n\u003Cli>\u003Cstrong>扩展项目\u003C\u002Fstrong>：使用 \u003Ccode>copy + 手动加载\u003C\u002Fcode>，参见第 7.3 节 VS Code 扩展\u003C\u002Fli>\n\u003Cli>\u003Cstrong>库项目\u003C\u002Fstrong>：使用 \u003Ccode>copy + 运行时加载\u003C\u002Fcode>\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch3 id=\"10.3.-%E5%8A%A8%E6%80%81%E5%AF%BC%E5%85%A5\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#10.3.-%E5%8A%A8%E6%80%81%E5%AF%BC%E5%85%A5\">#\u003C\u002Fa> 10.3. 动态导入\u003C\u002Fh3>\n\u003Col>\n\u003Cli>\u003Cstrong>避免同时静态和动态导入同一模块\u003C\u002Fstrong>\u003C\u002Fli>\n\u003Cli>\u003Cstrong>使用异步加载函数\u003C\u002Fstrong>（如 \u003Ccode>loadBuiltInRules()\u003C\u002Fcode>）\u003C\u002Fli>\n\u003Cli>\u003Cstrong>在异步函数中使用 \u003Ccode>await\u003C\u002Fcode> 加载\u003C\u002Fstrong>\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch3 id=\"10.4.-%E6%9E%84%E5%BB%BA%E9%85%8D%E7%BD%AE\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#10.4.-%E6%9E%84%E5%BB%BA%E9%85%8D%E7%BD%AE\">#\u003C\u002Fa> 10.4. 构建配置\u003C\u002Fh3>\n\u003Col>\n\u003Cli>\u003Cstrong>始终设置 \u003Ccode>platform: &quot;node&quot;\u003C\u002Fcode>\u003C\u002Fstrong>（Node.js 项目）\u003C\u002Fli>\n\u003Cli>\u003Cstrong>始终设置 \u003Ccode>target: &quot;node22&quot;\u003C\u002Fcode>\u003C\u002Fstrong>（或你的目标版本）\u003C\u002Fli>\n\u003Cli>\u003Cstrong>双格式输出时启用 \u003Ccode>shims: true\u003C\u002Fcode>\u003C\u002Fstrong>\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Chr>\n\u003Ch2 id=\"11.-%E5%8F%82%E8%80%83%E8%B5%84%E6%BA%90\" tabindex=\"-1\">\u003Ca class=\"header-anchor\" href=\"#11.-%E5%8F%82%E8%80%83%E8%B5%84%E6%BA%90\">#\u003C\u002Fa> 11. 参考资源\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Ftsdown.dev\u002F\">tsdown 官方文档\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Ftsdown.dev\u002Foptions\u002Fshims\">tsdown Shims 文档\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Ftsdown.dev\u002Frecipes\u002Fwasm-support\">tsdown WASM 支持\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fnodejs.org\u002Fapi\u002Fesm.html\">Node.js ESM 文档\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fnodejs.org\u002Fapi\u002Fmodule.html\">Node.js module 文档\u003C\u002Fa>\u003C\u002Fli>\n\u003C\u002Ful>\n",1786290224233]