mcpField
N
nx-import

nx-import

github.com/nrwl开发292.6k 次安装今天更新
代码仓库

关于 nx-import

用于指导将代码仓库或文件夹导入 Nx 工作区并保留 Git 历史的技能,帮助开发者选择导入方式并处理后续配置问题。

主要功能

  1. 01导入代码并保留 Git 历史
  2. 02选择整仓库或子目录导入
  3. 03识别应用与库
  4. 04处理工作区 glob 和依赖配置
  5. 05排查 TypeScript 与插件配置问题

适用场景

  1. 01将其他仓库中的项目加入 Nx
  2. 02导入 monorepo 中选定的包
  3. 03排查工作区包解析失败
  4. 04为 Nx 配置导入的 TypeScript 项目

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/nrwl/nx-ai-agents-config --skill nx-import

安装后在 Claude Code 中输入/nx-import确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
ESLINT.md
GRADLE.md
JEST.md
NEXT.md
TURBOREPO.md
VITE.md

详细介绍

快速入门

  • nx import 会将代码从源代码仓库或文件夹导入当前工作区,并保留提交历史。
  • 在 nx 22.6.0 及更高版本中,nx import 会输出 .ndjson 并提出后续问题。对于更早的版本,始终使用 --no-interactive 运行,并直接指定所有标志。
  • 运行 nx import --help 查看可用选项。
  • 导入前,请确保目标目录为空。 示例:目标目录中有 libs/utils 和 libs/models;源目录中有 libs/ui 和 libs/data-access——你不能直接将 libs/ 导入 libs/。请分别导入源目录中的每个库。

主要文档:

如果你有相关工具,请阅读 nx 文档。

导入策略

逐个子目录导入(nx import <source> apps --source=apps):

  • 建议用于单体仓库源——文件会放在顶层,不会产生冗余配置
  • 注意事项:需要运行多条导入命令(每条都会创建单独的合并提交);目标目录不能有冲突目录;不会导入根目录配置(依赖项、插件、targetDefaults)
  • 目录冲突:导入到名称不同的目录(例如 imported-apps/),然后重命名

导入整个仓库(nx import <source> imported --source=.):

  • 仅用于非单体仓库源(单项目仓库)
  • 对于单体仓库,会产生杂乱的嵌套配置(imported/nx.json、imported/tsconfig.base.json 等)
  • 如果必须这样做:保留导入的 tsconfig.base.json(项目会扩展此配置),为工作区 glob 和 executor 路径添加前缀
目录约定
  • **始终优先遵循目标目录现有的约定。**源目录使用 libs/,但目标目录使用 packages/?导入到 packages/(nx import <source> packages/foo --source=libs/foo)。
  • 如果目标目录没有约定(工作区为空),请询问用户。
应用与库的识别

导入前,判断源项目是应用还是库:

  • 应用:可部署的最终产品。常见特征:
    • 前端:next.config.*、带有构建入口点的 vite.config.*、特定框架的应用脚手架(CRA、Angular CLI 应用等)
    • 后端(Node.js):Express/Fastify/NestJS 服务入口点,package.json 中没有 "exports" 字段
    • JVM:Maven pom.xml 中包含 <packaging>jar</packaging> 或 <packaging>war</packaging>,且有 main 类;Gradle application 插件或 mainClass 设置
    • .NET:.csproj/.fsproj 中包含 <OutputType>Exe</OutputType> 或 <OutputType>WinExe</OutputType>
    • 通用:Dockerfile、可运行的入口点、没有供其他项目导入的公共 API
  • 库:供其他项目使用的可复用包。常见特征:package.json 中的 "main"/"exports"、Maven/Gradle 将其打包为库 JAR、.NET <OutputType>Library</OutputType>、旨在供其他包导入的命名导出。

目标目录规则:

  • 应用 → apps/<name>。检查工作区 glob(例如 pnpm-workspace.yaml、根 package.json 中的 workspaces),确认是否已有 apps/* 条目。
    • 如果没有 apps/*,请在导入前添加:更新工作区 glob 配置并提交(或暂存)更改。
    • 示例:nx import <source> apps/my-app --source=packages/my-app
  • 库 → 遵循目标目录现有的约定(packages/、libs/ 等)。

常见问题

pnpm 工作区 Glob(重要)

nx import 会将导入目录本身(例如 apps)添加到 pnpm-workspace.yaml,而不是添加其中包的 glob 模式。跨包导入会失败,并出现 Cannot find module。

修复方法:根据源配置替换为正确的 glob(例如 apps/*、libs/shared/*),然后运行 pnpm install。

根依赖和配置不会被导入(严重)

nx import 不会合并源项目根目录中的以下内容:

  • package.json 中的 dependencies/devDependencies
  • nx.json 中的 targetDefaults(例如 "@nx/esbuild:esbuild": { "dependsOn": ["^build"] }——对构建顺序至关重要)
  • nx.json 中的 namedInputs(例如用于排除测试文件的 production 模式)
  • nx.json 中的插件配置

修复方法:比较源项目和目标项目的 package.json 与 nx.json。补上缺失的依赖项,并合并相关的 targetDefaults 和 namedInputs。

TypeScript 项目引用

导入后,运行 nx sync --yes。如果没有报告任何内容,但类型检查仍然失败,请先运行 nx reset,然后再次运行 nx sync --yes。

显式执行器路径修正

推断出的目标(通过 Nx 插件)会基于项目根目录解析配置,无需更改。显式执行器目标(例如 @nx/esbuild:esbuild)使用相对于工作区根目录的路径(main、outputPath、tsConfig、assets、sourceRoot),必须在这些路径前加上导入目标目录。

插件检测
  • 导入整个仓库:nx import 会检测并提示安装插件。接受提示。
  • 导入子目录:不会自动检测插件。请手动使用 npx nx add @nx/PLUGIN 添加。检查 include/exclude 模式——默认模式不适用于其他目录(例如 apps-beta/)。
  • 更改任何插件配置后,运行 npx nx reset。
多余的根目录文件(仅适用于导入整个仓库)

导入整个仓库会将源项目根目录下的所有文件带入目标子目录。请清理以下文件:

  • pnpm-lock.yaml——已过时;目标项目有自己的锁文件
  • pnpm-workspace.yaml——源项目的工作区配置;会与目标项目冲突
  • node_modules/——已过时,包含指向源文件系统的符号链接
  • .gitignore——与目标项目根目录下的 .gitignore 重复
  • nx.json——源项目的 Nx 配置;目标项目有自己的配置
  • README.md——可选;保留或删除均可

不要盲目删除 tsconfig.base.json——导入的项目可能会通过相对路径扩展该文件。

缺少根目录 ESLint 配置(导入子目录)

导入子目录不会带入源项目根目录下的 eslint.config.mjs,但项目配置中引用了 ../../eslint.config.mjs。

修复顺序:

  1. 先安装 ESLint 依赖:pnpm add -wD eslint@^9 @nx/eslint-plugin typescript-eslint(以及特定框架所需的插件)
  2. 创建根目录 eslint.config.mjs(从源项目复制,或使用 @nx/eslint-plugin 基础规则创建)
  3. 然后运行 npx nx add @nx/eslint,在 nx.json 中注册插件

请显式安装 typescript-eslint——pnpm 的严格提升机制不会自动解析 @nx/eslint-plugin 的这个传递依赖。

固定 ESLint 版本(严重)

将 ESLint 固定为 v9(eslint@^9.0.0)。ESLint 10 会导致 @nx/eslint 和许多插件出错,并产生难以理解的错误,例如 Cannot read properties of undefined (reading 'version')。

@nx/eslint 可能会将 ESLint 8 作为对等依赖,导致解析到错误版本。如果 lint 因 Cannot read properties of undefined (reading 'allow') 失败,请添加 pnpm.overrides:

{ "pnpm": { "overrides": { "eslint": "^9.0.0" } } }
依赖版本冲突

导入后,请比较关键依赖项(typescript、eslint 和特定框架的依赖项)。如果目标项目使用较新版本,请将导入的软件包升级到匹配版本(通常是安全的)。如果源项目使用较新版本,可能需要先升级目标项目。如果需要强制执行单一版本策略,请使用 pnpm.overrides。

模块边界

导入的项目可能缺少 tags。请添加标签,或更新 @nx/enforce-module-boundaries 规则。

项目名称冲突(多次导入)

源项目和目标项目的 package.json 中如果有相同的 name,会导致 MultipleProjectsWithSameNameError。修复方法:重命名冲突项(例如将 @org/api 改为 @org/teama-api),更新所有依赖引用和导入语句,然后运行 pnpm install。每个导入仓库的根目录 package.json 也会成为一个项目——也请重命名其中的名称。

工作区依赖导入顺序

如果尚未导入某个 "workspace:*" 依赖,pnpm install 会在 nx import 期间失败。文件操作仍会成功。修复方法:先导入所有项目,再运行 pnpm install --no-frozen-lockfile。

.gitkeep 阻止子目录导入

TS 预设会创建 packages/.gitkeep。导入前将其删除并提交。

前端 tsconfig 基础设置(关键)

TS 预设的默认设置(module: "nodenext"、moduleResolution: "nodenext"、lib: ["es2022"])与前端框架(React、Next.js、Vue、Vite)不兼容。导入前端项目后,请检查目标根目录的 tsconfig.base.json:

  • moduleResolution:必须为 "bundler"(而非 "nodenext")
  • module:必须为 "esnext"(而非 "nodenext")
  • lib:必须包含 "dom" 和 "dom.iterable"(前端项目需要这些)
  • jsx:仅使用 React 的工作区设为 "react-jsx";混合框架则按项目设置

对于子目录导入,目标根目录的 tsconfig 是权威配置——请更新它。对于整个仓库导入,导入的项目可能会继承各自嵌套的 tsconfig.base.json,因此这项设置没那么关键。

如果目标仓库还有需要 nodenext 的后端项目,请使用按项目覆盖设置,而不是修改根目录。

注意事项:TypeScript 不会合并 lib 数组——项目级覆盖设置会完全替换基础数组。项目级 lib 中务必包含所有需要的条目(例如 es2022、dom、dom.iterable)。

库的 @nx/react 类型定义

使用 @nx/react:library 生成的 React 库,会在其 tsconfig 的 types 中引用 @nx/react/typings/cssmodule.d.ts 和 @nx/react/typings/image.d.ts。如果目标工作区未安装 @nx/react,就会出现 Cannot find type definition file 错误。

修复方法:pnpm add -wD @nx/react

缺少 Jest 预设(子目录导入)

Nx 预设会在工作区根目录创建 jest.preset.js,项目的 Jest 配置会引用它(例如 ../../jest.preset.js)。子目录导入不会导入此文件。

修复方法:

  1. 运行 npx nx add @nx/jest——在 nx.json 中注册 @nx/jest/plugin 并更新 namedInputs
  2. 在工作区根目录创建 jest.preset.js(内容见 references/JEST.md)——nx add 只有在运行生成器时才会创建此文件,单独运行 nx add 不会创建
  3. 安装测试运行器依赖:pnpm add -wD jest jest-environment-jsdom ts-jest @types/jest
  4. 按需安装框架专用的测试依赖(见 references/JEST.md)

有关更深入的 Jest 问题(tsconfig.spec.json、Babel 转换、CI 原子化、Jest 与 Vitest 共存),请参阅 references/JEST.md。

目标名称添加前缀(整个仓库导入)

导入含有现有 npm 脚本(build、dev、start、lint)的项目时,Nx 插件会自动为推断出的目标名称添加前缀,以避免冲突:例如 next:build、vite:build、eslint:lint。

修复方法:从导入项目的 package.json 中删除 Nx 重写过的 npm 脚本,然后选择以下方式之一:

  • 接受添加前缀后的名称(例如 nx run app:next:build)
  • 在 nx.json 中重命名插件目标,使其使用不带前缀的名称

非 Nx 源代码问题

当源代码是没有 nx.json 的普通 pnpm/npm 工作区时。

npm 脚本重写(关键)

Nx 会在初始化期间重写 package.json 脚本,导致命令失效(例如将 vitest run 改为 nx test run)。修复方法:删除所有被重写的脚本——Nx 插件会根据配置文件推断目标。

noEmit → composite + emitDeclarationOnly(关键)

普通 TS 项目使用 "noEmit": true,这与 Nx 项目引用不兼容。

症状:“typecheck target is disabled because one or more project references set 'noEmit: true'” 或 TS6310。

修复:在所有导入的 tsconfig 中:

  1. 移除 "noEmit": true。如果它是通过 extends 链继承的,请显式设置 "noEmit": false。
  2. 添加 "composite": true、"emitDeclarationOnly": true、"declarationMap": true
  3. 添加 "outDir": "dist" 和 "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo"
  4. 如果缺少 "extends": "../../tsconfig.base.json",则添加。移除现在可以从基础配置继承的设置。
过时的 node_modules 和锁文件

nx import 可能会从源项目导入 node_modules/(其中包含指向源文件系统的 pnpm 符号链接)和 pnpm-lock.yaml。两者都已过时。

修复:rm -rf imported/node_modules imported/pnpm-lock.yaml imported/pnpm-workspace.yaml imported/.gitignore,然后运行 pnpm install。

ESLint 配置处理
  • 旧版 .eslintrc.json(ESLint 8):删除所有 .eslintrc.*,移除 v8 依赖,并创建扁平配置 eslint.config.mjs。
  • 扁平配置(eslint.config.js):自包含的配置通常可以保持原样。
  • 未使用 ESLint:从头创建根目录和项目级配置。
TypeScript paths 别名

Nx 使用 package.json "exports" 和 pnpm 工作区链接,而不是 tsconfig "paths"。如果软件包配置了正确的 "exports",则不需要 paths。否则,请根据新的目录结构更新 paths。

特定技术的指导

识别源代码仓库中使用的技术,然后阅读并应用对应的参考文件。

可用参考文件:

  • references/ESLINT.md — ESLint 项目:重复的 lint/eslint:lint 目标、旧版 .eslintrc.* 对生成文件的检查、扁平配置 .cjs 自检查、typescript-eslint v7/v9 对等依赖冲突、同一工作区混用 ESLint v8 和 v9。
  • references/GRADLE.md
  • references/JEST.md — Jest 测试:@nx/jest/plugin 配置、jest.preset.js、按框架配置测试依赖、tsconfig.spec.json、Jest 与 Vitest 共存、Babel 转换、CI 原子化。
  • references/NEXT.md — Next.js 项目:@nx/next/plugin 目标、withNx、Next.js TS 配置(noEmit、jsx: "preserve")、通过错误的 PM 自动安装依赖、导入非 Nx create-next-app 项目、Next.js 与 Vite 混用。
  • references/TURBOREPO.md
  • references/VITE.md — Vite 项目(React、Vue 或两者):@nx/vite/plugin 类型检查目标、resolve.alias/__dirname 修复、框架依赖、Vue 专属配置、React 与 Vue 混用。

评论

支持 Markdown