How to run dev mode with many packages

I’ve followed the docs for developing applications, but they seem to be sparse for something more complex than a couple apps and a small number of packages.

I have a monorepo with only about 10 packages. Different apps depend on different packages. Persistent tasks cannot depend on other tasks. This is unfortunate because I cannot use turbo to construct the dependency graph and pick which packages to run in dev mode for a given app or set of apps.

  1. What is the best way to create the dependency graph? A workaround is to create a turbo.json in each app and specify which packages to run in dev mode via with. Is there a better way?
  2. When many packages are run using "dev": "tsc --watch" (in package.json) while some depend on each other, initial builds are run many times until race conditions are met. With my current setup, this can take 40-60 seconds, whereas a raw turbo run build --filter=./packages/* can take about 10 seconds. Making a single edit in a file can take around 30 seconds to reflect in the app (much longer than when we used to have a root tsconfig.json to watch and build any changes across the monorepo. I am running this via turbo run dev. Is there a better way to achieve running dependencies in watch/dev mode?

It looks like Turbowatch describes this problem quite well.

Hey, wrporter. Did you see the Watch Mode section? It sounds like it describes exactly what you need.

If you’re looking dependency-aware hot-reloading of Internal Packages in your repository, I suggest using turbo watch. Here’s the full documentation on turbo watch: https://turborepo.com/docs/reference/watch

Let me know if that’s insufficient and any more specific questions you have.

Hey @anthony-shew, thank you for the reply! I tried turbo watch (and should have mentioned this in the original post). But it gave me similar results where building is incremental and slow across dependent packages before arriving at the final app. In other words, it wasn’t any better than adding a "dev": "tsc --watch --noCheck script to each package.

What seems to be the best solution (that I’ve found so far) is to use TypeScript Project References for packages, using incremental builds. This is fast and requires a single process to run.

I have a tsconfig.dev.json with the following:

{
  "files": [],
  "compilerOptions": {
    "composite": true,
    "preserveWatchOutput": true,
    "noCheck": true,
    "incremental": true
  },
  "references": [
    { "path": "./packages/package1/tsconfig.json" },
    { "path": "./packages/package2/tsconfig.json" },
    { "path": "./packages/package3/tsconfig.json" },
    { "path": "./packages/package4/tsconfig.json" },
    { "path": "./packages/package5/tsconfig.json" },
    { "path": "./packages/package6/tsconfig.json" },
    { "path": "./packages/package7/tsconfig.json" },
    { "path": "./packages/package8/tsconfig.json" },
    { "path": "./packages/package9/tsconfig.json" },
    { "path": "./packages/package10/tsconfig.json" },
  ]
}

In my package.json I have the following:

{
  "scripts": {
    "dev": "turbo run dev --ui=tui",
    "dev:packages": "tsc --build tsconfig.dev.json --watch"
  }
}

In my turbo.json:

{
  "tasks": {
    "//#dev:packages": { "cache": false },
    "dev": {
      "dependsOn": ["generate"],
      "with": ["//#dev:packages"],
      "persistent": true,
      "cache": false
    },
    "generate": {},
}

(We have some code generation tasks that are required at start.)

Then I run my dev environment via yarn dev.

turbo watch is missing incremental builds like we can get with tsc.