TypeScript(tsconfig.json - references)

在 TypeScript 中,references(项目引用)是用于管理多项目依赖关系 的核心配置,通过 tsconfig.json 中的 references 字段实现。其核心作用是将大型项目拆分为多个独立子项目(如工具库、业务模块、UI 组件库等),支持子项目间的隔离编译、依赖复用,同时提升整体编译效率(仅重新编译修改的子项目)。

使用示例:

json 复制代码
{
  "references": [
    { "path": "../utils/tsconfig.json" } 
  ]
}

一、使用前提

要使用 references,被引用的子项目(依赖项)必须满足以下约束:

  1. 子项目的 tsconfig.json 中需设置 "composite": true(启用复合项目模式,允许被其他项目引用);
  2. 子项目需明确指定 "rootDir"(源代码根目录)和 "outDir"(编译输出目录),确保输出文件结构可被引用方识别;
  3. 建议开启 "declaration": true(生成 .d.ts 类型声明文件),确保引用方能获取类型提示。

二、核心配置字段

1. 引用方配置(references 字段)

在需要依赖其他子项目的「引用方项目」的 tsconfig.json 中,通过 references 数组声明依赖,每个依赖项包含以下属性:

  • path(必填):指向被引用子项目的 tsconfig.json 文件路径(相对路径或绝对路径);
  • prepend(可选,默认 true):若为 true,被引用项目的编译输出会自动添加到引用方的模块查找路径中,无需手动配置 baseUrlpaths

2. 被引用方配置(复合项目约束)

被引用的「子项目」的 tsconfig.json 需包含以下关键配置:

json

json 复制代码
{
  "compilerOptions": {
    "composite": true,        // 启用复合项目,允许被引用
    "rootDir": "./src",       // 源代码根目录(必须明确)
    "outDir": "./dist",       // 编译输出目录(必须明确)
    "declaration": true,      // 生成 .d.ts 类型声明(推荐)
    "declarationMap": true    // 生成类型声明的源映射(可选,便于调试)
  },
  "include": ["./src/**/*"]   // 明确包含的源代码文件
}

三、使用步骤与示例

假设我们有一个大型项目,拆分为 3 个子项目,结构如下:

plaintext

scss 复制代码
my-monorepo/                // 根目录(可包含根 tsconfig.json,也可仅作为文件夹)
├─ packages/
│  ├─ utils/                // 子项目 1:工具库(被依赖项)
│  │  ├─ src/               // utils 源代码
│  │  │  └─ math.ts         // 工具函数(如 add 方法)
│  │  └─ tsconfig.json      // utils 的配置(复合项目)
│  ├─ components/           // 子项目 2:UI 组件库(依赖 utils)
│  │  ├─ src/               // components 源代码
│  │  │  └─ Button.tsx      // UI 组件(使用 utils 的 add 方法)
│  │  └─ tsconfig.json      // components 的配置(引用 utils)
│  └─ app/                  // 子项目 3:主应用(依赖 utils 和 components)
│     ├─ src/               // app 源代码
│     │  └─ index.tsx       // 主应用入口(使用 components 的 Button)
│     └─ tsconfig.json      // app 的配置(引用 utils 和 components)
└─ package.json             // 根项目依赖(可选,用于管理 monorepo 依赖)

步骤 1:配置被引用方(utils 子项目)

packages/utils/tsconfig.json(复合项目配置):

json

json 复制代码
{
  "compilerOptions": {
    "target": "es2015",
    "module": "commonjs",
    "composite": true,        // 启用复合项目
    "rootDir": "./src",       // 源代码根目录
    "outDir": "./dist",       // 编译输出到 dist 目录
    "declaration": true,      // 生成 .d.ts 类型声明
    "strict": true
  },
  "include": ["./src/**/*"],  // 包含所有 src 下的文件
  "exclude": ["node_modules"]
}

packages/utils/src/math.ts 中编写工具函数:

typescript

typescript 复制代码
// 工具函数:加法
export const add = (a: number, b: number): number => a + b;

步骤 2:配置引用方 1(components 子项目,依赖 utils)

packages/components/tsconfig.json(声明对 utils 的引用):

json

json 复制代码
{
  "compilerOptions": {
    "target": "es2015",
    "module": "commonjs",
    "jsx": "react-jsx",       // 假设是 React 组件库
    "rootDir": "./src",
    "outDir": "./dist",
    "declaration": true,
    "strict": true
  },
  "include": ["./src/**/*"],
  "exclude": ["node_modules"],
  // 声明依赖:引用 utils 子项目
  "references": [
    { "path": "../utils/tsconfig.json" }  // 指向 utils 的 tsconfig 路径
  ]
}

packages/components/src/Button.tsx 中使用 utils 的 add 函数:

tsx

typescript 复制代码
// 导入 utils 的 add 函数(无需配置 paths,因 references.prepend 默认 true)
import { add } from "@my-monorepo/utils";  // 假设 utils 在 package.json 中声明为 "@my-monorepo/utils"
// 或相对路径:import { add } from "../utils/dist/src/math";(不推荐,references 会自动处理路径)

interface ButtonProps {
  count: number;
}

export const Button = ({ count }: ButtonProps) => {
  // 使用 utils 的 add 函数
  const handleClick = () => alert(`新计数:${add(count, 1)}`);
  return <button onClick={handleClick}>点击加 1</button>;
};

步骤 3:配置引用方 2(app 主应用,依赖 utils 和 components)

packages/app/tsconfig.json(声明对 utils 和 components 的引用):

json

json 复制代码
{
  "compilerOptions": {
    "target": "es2015",
    "module": "commonjs",
    "jsx": "react-jsx",
    "rootDir": "./src",
    "outDir": "./dist",
    "strict": true
  },
  "include": ["./src/**/*"],
  "exclude": ["node_modules"],
  // 声明多个依赖:utils 和 components
  "references": [
    { "path": "../utils/tsconfig.json" },
    { "path": "../components/tsconfig.json" }
  ]
}

packages/app/src/index.tsx 中使用 components 的 Button 组件:

tsx

javascript 复制代码
import { Button } from "@my-monorepo/components";  // 导入 UI 组件
import React from "react";
import ReactDOM from "react-dom/client";

const root = ReactDOM.createRoot(document.getElementById("root")!);
root.render(
  <React.StrictMode>
    {/* 使用 components 的 Button 组件,传递 count 属性 */}
    <Button count={0} />
  </React.StrictMode>
);

步骤 4:编译与运行

  1. 单独编译子项目 :进入某个子项目目录,执行 tsc 即可编译(如编译 utils:cd packages/utils && tsc);

  2. 编译所有依赖项目 :在引用方项目中执行 tsc --build(缩写 tsc -b),TypeScript 会自动编译所有被引用的子项目(若子项目已编译且无修改,则跳过);

    • 示例:在 app 目录执行 tsc -b,会先检查 utils 和 components 是否最新,若未编译则自动编译,再编译 app;
  3. 运行主应用 :编译完成后,执行 app 的输出文件(如 node packages/app/dist/src/index.js,或根据框架配置启动)。

四、常见场景与注意事项

1. 场景扩展:根项目统一管理

若需要统一编译所有子项目,可在根目录创建 tsconfig.json,通过 references 包含所有子项目,实现「一键编译全部」:

json

json 复制代码
// 根目录 tsconfig.json
{
  "files": [],  // 根项目无源代码,仅用于管理引用
  "references": [
    { "path": "./packages/utils" },
    { "path": "./packages/components" },
    { "path": "./packages/app" }
  ]
}

执行 tsc -b 即可从根目录编译所有子项目。

2. 注意事项

  • 避免循环引用:不可出现 A 引用 B、B 引用 A 的循环依赖,会导致编译错误;

  • 路径正确性references.path 必须指向被引用项目的 tsconfig.json 文件(而非文件夹,若指向文件夹,TypeScript 会自动查找其中的 tsconfig.json);

  • composite 必开启 :被引用项目若未设置 "composite": true,引用方会报错;

  • 类型声明依赖 :若被引用项目未开启 "declaration": true,引用方可能无法获取类型提示(仅能运行,但失去 TypeScript 类型检查能力)。

通过 references,可将大型项目拆分为高内聚、低耦合的子模块,不仅提升编译效率,还便于团队协作(不同团队维护不同子项目),是 TypeScript 大型应用的最佳实践之一。

相关推荐
duansamve8 小时前
React 18+TS中使用Cesium 1.95
react.js·typescript·cesium
岁岁岁平安9 小时前
SpringBoot3+WebSocket+Vue3+TypeScript实现简易在线聊天室(附完整源码参考)
java·spring boot·websocket·网络协议·typescript·vue
简小瑞2 天前
VSCode 源码解密:一个"无用"属性背后的精妙设计
typescript·visual studio code
FogLetter2 天前
TypeScript 泛型:让类型也拥有“函数式”超能力
前端·typescript
Keepreal4962 天前
Typescript中type和interface的区别
前端·typescript
huangql5202 天前
UniApp + Vite + Vue3 + TypeScript 项目中 ESLint 与 Prettier 的完整配置指南
vue.js·typescript·团队开发·代码规范
带娃的IT创业者3 天前
TypeScript + React + Ant Design 前端架构入门:搭建一个 Flask 个人博客前端
前端·react.js·typescript
星光不问赶路人3 天前
project references在tsserver内工作流程
typescript·visual studio code
keep_di4 天前
05-vue3+ts中axios的封装
前端·vue.js·ajax·typescript·前端框架·axios
RoyLin4 天前
SurrealDB - 统一数据基础设施
前端·后端·typescript