TypeScript Project References npm 包构建小实践

npm 包输出 es/cjs 产物

在开发一个 npm 包时,通常需要同时输出 ES 模块和 CommonJS 模块的产物供不同的构建进行使用。在只使用tsc进行产物编译的情况下,我们通常可以通过配置两个独立的 tsconfig.json 配置文件,并在一个 npm script 中 执行两次 tsc 命令来实现

项目结构

假设我们的项目结构如下:

yaml 复制代码
my-package/
├── src/
│   └── index.ts
├── dist/
│   ├── es/
│   └── cjs/
├── package.json
├── tsconfig.es.json
└── tsconfig.cjs.json

配置 TypeScript

tsconfig.es.json

为 ES 模块创建一个 tsconfig.es.json 文件:

json 复制代码
{
    "compilerOptions": {
        "rootDir": "src",
        "module": "ESNext",
        "moduleResolution": "Node",
        "outDir": "dist/es"
    },
    "include": ["src"]
}

tsconfig.cjs.json

为 CommonJS 模块创建一个 tsconfig.cjs.json 文件:

json 复制代码
{
    "compilerOptions": {
        "rootDir": "src",
        "module": "CommonJS",
        "moduleResolution": "Node",
        "outDir": "dist/cjs"
    },
    "include": ["src"]
}

配置构建脚本

在 package.json 中,我们可以添加以下脚本来构建我们的项目,执行两次 tsc 并分别指定不同的配置文件

json 复制代码
{
    "scripts": {
        "build": "tsc -p tsconfig.es.json && tsc -p tsconfig.cjs.json",
    }
}

通过运行 npm run build,可以生成同时包含 ES 模块和 CommonJS 模块的产物

TypeScript 的 references 是什么

TypeScript 的项目引用(Project References)是 TypeScript 3.0 引入的一项功能,允许一个 TypeScript 项目引用另一个 TypeScript 项目。这使得我们可以将大型代码库拆分为多个较小的项目,并且这些项目可以相互依赖

Project References 的好处

  • 增量编译:当项目引用被正确配置时,TypeScript 只会重新编译发生变化的部分,从而大幅提升编译速度。
  • 模块化:通过项目引用,可以将代码库拆分为多个独立的、可复用的模块,提升代码的可维护性和可读性。
  • 类型安全:项目引用确保了项目之间的类型安全,避免了类型不一致的问题。

配置

要使用项目引用,需要在 tsconfig.json 中添加 references 字段。例如:

json 复制代码
{
  "compilerOptions": {
    "composite": true,
    "declaration": true,
    "outDir": "./dist"
  },
  "include": ["src"],
  "references": [
    { "path": "../other-project" }
  ]
}

相应的子项目需要存在相应的tsconfig.json配置,并且配置compilerOptions.composite=true,这样才能被主项目引用。如

json 复制代码
{
    "compilerOptions": {
        "composite": true,
        "types": [],
        "rootDir": "src",
        "module": "ESNext",
        "moduleResolution": "Node",
        "outDir": "dist"
    }
}

使用 TypeScript 的 references 后如何实现一个命令 tsc 输出 ES 和 CommonJS 产物并且提升增量编译的性能

仍以上面的项目结构为例子,我们使用 TypeScript 的项目引用来实现这个需求。

项目结构

假设我们的项目结构如下:

yml 复制代码
my-package/
├── src/
│   └── index.ts
├── dist/
│   ├── es/
│   └── cjs/
├── package.json
├── tsconfig.json
├── tsconfig.base.json
├── tsconfig.es.json
└── tsconfig.cjs.json

首先,我们需要在根目录下创建一个 tsconfig.json 文件,用于配置项目引用:

json 复制代码
{
  "files": [],
  "references": [
    { "path": "./tsconfig.es.json" },
    { "path": "./tsconfig.cjs.json" }
  ]
}

配置 tsconfig.es.json

为 ES 模块创建一个 tsconfig.es.json 文件:

json 复制代码
{
    "extends": "./tsconfig.base.json",
    "compilerOptions": {
      "outDir": "./dist/es",
      "module": "ESNext"
    }
  }

配置 tsconfig.cjs.json

为 CommonJS 模块创建一个 tsconfig.cjs.json 文件:

json 复制代码
{
    "extends": "./tsconfig.base.json",
    "compilerOptions": {
      "outDir": "./dist/cjs",
      "module": "CommonJS"
    }
}

公共配置 tsconfig.base.json

为了避免重复配置,我们可以创建一个 tsconfig.base.json 文件,包含通用的配置:

json 复制代码
{
  "compilerOptions": {
    "target": "ES5",
    "declaration": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "composite": true,
    "rootDir": "src"
  },
  "include": ["src"]
}

构建脚本

在 package.json 中,我们可以添加以下脚本来构建我们的项目

json 复制代码
{
  "scripts": {
    "build": "tsc -b"
  }
}

此时我们不再需要执行两次 tsc 命令,而是只需要执行一次 tsc -b 命令即可输出符合我们需求的 es + cjs 产物(和上面的两次执行 tsc 是一样的效果)。

在这个场景下 TypeScript 会根据项目引用的配置,自动构建 ES 模块和 CommonJS 模块,并且只会重新编译发生变化的部分,从而提升增量编译的性能

相关推荐
江城开朗的豌豆8 分钟前
Vue-router方法大全:让页面跳转随心所欲!
前端·javascript·vue.js
江城开朗的豌豆20 分钟前
Vue路由动态生成秘籍:让你的链接'活'起来!
前端·javascript·vue.js
晓得迷路了21 分钟前
栗子前端技术周刊第 88 期 - Apache ECharts 6.0 beta、Deno 2.4、Astro 5.11...
前端·javascript·echarts
江城开朗的豌豆26 分钟前
在写vue公用组件的时候,怎么提高可配置性
前端·javascript·vue.js
江城开朗的豌豆27 分钟前
Vue路由跳转的N种姿势,总有一种适合你!
前端·javascript·vue.js
江城开朗的豌豆27 分钟前
Vue路由玩法大揭秘:三种路由模式你Pick谁?
前端·javascript·vue.js
江城开朗的豌豆28 分钟前
Vue路由守卫全攻略:给页面访问装上'安检门'
前端·javascript·vue.js
前端 贾公子36 分钟前
monorepo + Turborepo --- 开发应用程序
java·前端·javascript
江城开朗的豌豆40 分钟前
Vue路由传参避坑指南:params和query的那些猫腻
前端·javascript·vue.js
十里青山1 小时前
超好用的vue图片预览插件更新啦,hevue-img-preview 7.0.0版本正式发布,支持vue2/vue3/移动/pc,增加缩略图、下载、自定义样式等
前端·javascript·vue.js