Compile Typescript Libraries to Multiple Formats
It can be difficult to set up a typescript library to compile to ESM and CommonJS. As of Nx 16.8, you can use the @nx/rollup:rollup executor to take care of it for you.
Use Rollup to Compile your TypeScript Project
If you do not use Rollup already, install the corresponding Nx plugin as follows:
โฏ
nx add @nx/rollup
Make sure the version of @nx/rollup matches your other @nx/* package versions.
You can then configure Rollup to compile your library by adding a build target to your project.json or package.json file. Here's an example:
1{
2 "name": "my-awesome-lib",
3 "nx": {
4 "targets": {
5 "build": {
6 "executor": "@nx/rollup:rollup",
7 "options": {
8 "main": "packages/my-awesome-lib/src/index.ts"
9 }
10 }
11 }
12 }
13}
14If you happen to use the @nx/js:tsc executor already, you can also use the Rollup configuration generator from the Nx Rollup plugin to automatically configure your project's build target.
Configure Rollup to Create Multiple Formats
You'll need to specify format, additionalEntryPoints and generateExportsField in the executor options. Here's an example:
1{
2 "name": "my-awesome-lib",
3 "targets": {
4 "build": {
5 "executor": "@nx/rollup:rollup",
6 "options": {
7 "main": "packages/my-awesome-lib/src/index.ts",
8 "format": ["esm", "cjs"],
9 "additionalEntryPoints": ["packages/my-awesome-lib/src/foo.ts"],
10 "generateExportsField": true
11 }
12 }
13 }
14}
15After compiling our package using nx build my-awesome-lib we'll get the following output in our dist folder.
1my-awesome-lib
2โโ .
3 โโ README.md
4 โโ foo.cjs.d.ts
5 โโ foo.cjs.js
6 โโ foo.esm.js
7 โโ index.cjs.d.ts
8 โโ index.cjs.js
9 โโ index.esm.js
10 โโ package.json
11 โโ src
12 โโ foo.d.ts
13 โโ index.d.ts
14 โโ lib
15 โโ my-awesome-lib.d.ts
16And our package.json will look like this:
1{
2 "name": "my-awesome-lib",
3 "version": "0.0.1",
4 ...
5 "type": "commonjs",
6 "main": "./index.cjs.js",
7 "typings": "./src/index.d.ts",
8 "exports": {
9 "./package.json": "./package.json",
10 ".": {
11 "import": "./index.esm.js",
12 "default": "./index.cjs.js"
13 },
14 "./foo": {
15 "import": "./foo.esm.js",
16 "default": "./foo.cjs.js"
17 }
18 },
19 "module": "./index.esm.js"
20}
21
22Now consumers of your package can access the appropriate format for their codebase and you don't have to worry about maintaining the infrastructure to compile to both formats.