Switch to Workspaces and Project References

In order to take advantage of the performance benefits of TypeScript project references, you need to use package manager workspaces for local project linking. If you are currently using TypeScript path aliases for project linking, follow the steps in this guide to switch to workspaces project linking and enable TypeScript project references.

Enable Package Manager Workspaces

Follow the specific instructions for your package manager to enable workspaces project linking.

package.json
1{ 2 "workspaces": ["apps/**", "libs/**"] 3} 4

Defining the workspaces property in the root package.json file lets npm know to look for other package.json files in the specified folders. With this configuration in place, all the dependencies for the individual projects will be installed in the root node_modules folder when npm install is run in the root folder. Also, the projects themselves will be linked in the root node_modules folder to be accessed as if they were npm packages.

Update Root TypeScript Configuration

The root tsconfig.base.json should contain a compilerOptions property and no other properties. compilerOptions.composite and compilerOptions.declaration should be set to true. compilerOptions.paths should not be set.

Note: Before you delete the paths property, copy the project paths for use in the tsconfig.json file.

tsconfig.base.json
1{ 2 "compilerOptions": { 3 "allowJs": false, 4 "allowSyntheticDefaultImports": true, 5 // ... 6 "paths": { 7 "@myorg/utils": ["libs/utils/src/index.ts"], 8 "@myorg/ui": ["libs/ui/src/index.ts"] 9 } 10 } 11} 12

The root tsconfig.json file should extend tsconfig.base.json and not include any files. It needs to have references for every project in the repository so that editor tooling works correctly.

tsconfig.json
1{ 2 "extends": "./tsconfig.base.json", 3 "files": [] // intentionally empty 4} 5

Create Individual Project package.json files

When using package manager project linking, every project needs to have a package.json file. The only required property of the package.json is the name, so you can leave all the task configuration in the existing project.json file.

libs/ui/package.json
1{ 2 "name": "@myorg/ui" 3} 4
Package Names with Multiple Slashes

The package.json name can only have one / character in it. This is more restrictive than the TypeScript path aliases. So if you have a project that you have been referencing with @myorg/shared/ui, you'll need to make the package.json name be something like @myorg/shared-ui and update all the import statements in your codebase to reference the new name.

Update Individual Project TypeScript Configuration

Each project's tsconfig.json file should extend the tsconfig.base.json file and list references to the project's dependencies.

libs/ui/tsconfig.json
1{ 2 "extends": "../../tsconfig.base.json", 3 "files": [], // intentionally empty 4 "references": [ 5 // All project dependencies 6 // UPDATED BY NX SYNC 7 // This project's other tsconfig.*.json files 8 { 9 "path": "./tsconfig.lib.json" 10 }, 11 { 12 "path": "./tsconfig.spec.json" 13 } 14 ] 15} 16

Each project's tsconfig.lib.json file extends the project's tsconfig.json file and adds references to the tsconfig.lib.json files of project dependencies.

libs/ui/tsconfig.lib.json
1{ 2 "extends": "./tsconfig.json", 3 "compilerOptions": { 4 // Any overrides 5 }, 6 "include": ["src/**/*.ts"], 7 "exclude": [ 8 // exclude config and test files 9 ], 10 "references": [ 11 // tsconfig.lib.json files for project dependencies 12 // UPDATED BY NX SYNC 13 ] 14} 15

The project's tsconfig.spec.json does not need to reference project dependencies.

libs/ui/tsconfig.spec.json
1{ 2 "extends": "./tsconfig.json", 3 "compilerOptions": { 4 // Any overrides 5 }, 6 "include": [ 7 // test files 8 ], 9 "references": [ 10 // tsconfig.lib.json for this project 11 { 12 "path": "./tsconfig.lib.json" 13 } 14 ] 15} 16

After creating these tsconfig.*.json files, run nx sync to have Nx automatically add the correct references for each project.

Future Plans

We realize that this manual migration process is tedious. We are investigating automating parts of this process with generators.