How to use yarn workspaces with typescript and out folders?
I created a Github Repository to make it easier to follow the following code description:
Code Description
TypeScript Project References
make it possible to compile a TypeScript project that consist of multiple smaller TypeScript projects, each project having a tsconfig.json
file. (Source: Project References Documentation)
TypeScript Setup
We have a root tsconfig.json
file that only manages its sub-projects. The references
property specifies the directories that each contain a valid tsconfig.json
file. If we now build the project with the --build
option (tsc --build tsconfig.json
) then we specified the projects which should be compiled, but we didn't specified the build order in which the projects should be compiled.
{
"references": [
{ "path": "./client" },
{ "path": "./cmd" }
],
"files": [],
"include": [],
"exclude": ["**/node_modules"]
}
To correctly specify the build order we need to add a references
property to the cmd/tsconfig.json
file. This tells the compiler that it first needs to compile client/
before we compile cmd/
:
cmd/tsconfig.json
:
{
"extends": "../tsconfig.packages.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
"references": [
{
"path": "../client"
}
]
}
Build order
client/
^
|
|
cmd/
Node Setup
Best practice is that each sub-project has its own package.json
file with the main
property and the name
set. In our example both packages (cmd/
and client/
) have a main
property pointing to the index.js
file in the TypeScript outDir
directory (cmd/dist/index.js
and client/dist/index.js
).
Project structure:
tsconfig.json
cmd/
tsconfig.json
package.json
src/
index.ts
dist/ #artifacts
index.js
client/
tsconfig.json
package.json
src/
index.ts
dist/ #artifacts
index.js
client/packages.json
{
"name": "client",
"version": "1.0.0",
"main": "dist/index",
...
}
It is important that we add the client/
as dependency to the cmd/packages.json
so the module resolution algorithm can find the client/dist/index.js
when we import it in our TypeScript code import Foo from 'client';
:
cmd/packages.json
{
"name": "cmd",
"version": "1.0.0",
"main": "dist/index",
"dependencies": {
"client": "1.0.0" // important
}
}
cmd/src/index.ts
import Foo from 'client';
console.log(Foo())
Yarn Setup
The yarn setup is easy. Yarn adds all packages under node_modules
instead of:
cmd/node_modules
client/node_modules
To enable yarn workspaces add the workspaces
property and the private: true
property to the <root>/package.json
file.
<root>/package.json
{
"private": true,
"workspaces": [
"cmd",
"client"
],
"name": "yarn_workplace",
"version": "1.0.0"
...
}
The cmd/
and client/
packages are symlinked
under the <root>/node_modules/
directory:
Notes
- To enable code navigation one has to first build the project
- Every package lives on its own. The
cmd/
package uses the definition fileclient/dist/index.d.ts
for type information instead of using the the TypeScript files directly.