Npm Workspace
Directory Structure
.
├── apps
│ └── src
│ ├── dist
│ │ ├── index.d.ts
│ │ └── index.js
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
├── biome.json
├── Makefile
├── node_modules
│ └── *
├── package.json
├── package-lock.json
└── packages
├── fizzbuzz
│ ├── dist
│ │ ├── index.d.ts
│ │ └── index.js
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
└── tsconfig
├── package.json
└── packages
└── tsconfig.json
package.json
json
{
"name": "npm-workspace-test",
"private": true,
"scripts": {
"fmt": "npx @biomejs/biome format --write ./"
},
"workspaces": ["apps/*", "packages/*"],
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"tsx": "^4.19.1"
}
}
apps
ts
import { fizzBuzz } from '@packages/fizzbuzz'
console.log('npm workspace')
console.log(fizzBuzz(100))
package.json
json
{
"name": "@apps/src",
"version": "1.0.0",
"private": true,
"type": "module",
"exports": "./dist/index.js",
"scripts": {
"build": "tsc"
},
"dependencies": {
"@packages/fizzbuzz": "^1.0.0"
},
"devDependencies": {
"@types/node": "^22.7.9",
"typescript": "^5.6.3"
}
}
packages
ts
export const fizzBuzz = (number: number): string => {
if (number % 15 === 0) return 'FizzBuzz'
if (number % 3 === 0) return 'Fizz'
if (number % 5 === 0) return 'Buzz'
return number.toString()
}
package.json
json
{
"name": "@packages/fizzbuzz",
"version": "1.0.0",
"private": true,
"type": "module",
"exports": "./dist/index.js",
"scripts": {
"build": "tsc"
},
"devDependencies": {
"@packages/tsconfig": "^1.0.0",
"@types/node": "^22.7.9",
"typescript": "^5.6.3"
}
}
tsconfig
json
{
"compilerOptions": {
"target": "es2016",
"module": "NodeNext",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"declaration": true
}
}
package.json
json
{
"name": "@packages/tsconfig",
"version": "1.0.0",
"private": true
}
Execution
sh
npm install
npm run build -w packages/fizzbuzz
npm run build -w apps/src
npx tsx watch apps/src/index.ts
Hello World!
Buzz