Read the associated blog post for complete information.
In development, your TypeScript code should feel "alive". When you update your code in one file, the effects of that change should propogate to all files that import it.
This is true even for monorepos, where you may not be importing things from a file, but from a local package.
- import { Fish } from "../pkg-a/index";
+ import { Fish } from "pkg-a"This repo contains a few strategies you can use to make your TypeScript monorepo feel more alive.
Each subdirectory contains a pnpm monorepo (pnpm-workspace.yaml) with two packages, pkg-a and pkg-b. pkg-b has a dependency on pkg-a. Each package has a tsconfig.json that extends a tsconfig.base.json in the root of the monorepo.
The file structure looks something like this:
.
├── package.json
├── packages
│ ├── pkg-a
│ │ ├── index.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│ └── pkg-b
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── tsconfig.base.json
└── tsconfig.jsonLet's break down the approaches. (Refer to the associated blog post for complete breakdowns.)
Use TypeScript project references to link packages together. This has a lot of downsides and doesn't play nice with node or other tooling out of the box.
Use publishConfig in package.json to specify .ts file in development and .js file in production.
Configure compilerOptions.paths in tsconfig.json to override resolution for local package names.
Using tshy's liveDev mode to hard-link the .ts source code directly into ./dist/esm and ./dist/commonjs directories. This lets VS Code discover your live TypeScript source code without any additional package.json configuration.
Recommended User-defined conditional export in package.json#exports plus customConditions in tsconfig.json
To play around with a particular approach, clone this repo and navigate to the appropriate subdirectory.
$ gh repo clone colinhacks/live-typescript-monorepo
$ cd live-typescript-monorepo
$ cd <subdir> # tsconfig-paths, publishconfig, project-references, custom-conditionsThen run the following commands:
$ pnpm i # install
$ code . # open in VS CodeOnce the project is open in VS Code, open packages/pkg-a/index.ts and packages/pkg-b/index.ts. When you change the definition of Fish in pkg-a, those changes should propagate immediately to pkg-b without a build step.
Each subdirectory also contains a "test" script that executes pkg-b/index.ts. (This won't work in project-references.) This should execute the latest .ts files for both pkg-a and pkg-b! Make some changes and see the effects.
pnpm testHappy monorepo hacking!