Nx 迁移 Storybook 10:.storybook 配置文件从 CommonJS 到 ESM 的完整转换指南 Nx 迁移 Storybook 10.storybook 配置文件从 CommonJS 到 ESM 的完整转换指南【免费下载链接】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 仓库中 Storybook 10 迁移生成器附带的一份 AI 迁移指令文档展开系统讲解如何将工作区中所有.storybook/main.ts与.storybook/main.js配置文件从 CommonJSCJS语法转换为 ES ModulesESM语法。读完本文你将掌握一套可直接落地的五步转换流程、四种典型 CJS 代码模式的改写方法以及迁移后的校验与结果汇报规范并能理解 Nx 为何在 Storybook 10 时代强制要求 ESM 配置。背景Storybook 10 为何要求 ESM 配置Storybook 10 起Storybook 官方要求项目配置文件使用 ES Modules 语法。这一要求在 Nx 的代码生成中体现得十分明确在 util-functions.ts 中为 Storybook 10 生成的tsconfig.storybook.json强制设置了module: esnext与moduleResolution: bundler从 TypeScript 编译层面保证 ESM 语义可用Nx 为 Storybook 10 生成的默认配置文件模板 main.ts__tmpl__ 本身就采用import type { StorybookConfig }、export default config的纯 ESM 写法。因此当工作区通过 Nx 的migrate-10生成器从旧版本升级到 Storybook 10 时历史遗留的 CJS 风格配置必须同步改写否则 Storybook 启动或构建时可能因模块语法不兼容而失败。迁移的整体流程migrate-10 生成器如何工作Nx 提供了专门的迁移生成器来驱动这一过程其实现位于 migrate-10.ts。整个迁移分为两条并行的工作流升级 Storybook 依赖生成器调用 calling-storybook-cli.ts 中的callUpgrade()通过当前包管理器执行storybook upgrade命令将storybook/*相关包升级到最新版本产出 AI 迁移指令升级完成后生成器读取本仓库中的 ai-instructions-for-cjs-esm.md将其原样写入工作区的tools/ai-migrations/MIGRATE_STORYBOOK_10.md供 AI Agent或开发者据此把 CJS 配置改写成 ESM。该生成器的可用参数定义在 schema.json 中参数类型默认值说明autoAcceptAllPromptsbooleanfalse自动同意 Storybook CLI 迁移脚本的所有交互提示configDirarray[]指定需要加载 Storybook 配置的目录可自定义要迁移的 Storybook 项目skipAiInstructionsbooleanfalse跳过向tools/ai-migrations/写入 AI 迁移指令文件只有当工作区同时安装了storybook与nx/storybook时迁移才会执行见checkStorybookInstalled()的实现逻辑否则生成器会直接提示无需迁移。核心任务CJS 到 ESM 的五步转换法以下转换流程是 AI 迁移指令的主体内容同样适用于任何手动执行迁移的开发者。Step 1查找所有 Storybook 配置文件使用 glob 模式定位工作区中所有的 Storybook 主配置文件**/.storybook/main.js **/.storybook/main.ts注意main.js与main.ts都要纳入搜索范围因为不同项目、不同历史时期生成的文件可能分别使用 JS 或 TS 版本。在 Nx 的多项目工作区中每个应用/库目录下都可能存在独立的.storybook目录。Step 2识别 CommonJS 与 ESM逐个读取找到的文件通过以下特征判断其语法类型CommonJS 特征需要转换module.exports 或module.exports.exports.require()函数调用ESM 特征已正确无需改动export defaultexport const/export functionimport语句判断的关键是看文件是否使用了require()和module.exports这对 CJS 特有的 API而非仅仅看文件扩展名——.js文件也可能是 ESM 风格而.ts文件同样可能残留 CJS 写法。Step 3执行转换对每个识别为 CommonJS 的文件按下述四种模式逐一改写。A. 转换module.exportsFROMCJSmodule.exports { stories: [../src/**/*.stories.(js|jsx|ts|tsx|mdx)], addons: [storybook/addon-essentials] };TOESMexport default { stories: [../src/**/*.stories.(js|jsx|ts|tsx|mdx)], addons: [storybook/addon-essentials] };module.exports直接改写为export default对象字面量的内容保持不变。这是最常见、也是最简单的一类转换。B. 转换require()为 importFROMCJSconst { nxViteTsPaths } require(nx/vite/plugins/nx-tsconfig-paths.plugin); const { mergeConfig } require(vite);TOESMimport { nxViteTsPaths } from nx/vite/plugins/nx-tsconfig-paths.plugin; import { mergeConfig } from vite;解构赋值的require()调用转换为具名导入import { ... } from ...。注意 Nx 的 Vite 插件路径nx/vite/plugins/nx-tsconfig-paths.plugin是 Nx 工作区中 Storybook 配置的常见依赖它同时出现在 v10 的 ESM 模板 main.ts__tmpl__ 中转换后应与之一致。C. 处理path.join()模式FROMCJSconst path require(path); const rootMain require(path.join(__dirname, ../../.storybook/main));TOESMimport { join } from path; import rootMain from ../../.storybook/main;这是 CJS 迁移中最容易出错的一类ESM 中没有__dirname因此原本用于拼接绝对路径的path.join(__dirname, ...)必须整体移除。通过相对路径直接导入目标文件并使用默认导入接收因为目标文件本身通常以module.exports/export default导出。如果确实需要在 ESM 中获取当前目录可以改用import { fileURLToPath } from node:url配合import.meta.url——Nx 的 v10 模板中getAbsolutePath辅助函数即采用这一方案。D. 处理配置函数内的动态 requireFROMCJSmodule.exports { viteFinal: async (config) { const { mergeConfig } require(vite); return mergeConfig(config, {}); } };TOESMimport { mergeConfig } from vite; export default { viteFinal: async (config) { return mergeConfig(config, {}); } };配置文件内部的回调函数如viteFinal、webpackFinal中常见的函数内再require写法在 ESM 中应当把依赖提升到文件顶部的import语句函数体内直接使用。这也是 Step 4 校验第 3 条imports 必须在 export 之前所对应的场景。Step 4转换后的校验检查完成改写后逐项验证所有require()调用都已转换为文件顶部的import语句所有module.exports都已转换为export default或具名导出所有import语句位于文件顶部在export之前若为.ts文件保持正确的 TypeScript 类型标注。对于.ts文件Nx v10 的模板还使用了import type { StorybookConfig }这类纯类型导入因此在转换时也要留意纯类型场景应使用import type以配合isolatedModules等编译选项。Step 5汇报转换结果迁移完成后输出如下汇总信息找到的文件总数Total files found本来就是 ESM、无需改动的文件Files that were already ESM从 CJS 转换到 ESM 的文件Files that were transformed from CJS to ESM具体被修改的文件清单List the specific files that were modified清晰的汇报不仅便于人工复核也让 AI Agent 的迁移过程可审计、可回滚。完整转换示例下面是一份同时覆盖四种改写模式的完整示例可直接作为迁移的对照基准。BeforeCJSconst path require(path); const { mergeConfig } require(vite); module.exports { stories: [../src/**/*.stories.(js|jsx|ts|tsx|mdx)], addons: [storybook/addon-essentials], viteFinal: async (config) { return mergeConfig(config, { resolve: { alias: {} } }); } };AfterESMimport { join } from path; import { mergeConfig } from vite; export default { stories: [../src/**/*.stories.(js|jsx|ts|tsx|mdx)], addons: [storybook/addon-essentials], viteFinal: async (config) { return mergeConfig(config, { resolve: { alias: {} } }); } };从源码结构看这份After形态与 Nx 为 Storybook 10 项目生成的新配置模板见 main.ts__tmpl__高度一致顶部统一import、配置对象export default、viteFinal中直接调用mergeConfig。这也意味着转换目标即是 Nx 官方生成器的输出风格保证迁移后与后续由 Nx 管理的新项目保持同构。迁移中的注意事项原指令文档在结尾给出了几条重要的工程约束实践中务必遵守保留原文件中的所有注释注释中可能记录了配置的历史决策或特殊说明转换时不得丢弃保持原有的缩进与格式化风格尽可能只做语法层面的最小改动避免引入无关的格式噪音便于 review diffTypeScript 文件中的类型导入.ts文件在适当场景应使用import type处理纯类型导入Nx v10 模板中的import type { StorybookConfig } from framework即为范例验证转换不破坏 Storybook 配置转换完成后应运行 Storybook 启动或构建命令确认配置能被正常加载。从指令到落地如何运行迁移在实际的 Nx 工作区中完整的落地路径如下运行 Nx 的 Storybook 10 迁移生成器等价于nx g nx/storybook:migrate-10它会自动执行storybook upgrade并生成tools/ai-migrations/MIGRATE_STORYBOOK_10.md指令文件若希望在迁移时跳过指令文件的生成可在执行时传入--skipAiInstructions对应 schema.json 中的skipAiInstructions参数将生成的指令文件提供给 AI Agent或由开发者按照本文所述的五步流程手工完成 CJS 到 ESM 的改写按 Step 4 的校验清单逐项核对并通过storybook/build-storybook目标验证配置可正常加载Nx 生成的目标配置位于项目的project.json中指向各项目的.storybook目录。至此工作区的 Storybook 配置即可与 Storybook 10 的 ESM 要求完全对齐后续由 Nx 新增或维护的 Storybook 项目也会沿用同一套 ESM 风格保持整个工作区配置形态的一致性与可维护性。【免费下载链接】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),仅供参考