41
loading...
This website collects cookies to deliver better user experience
libs/types
package. It's quite straightforward to set up compiling:tsconfig.json
has the outDir
field specified, that's the folder Javascript gets output to:$ cd libs/types
$ cat tsconfig.json
"compilerOptions": {
"outDir": "./dist"
build
script:$ cat package.json
"scripts": {
"build": "tsc -b"
$ pnpm build
$ tree dist
dist
├── index.d.ts
├── index.js
└── index.js.map
package.json
entry-point fields are set to point to the files in the dist
folder:$ cat package.json
"main": "dist/index.js",
"types": "dist/index.d.ts",
webby
├── apps
│ ├── api
│ │ ├── package.json
│ │ ├── prisma/
│ │ ├── src/
│ │ └── tsconfig.json
│ └── web
│ ├── package.json
│ ├── src/
│ ├── tsconfig.json
│ └── typings/
├── libs
│ ├── analytics
│ │ ├── jest.config.js
│ │ ├── package.json
│ │ ├── src/
│ │ └── tsconfig.json
│ ├── logging
│ │ ├── package.json
│ │ ├── src/
│ │ └── tsconfig.json
│ └── types
│ ├── package.json
│ ├── src/
│ └── tsconfig.json
├── package.json
└── tsconfig.json
ℹ️ This project is prepared on GitHub1s if you'd like to familiarize yourself with the code.
build
script across all packages quite easy:$ cd ../..
$ pnpm install
Scope: all 6 workspace projects
$ pnpm -r run build
Scope: all 6 workspace projects
web
work now?$ cd apps/web
$ pnpm start
[razzle] > Started on port 3000
api
?$ cd ../api
$ pnpm start
[api] > prisma generate && nodemon -w src/* -x 'ts-node src/api.ts'
[api] Error: Command failed with exit code 1: npm install -D [email protected]
[api] ERROR Command failed with exit code 1.
Command failed: npm install
when we're using pnpm??package.json
's dependencies, does that make api
work?$ pnpm install
- @prisma/client 2.26.0
+ @prisma/client 2.27.0-integration-fix-sdk-pnpm.2
- prisma 2.26.0
+ prisma 2.27.0-integration-fix-sdk-pnpm.2
$ pnpm start
[api] api started at http://localhost:3002
$ cd ../..
$ git clean -dxi .; # this prompts you for what to delete so it's safe to run
$ pnpm install && pnpm build
$ pnpm start
apps/web start: [razzle] > Started on port 3000
apps/api start: [api] api started at http://localhost:3002
By building the code we are no longer bound to writing it in Typescript. Any language that compiles to Javascript will do. So encapsulation of each project has increased, which I'll count as wonderful.
This allows us a lot of flexibility in what a library produces: For this article-series the libraries are just groupings of code, their built code is identical in function to the source. But what if we imagine we wanted to generate something different than the source-code? What if we had a library whose source-code downloads Swagger documentation from some remote API and generate a Javascript client? To do that we must have a build step, and with this article's approach building is now a "first-class concept" so we don't have to make weird one-off exceptions to support something like that.
I really appreciate the simplicity of boiling everything down to Javascript, there's just that much less chance of anything going wrong.
We now have a workflow where changes to a library aren't reflected in consumers until the library gets rebuilt. So we have to remember to run pnpm build
after every change 😬. That's not good because it's so easy to forget, and then whatever work we've just done will seem like it's missing in the consumer in possibly subtle and confusing ways. I don't know you so maybe you wouldn't have a problem with this, but I think for newcomers and juniors it'll be that little extra annoyance that we are so desperately trying to avoid.
We end up with boilerplate code and configurations that are identical across all projects, e.g. tsconfig.json
must specify outDir
and package.json
must have a build
script + specify main
& types
fields… it's just an annoying amount of small details that have to be exactly right and it gets worse the more projects we add.
apps/web
runs start
it would first go out and rebuild its dependencies.