isaacs / tshy

Other
894 stars 18 forks source link

workspace / monorepo usage? #40

Closed busticated closed 11 months ago

busticated commented 11 months ago

hey there πŸ‘‹

thanks for making this awesome tool πŸ™ ❀️ i'm just diving in and wondering if you / the community can provide any usage examples or tips for how to use tshy within a workspace / monorepo. i understand from this comment, that the basic approach is to have each package in the workspace do their own builds. that's something i've done successfully in the past but i'm wondering about some details - specifically:

if it's helpful, i'd be happy to compile feedback here and open a PR with doc updates πŸ‘

busticated commented 11 months ago

answering some of my own questions...

how are you sharing tsconfig.json settings between packages?

a base tsconfig.json in the root package which each workspace package extends works fine. i moved the tsconfig.json that tshy generated for me to my root package and updated my workspace packages to use:

{
  "extends": "../../tsconfig"
}

how are you wiring up typcheck commands (npm scripts, etc)?

in general, it seems the approach of having each workspace package implement a command which then the root package calls works fine. so my root package.json uses:

{
  "scripts": {
    "typecheck": "npm run typecheck --workspaces",
  }   
}

(other bits omitted)

while my workspace package.json files use:

{
  "scripts": {
    "typecheck": "tsc --noemit"
  }   
}

(other bits omitted)


what about linting?

in this case the top-down approach seems good. my root package.json uses:

{
  "scripts": {
    "lint": "eslint . --ext .js,.jsx,.mjs,.ts,.tsx,.cts,.mts --ignore-path .gitignore"
  }   
}

(other bits omitted)

i also added the dist directories to my .gitignore file so all files generated by tshy are ignored. i'm using @typescript-eslint but relying on the typescript that comes with tshy (iow, typescript is not a direct dependency)


how do interdependencies work between packages?

TBD


when testing, are you targeting compiled (/dist) files or relying on the test runner to build, etc?

i went the route of targeting the compiled bits. seems to work fine. each workspace package implements a test script and the root package simply calls them via npm run test --workspaces (or equivalent). i'm using Node's built-in test runner so my package.json uses:

{
  "scripts": {
    "test": "npm run build && NODE_V8_COVERAGE=tmp/coverage node --test --test-reporter spec --experimental-test-coverage --enable-source-maps dist/esm/*.test.js",
    "build": "tshy"
  }   
}

(other bits omitted)


any special considerations around publishing?

TBD


should we check the .tshy directory into source control?

seems so πŸ€—

busticated commented 11 months ago

πŸ•΅οΈ more answers...

how do interdependencies work between packages?

basically, as normal. import statements referencing external packages use that package's name - e.g. import thing from 'my-thing', etc. interdependent packages within the root workspace are installed with: npm install my-thing --workspace path/to/my-thing. (assumes npm@7.x and above - see docs).

NOTE: terminology is a bit awkward imo - "package" === "workspace" when working from your project's root directory

isaacs commented 11 months ago

It seems like you've got most of the questions answered?

I'm using tshy quite extensively in https://github.com/tapjs/tapjs (that's actually where it came out of), maybe that could provide some guidance?

isaacs commented 11 months ago

I don't find it's very useful to do tsc --noEmit just to type check. Better to just compile the code and let that fail if there's a type problem.

If you do tsc --noEmit, you'll probably want to provide it with something like tsc -p .tshy/esm.json --noEmit (or .tshy/commonjs.json), or else you may get spurious errors from the cjs/mjs shim stuff.