Skip to content

Instantly share code, notes, and snippets.

@jbsulli
Last active March 21, 2024 16:24
Show Gist options
  • Save jbsulli/881cb2e5d5d9c4e5e5d8736755c11ffb to your computer and use it in GitHub Desktop.
Save jbsulli/881cb2e5d5d9c4e5e5d8736755c11ffb to your computer and use it in GitHub Desktop.
Typescript Yarn 3 Plug'n'Play zero-install monorepo for VSCode

Setup nvm

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
source ~/.bashrc

Setup node

nvm install 18.14.2
nvm use 18.14.2

Add yarn

corepack enable

Create directory

mkdir hello-world
cd hello-world

Use berry

yarn init -2

(I then deleted .editorconfig... seemed redundant)

Edit package.json

{
  "packageManager": "[email protected]",
  "private": true,
  "workspaces": [
    "packages/hello-world"
  ]
}

Add typescript to the root

yarn add --dev typescript

Add PnP Support to VSCode

yarn dlx @yarnpkg/sdks vscode

Note: it's important that you have typescript installed at the root so that this step installs typescript sdk to .yarn/sdks/typescript. This is what VSCode will use to handle the Plug'n'Play (PnP) modules. Otherwise, you'll get a lot of Cannot find type definition file for ... errors and lose your mind trying to figure out why (like I did).

Add package folder

mkdir packages
cd packages
mkdir hello-world
cd hello-world

Init package

yarn init

Add Typescript

yarn add --dev typescript

Add tsconfig.json

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "alwaysStrict": true,
    "declaration": true,
    "declarationMap": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "forceConsistentCasingInFileNames": true,
    "importHelpers": true,
    "lib": ["es2017", "DOM"],
    "module": "commonjs",
    "moduleResolution": "node",
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "outDir": ".dist",
    "rootDir": "./src",
    "sourceMap": true,
    "strict": true,
    "strictFunctionTypes": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "target": "ES2017",
    "types": ["node"]
  },
  "exclude": ["node_modules", ".dist", "src/test-util/**/*", "**/*.test.ts", "**/tmp/**/*"],
  "include": ["src/**/*", "types/**/*"]
}

Add node types

yarn add --dev @types/node

Install app deps

yarn add express && yarn add @types/express

Add src/index.ts

Use PnP Typescript Version in VSCode

This is when I got this dialog (DON'T IGNORE!!!):

image

Click allow so that you don't get Cannot find type definition file for ... errors. I think it adds the following to .vscode/settings.json:

{
  // ...
  "typescript.tsdk": ".yarn/sdks/typescript/lib",
  "typescript.enablePromptUseWorkspaceTsdk": true
}

Note: if you miss this dialog, you can open a *.ts file (any TypeScript file... just needs to be focused), hit F1, search for TypeScript: Select TypeScript Version... and select Use Workspace Version. If you don't see a Use Workspace Version option, you need to redo the Add PnP Support to VSCode step above (also, read the note).

Add content to src/index.ts

import express from "express";

console.log("Starting...");

const app = express();
const port = 7777;

app.get("/", (_, res) => {
  res.send("Hello world!");
});

const server = app.listen(port, () => {
  console.log(`Listening on port ${port}`);
});

const shutdown = () => {
  console.log("Shutting down...");

  server.close(() => {
    console.log("Server closed");
  });
};

process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);

Add build script

{
  // ...
  "scripts": {
    "build": "tsc"
  },
  // ...
}

Build

yarn build

Add tslib

I'm using "importHelpers": true in the tsconfig.json so I add:

yarn add tslib

Add start script to package.json

{
  // ...
  "scripts": {
    // ...
    "start": "node ./.dist/index.js"
  }
  // ...
}

Now start your app

yarn start

Note: node ./.dist/index.js will not work because we're using PnP. You would have to use yarn node ./.dist/index.js instead.

Add global build script

Install workspace tools:

yarn plugin import workspace-tools

To build all packages, we can add the following script to the root package.json

{
  // ...
  "scripts": {
    "build": "yarn workspaces foreach -ptv run build"
  }
  // ...
}

Commit files

Probably a good time to save your work. Commit and push to your git repository. Note that yarn init -2 should have created a .gitignore that is set up for zero-install... meaning you'll be commiting a lot of files in .yarn/cache (all your dependency package zips). This is good. It means you just change your branch and go... instead of worrying about if you need to do yarn install.

Everything should look like this: jbsulli/ts-yarn-pnp-zero-install-monorepo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment