资讯详情

资讯详情

Nx 23 迁移实战:将 `NxTsconfigPathsWebpackPlugin` 导入自动重写到 `@nx/webpack/tsconfig-paths-plugin` 子路径

Nx 23 迁移实战将NxTsconfigPathsWebpackPlugin导入自动重写到nx/webpack/tsconfig-paths-plugin子路径【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nx本篇技术指南基于 Nx 仓库中nx/webpack插件在 v23 版本提供的自动迁移migration讲解已废弃的NxTsconfigPathsWebpackPlugin顶层再导出被移除后如何将 ES module 导入与 CommonJSrequire()调用自动重写到新的nx/webpack/tsconfig-paths-plugin子路径。读完本文你将掌握该迁移的完整改写规则含组合导入拆分、别名保留等边界情形、底层源码实现原理、对应测试用例验证以及不依赖迁移工具时的手动等价升级步骤。迁移背景v23 移除了nx/webpack顶层再导出在 Nx 早期版本中NxTsconfigPathsWebpackPlugin既可以从nx/webpack主入口导入也存在独立源码路径。从仓库当前的 package.json 可以看出nx/webpack的exports映射已经细分为多个公开子路径./app-plugin、./plugin、./tsconfig-paths-plugin与./internal。其中./tsconfig-paths-plugin子路径被显式声明为./tsconfig-paths-plugin: { nx/nx-source: ./tsconfig-paths-plugin.ts, types: ./dist/tsconfig-paths-plugin.d.ts, default: ./dist/tsconfig-paths-plugin.js }对应的子路径入口文件 tsconfig-paths-plugin.ts 目前只做了一件事——将插件从内部实现位置重新导出export { NxTsconfigPathsWebpackPlugin } from ./src/plugins/nx-typescript-webpack-plugin/nx-tsconfig-paths-webpack-plugin;也就是说从 v23 开始nx/webpack主入口index.ts不再对外再导出该插件使用方必须改从nx/webpack/tsconfig-paths-plugin子路径导入。为了保证升级过程无感、代码库自动收敛到新写法Nx 在update-23-0-0迁移组中内置了本迁移并在 migrations.json 中注册为update-23-0-0-remove-nx-tsconfig-paths-webpack-plugin-import: { cli: nx, version: 23.0.0-beta.10, description: Rewrites imports of NxTsconfigPathsWebpackPlugin from nx/webpack to the sub-path nx/webpack/tsconfig-paths-plugin., factory: ./dist/src/migrations/update-23-0-0/remove-nx-tsconfig-paths-webpack-plugin-import, documentation: ./dist/src/migrations/update-23-0-0/remove-nx-tsconfig-paths-webpack-plugin-import.md }迁移改写的核心规则迁移对匹配到的代码执行以下三类改写原则可以概括为三句话纯 ES import 重写模块路径导入声明里只有NxTsconfigPathsWebpackPlugin这一个命名导入时仅把模块说明符nx/webpack换成nx/webpack/tsconfig-paths-plugin。组合 import 拆分声明导入声明里同时带有其他命名导入如NxAppWebpackPlugin时把废弃符号拆到新的子路径声明中剩余符号保留在原nx/webpack声明里。别名保留无论是as PluginES import 别名还是: PluginCJS 解构重命名改写后别名原样保留不丢失。纯 ES module import改写前apps/my-app/webpack.config.tsimport { NxTsconfigPathsWebpackPlugin } from nx/webpack; export default { plugins: [new NxTsconfigPathsWebpackPlugin()] };改写后import { NxTsconfigPathsWebpackPlugin } from nx/webpack/tsconfig-paths-plugin; export default { plugins: [new NxTsconfigPathsWebpackPlugin()] };ES module import 与其他命名导入共存改写前import { NxTsconfigPathsWebpackPlugin, NxAppWebpackPlugin } from nx/webpack;改写后会被拆成两条独立声明import { NxTsconfigPathsWebpackPlugin } from nx/webpack/tsconfig-paths-plugin; import { NxAppWebpackPlugin } from nx/webpack;注意这里只挪走了废弃符号NxAppWebpackPlugin仍从nx/webpack解析——这正是迁移名称中 remove the import 而非 rewrite the whole import 的含义。CommonJSrequire()改写前apps/my-app/webpack.config.jsconst { NxTsconfigPathsWebpackPlugin } require(nx/webpack);改写后const { NxTsconfigPathsWebpackPlugin, } require(nx/webpack/tsconfig-paths-plugin);带别名的组合导入当 ES import 使用别名且与其他符号混排时import { NxTsconfigPathsWebpackPlugin as Plugin, NxAppWebpackPlugin } from nx/webpack;改写为import { NxTsconfigPathsWebpackPlugin as Plugin } from nx/webpack/tsconfig-paths-plugin; import { NxAppWebpackPlugin } from nx/webpack;CJS 解构重命名同理const { NxTsconfigPathsWebpackPlugin: Plugin, NxAppWebpackPlugin } require(nx/webpack);改写为const { NxTsconfigPathsWebpackPlugin: Plugin } require(nx/webpack/tsconfig-paths-plugin); const { NxAppWebpackPlugin } require(nx/webpack);源码实现tsquery AST 选择器驱动的定点重写迁移的完整实现位于 remove-nx-tsconfig-paths-webpack-plugin-import.ts其设计可以拆成四个层次来理解。第一层常量定义实现开头集中定义了迁移的三个关键常量它们是整个改写逻辑的配方const DEPRECATED_SYMBOL NxTsconfigPathsWebpackPlugin; const DEPRECATED_PACKAGE nx/webpack; const NEW_PACKAGE nx/webpack/tsconfig-paths-plugin;第二层AST 选择器精确圈定目标迁移基于phenomnomnominal/tsquery做语法树查询该依赖声明在 package.json 的dependencies中。它把 ES import 和 CJS require 分别建模为两组选择器ES module 匹配ImportDeclaration且其StringLiteral值为nx/webpack同时ImportClause的ImportSpecifier中存在名为NxTsconfigPathsWebpackPlugin的Identifier。这保证了路径对 符号对才命中。CJS 匹配VariableStatement中ObjectBindingPattern的解构元素包含目标标识符且CallExpression的require(nx/webpack)命中目标路径。第三层区分单符号与多符号两种改写策略这是整个迁移最核心的分支逻辑只有一个 specifier/binding 时直接定位模块路径节点ES 的StringLiteral或 CJS 的 require 路径字符串用字符串切片把nx/webpack原位替换为nx/webpack/tsconfig-paths-plugin。有多个 specifier/binding 时把目标符号节点原文getText()因此别名会原样包含在内拼成一条新声明import { X } from nx/webpack/tsconfig-paths-plugin;或const { X } require(nx/webpack/tsconfig-paths-plugin);前置插入到原声明之前再从原声明中删除目标符号片段剩余符号与路径保持不变。值得注意的实现细节是endAfterTrailingComma辅助函数它从目标符号的结束位置向后跳过空白字符寻找尾随逗号从而正确处理NxTsconfigPathsWebpackPlugin , NxAppWebpackPlugin逗号前带空格的写法删除时不会留下多余逗号导致语法错误。第四层while循环实现同文件多点重写一个文件里可能同时存在多处匹配例如既有 ES import 又有 CJS require或者多个文件内多处 import。由于多符号分支会前置插入新声明导致文件偏移量整体变化、已收集的 AST 节点位置全部失效实现选择一次只处理一个匹配、处理完重新解析的策略let didRewrite true; while (didRewrite) { didRewrite false; const sourceFile ast(contents); // 每次循环重新查询 ES import 与 CJS require…… }循环直到某次遍历不再产生任何改写为止从而天然保证幂等性——已改写成子路径的代码不会被再次触碰因为新路径不再匹配DEPRECATED_PACKAGE。文件范围与收尾迁移通过visitNotIgnoredFiles(tree, )遍历工作区所有未被忽略的文件但只处理.ts、.tsx、.js、.jsx、.cjs、.mjs六类源码文件在进入 AST 解析前还会做一次字符串级快速预检文件必须同时包含废弃符号和废弃包路径否则直接跳过避免对无关文件做无谓解析。全部改写完成后调用await formatFiles(tree)统一格式化保证代码风格一致。测试用例12 个场景覆盖改写行为迁移配套了完整的单元测试 remove-nx-tsconfig-paths-webpack-plugin-import.spec.ts基于createTreeWithEmptyWorkspace()构造内存工作区并断言改写后的文件内容覆盖的关键行为包括测试场景验证要点单个 ES import路径改写为子路径多 specifier目标在前 / 在后仅移走废弃符号其余符号保留原路径单个 CJS require路径改写为子路径多 binding 的 require拆分声明目标符号单独 require 子路径无废弃符号的文件文件保持字节级不变幂等性连续运行两次结果一致ES import 别名as Plugin别名原样保留CJS 解构重命名: Plugin别名原样保留同文件多处匹配所有 import/require 均被改写逗号前空白Foo , Bar不残留孤立逗号无语法错误已是正确子路径的代码不做任何修改尤其最后两个场景很关键一个是不该动的别动一个是该动的别漏从测试层面锁定了迁移的精确边界。does not modify files already using the correct sub-path import用例还特意以formatter: none创建树断言文件改写前后字节完全一致防止格式化逻辑掩盖真实的改动行为。不依赖迁移工具时的手动等价升级自动迁移会在nx migrate流程中自动执行但如果你需要手动升级例如迁移未覆盖到的自定义构建配置、独立维护的脚本、或 CI 中临时修复等价的手动步骤是替换所有从nx/webpack导入NxTsconfigPathsWebpackPlugin的语句单符号 import/require直接把模块路径改成nx/webpack/tsconfig-paths-plugin组合 import/require把废弃符号拆成独立声明并从原声明中移除其余符号维持nx/webpack别名as/:保持原样。检查工作区中是否还有nx/webpack/src/...形式的深路径导入与本次迁移同批发布的rewrite-webpack-internal-subpath-imports迁移见 migrations.json负责处理nx/webpack不再暴露./src/*子路径的情况建议一并升级处理。执行构建验证运行nx build app或对应webpack构建命令确认模块解析正常、NxTsconfigPathsWebpackPlugin实例化不再报 Missing tsConfig option 以外的错误。理解插件本身迁移背后的技术动机搞清楚迁移为什么存在还需要理解NxTsconfigPathsWebpackPlugin在构建链中的角色。其类定义位于 nx-tsconfig-paths-webpack-plugin.ts构造函数要求传入tsConfig选项否则直接抛错Missing tsConfig option. Set this option in your Nx webpack plugin.apply(compiler)阶段会基于tsconfig-paths-webpack-plugin的TsconfigPathsPlugin注册resolve.plugins并把.ts/.tsx/.mjs/.js/.jsx与 webpack 自身resolve.extensions合并进extensions集合baseUrl通过resolvePathsBaseUrl(configFile)计算它还承担buildLibsFromSource: false时的依赖协调调用nx/js/internal的calculateProjectBuildableDependencies与createTmpTsConfig生成临时 tsconfig并在serve目标下注入WebpackNxBuildCoordinationPlugin联动nx run-many --targetbuild构建可构建依赖。仓库内部代码如 apply-base-config.ts通过相对路径../../nx-typescript-webpack-plugin/nx-tsconfig-paths-webpack-plugin直接导入该类因此不受 exports 映射调整影响受影响的是所有通过包名nx/webpack导入它的外部使用者——这正是本次迁移存在的全部意义。迁移本身只重写导入语句不改变插件行为属于典型的API 面收敛、实现不动的兼容性迁移。注意事项迁移只处理上述六类源码文件.ts/.tsx/.js/.jsx/.cjs/.mjs模板文件如__tmpl__后缀不会被扫描若工作区存在手写的模板字符串需要自行同步修改。迁移是幂等的运行两次不会产生二次改写已经使用子路径的代码不会被触碰。若自定义 webpack 配置中同时依赖NxAppWebpackPlugin等其余符号拆分后它们仍从nx/webpack主入口解析无需改动。升级后建议完整运行一次目标应用的构建与测试确认resolve.plugins中的 tsconfig paths 解析行为与升级前一致。【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →