🚀 快速安装
复制以下命令并运行,立即安装此 Skill:
npx skills add https://skills.sh/nrwl/nx-ai-agents-config/nx-import
💡 提示:需要 Node.js 和 NPM
快速开始 (Quick Start)
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/。请分别导入每个源库。
主要文档:
- https://nx.dev/docs/guides/adopting-nx/import-project
- https://nx.dev/docs/guides/adopting-nx/preserving-git-histories
如有相应工具,请阅读 nx 文档。
导入策略 (Import Strategy)
逐个子目录导入 (Subdirectory-at-a-time) (nx import <source> apps --source=apps):
- 推荐用于 monorepo 源 — 文件放置在顶层,没有冗余配置
- 注意事项:需要多次导入命令(每次产生单独的合并提交);目标目录不能有冲突的目录;根目录配置(依赖、插件、targetDefaults)不会被导入
- 目录冲突 (Directory conflicts):导入到替代名称的目录(例如
imported-apps/),然后重命名
整个仓库导入 (Whole repo) (nx import <source> imported --source=.):
- 仅适用于非 monorepo 源(单项目仓库)
- 对于 monorepo,会产生混乱的嵌套配置(
imported/nx.json、imported/tsconfig.base.json等) - 如果必须这样做:保留导入的
tsconfig.base.json(项目会扩展它),为工作区全局和 executor 路径添加前缀
目录约定 (Directory Conventions)
- 始终优先采用目标目录的现有约定。源使用
libs/但目标使用packages/?导入到packages/(nx import <source> packages/foo --source=libs/foo)。 - 如果目标目录没有约定(空工作区),请询问用户。
应用程序与库的识别 (Application vs Library Detection)
导入前,确定源是应用程序还是库:
- 应用程序 (Applications):可部署的最终产品。常见标志:
- 前端 (Frontend):
next.config.*、vite.config.*带有构建入口点、特定框架的应用脚手架(CRA、Angular CLI 应用等) - 后端 (Node.js) (Backend – Node.js):Express/Fastify/NestJS 服务器入口点,
package.json中没有"exports"字段 - JVM:Maven
pom.xml带有<packaging>jar</packaging>或<packaging>war</packaging>以及一个main类;Gradleapplication插件或mainClass设置 - .NET:
.csproj/.fsproj带有<OutputType>Exe</OutputType>或<OutputType>WinExe</OutputType> - 通用 (General):Dockerfile、可运行的入口点、没有打算供其他项目导入的公共 API 接口
- 前端 (Frontend):
- 库 (Libraries):可被其他项目消费的可重用包。常见标志:
package.json中有"main"/"exports",Maven/Gradle 打包为库 jar,.NET<OutputType>Library</OutputType>,打算供其他包导入的具名导出。
目标目录规则 (Destination directory rules):
- 应用程序 →
apps/<name>。检查工作区 glob 模式(例如pnpm-workspace.yaml、根目录package.json中的workspaces)是否已有apps/*条目。- 如果 不存在
apps/*,在导入前添加它:更新工作区 glob 配置并提交(或暂存)更改。 - 示例:
nx import <source> apps/my-app --source=packages/my-app
- 如果 不存在
- 库 → 遵循目标目录的现有约定(
packages/、libs/等)。
常见问题 (Common Issues)
pnpm 工作区 Glob 模式 (pnpm Workspace Globs) (关键)
nx import 会将导入的目录本身(例如 apps)添加到 pnpm-workspace.yaml,而不是 其中的包 glob 模式。跨包导入会失败,报错 Cannot find module。
修复 (Fix):将其替换为源配置中的正确 glob 模式(例如 apps/*、libs/shared/*),然后 pnpm install。
根依赖和配置未被导入 (Root Dependencies and Config Not Imported) (关键)
nx import 不会 从源根目录合并以下内容:
package.json中的dependencies/devDependenciesnx.json中的targetDefaults(例如"@nx/esbuild:esbuild": { "dependsOn": ["^build"] }— 对构建顺序至关重要)nx.json中的namedInputs(例如排除测试文件的production模式)nx.json中的插件配置
修复 (Fix):对比源和目标目录的 package.json 和 nx.json。添加缺失的依赖,合并相关的 targetDefaults 和 namedInputs。
TypeScript 项目引用 (TypeScript Project References)
导入后,运行 nx sync --yes。如果它报告没有变化但类型检查仍然失败,请先运行 nx reset,然后再运行 nx sync --yes。
显式 Executor 路径修复 (Explicit Executor Path Fixups)
推断的目标(通过 Nx 插件)相对于项目根目录解析配置 — 无需更改。显式的 executor 目标(例如 @nx/esbuild:esbuild)具有工作区根目录的相对路径(main、outputPath、tsConfig、assets、sourceRoot),这些路径必须加上导入目标目录的前缀。
插件检测 (Plugin Detection)
- 整个仓库导入 (Whole-repo import):
nx import会检测并提供安装插件的选项。接受它们。 - 子目录导入 (Subdirectory import):插件不会自动检测。使用
npx nx add @nx/PLUGIN手动添加。检查include/exclude模式 — 默认模式不匹配替代目录(例如apps-beta/)。 - 任何插件配置更改后运行
npx nx reset。
冗余的根文件(仅整个仓库导入)(Redundant Root Files – Whole-Repo Only)
整个仓库导入会将源的所有根文件带入目标子目录。清理:
pnpm-lock.yaml— 过时;目标有自己的锁文件pnpm-workspace.yaml— 源工作区配置;与目标冲突node_modules/— 指向源文件系统的过时符号链接.gitignore— 与目标根目录的.gitignore重复nx.json— 源 Nx 配置;目标有自己的README.md— 可选;保留或删除
不要盲目删除 tsconfig.base.json — 导入的项目可能通过相对路径扩展它。
根 ESLint 配置缺失(子目录导入)(Root ESLint Config Missing – Subdirectory Import)
子目录导入不会带入源的根目录 eslint.config.mjs,但项目配置会引用 ../../eslint.config.mjs。
修复顺序 (Fix order):
- 首先安装 ESLint 依赖:
pnpm add -wD eslint@^9 @nx/eslint-plugin typescript-eslint(加上特定框架的插件) - 创建根目录
eslint.config.mjs(从源复制或使用@nx/eslint-plugin基础规则创建) - 然后运行
npx nx add @nx/eslint以在nx.json中注册插件
显式安装 typescript-eslint — pnpm 的严格提升不会自动解析 @nx/eslint-plugin 的这个传递依赖。
ESLint 版本固定 (ESLint Version Pinning) (关键)
将 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" } } }
依赖版本冲突 (Dependency Version Conflicts)
导入后,比较关键依赖(typescript、eslint、特定框架)。如果目标使用更新的版本,将导入的包升级以匹配(通常是安全的)。如果源版本更新,可能需要先升级目标。如果需要,使用 pnpm.overrides 强制执行单一版本策略。
模块边界 (Module Boundaries)
导入的项目可能缺少 tags。添加标签或更新 @nx/enforce-module-boundaries 规则。
项目名称冲突(多次导入)(Project Name Collisions – Multi-Import)
源和目标中 package.json 的相同 name 会导致 MultipleProjectsWithSameNameError。修复 (Fix):重命名冲突的名称(例如 @org/api → @org/teama-api),更新所有依赖引用和 import 语句,然后 pnpm install。每个导入仓库的根目录 package.json 也会成为一个项目 — 也要重命名它们。
工作区依赖导入顺序 (Workspace Dep Import Ordering)
如果在导入过程中某个 "workspace:*" 依赖尚未被导入,pnpm install 会失败。文件操作仍然成功。修复 (Fix):先导入所有项目,然后运行 pnpm install --no-frozen-lockfile。
.gitkeep 阻碍子目录导入 (.gitkeep Blocking Subdirectory Import)
TS 预设会创建 packages/.gitkeep。在导入前删除它并提交。
前端 tsconfig 基础设置 (Frontend tsconfig Base Settings) (关键)
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",对于混合框架则按项目配置
对于子目录导入 (subdirectory imports),目标根目录的 tsconfig 是权威的 — 更新它。对于整个仓库导入 (whole-repo imports),导入的项目可能会扩展它们自己嵌套的 tsconfig.base.json,这使得这个问题不那么关键。
如果目标也有需要 nodenext 的后端项目,请使用按项目覆盖,而不是更改根配置。
注意 (Gotcha):TypeScript 不会合并 lib 数组 — 项目级别的覆盖会完全替换基础数组。在任何项目级别的 lib 中,始终包含所有需要的条目(例如 es2022、dom、dom.iterable)。
@nx/react 库的类型定义 (@nx/react Typings for Libraries)
使用 @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。
修复 (Fix):pnpm add -wD @nx/react
Jest 预设缺失(子目录导入)(Jest Preset Missing – Subdirectory Import)
Nx 预设会在工作区根目录创建 jest.preset.js,项目 jest 配置会引用它(例如 ../../jest.preset.js)。子目录导入不会带入这个文件。
修复 (Fix):
- 运行
npx nx add @nx/jest— 在nx.json中注册@nx/jest/plugin并更新namedInputs - 在工作区根目录创建
jest.preset.js(内容见references/JEST.md)—nx add仅在运行生成器时才会创建此文件,而不是在纯粹的nx add时 - 安装测试运行器依赖:
pnpm add -wD jest jest-environment-jsdom ts-jest @types/jest - 根据需要安装特定框架的测试依赖(参见
references/JEST.md)
对于更深入的 Jest 问题(tsconfig.spec.json、Babel 转换、CI 原子化、Jest 与 Vitest 共存),请参阅 references/JEST.md。
目标名称前缀(整个仓库导入)(Target Name Prefixing – Whole-Repo Import)
当导入一个带有现有 npm 脚本(build、dev、start、lint)的项目时,Nx 插件会为推断的目标名称自动添加前缀以避免冲突:例如 next:build、vite:build、eslint:lint。
修复 (Fix):从导入的 package.json 中删除由 Nx 重写的 npm 脚本,然后选择:
- 接受带前缀的名称(例如
nx run app:next:build) - 在
nx.json中重命名插件目标名称,以使用不带前缀的名称
非 Nx 源问题 (Non-Nx Source Issues)
当源是没有 nx.json 的普通 pnpm/npm 工作区时。
npm 脚本重写 (npm Script Rewriting) (关键)
Nx 在初始化期间会重写 package.json 脚本,创建错误的命令(例如 vitest run → nx test run)。修复 (Fix):删除所有被重写的脚本 — Nx 插件从配置文件推断目标。
noEmit → composite + emitDeclarationOnly (关键)
普通的 TS 项目使用 "noEmit": true,这与 Nx 项目引用不兼容。
症状 (Symptoms):“typecheck target is disabled because one or more project references set ‘noEmit: true’”或 TS6310 错误。
在所有导入的 tsconfig 中修复 (Fix in all imported tsconfigs):
- 删除
"noEmit": true。如果通过 extends 链继承,显式设置"noEmit": false。 - 添加
"composite": true、"emitDeclarationOnly": true、"declarationMap": true - 添加
"outDir": "dist"和"tsBuildInfoFile": "dist/tsconfig.tsbuildinfo" - 如果缺失,添加
"extends": "../../tsconfig.base.json"。删除现在从基础继承的设置。
过时的 node_modules 和锁文件 (Stale node_modules and Lockfiles)
nx import 可能带入 node_modules/(指向源文件系统的 pnpm 符号链接)和来自源的 pnpm-lock.yaml。两者都已过时。
修复 (Fix):rm -rf imported/node_modules imported/pnpm-lock.yaml imported/pnpm-workspace.yaml imported/.gitignore,然后 pnpm install。
ESLint 配置处理 (ESLint Config Handling)
- 旧版
.eslintrc.json(ESLint 8):删除所有.eslintrc.*,移除 v8 依赖,创建扁平配置eslint.config.mjs。 - 扁平配置 (
eslint.config.js):自包含的配置通常可以保留原样。 - 无 ESLint:从零开始创建根和项目级别的配置。
TypeScript paths 别名 (TypeScript paths Aliases)
Nx 使用 package.json "exports" + pnpm 工作区链接,而不是 tsconfig "paths"。如果包有正确的 "exports",则 paths 是多余的。否则,为新的目录结构更新 paths。
技术特定指南 (Technology-specific Guidance)
识别源仓库中的技术,然后阅读并应用匹配的参考文件。
可用参考:
references/ESLINT.md— ESLint 项目:重复的lint/eslint:lint目标、遗留的.eslintrc.*对生成文件进行 lint、自 lint 的扁平配置.cjs、typescript-eslintv7/v9 对等依赖冲突、在同一工作区中混合 ESLint v8+v9。references/GRADLE.mdreferences/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")、通过错误的包管理器自动安装依赖、非 Nxcreate-next-app导入、Next.js+Vite 混合共存。references/TURBOREPO.mdreferences/VITE.md— Vite 项目(React、Vue 或两者):@nx/vite/plugintypecheck 目标、resolve.alias/__dirname修复、框架依赖、Vue 特定设置、React+Vue 混合共存。
📄 原始文档
完整文档(英文):
https://skills.sh/nrwl/nx-ai-agents-config/nx-import
💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。

评论(0)