moonrepo / moon

A build system and monorepo management tool for the web ecosystem, written in Rust.
https://moonrepo.dev/moon
MIT License
2.84k stars 155 forks source link

[feature] Don't write `tsconfig.json` when it hasn't changed #607

Closed bryanjswift closed 1 year ago

bryanjswift commented 1 year ago

Is your feature request related to a problem? Please describe.

When developing a web application locally watching for changes with a tool like ts-node-dev the server restarts every time tsconfig.json is modified. This is desirable when the contents of the file have been modified but the watching tools are listing for filesystem events to see if files were written and not reading the contents to compare if they have changed.

Describe the solution you'd like

Don't flush a write of an unmodified tsconfig.json file if what is on disk is the same as what would be written.

Describe alternatives you've considered

It is possible to change the ts-node-dev configuration to ignore changes to the tsconfig.json, which will work but it will mean that devs need to be aware that changes to TypeScript configuration require restarting the server by hand. Which includes anything that would change the TypeScript configuration as a result of "upstream" modifications (like adding a workspace dependency).

Additional context

The writing of tsconfig.json wouldn't trigger as many restarts if it didn't happen, seemingly, each time the package/project is processed. Meaning, even if the task is cached and restored from cache (or there's nothing to restore) the tsconfig.json file is still written and still triggers a reload.

milesj commented 1 year ago

@bryanjswift Do you happen to know which field is changing?

We do attempt to avoid writing if nothing has changed: https://github.com/moonrepo/moon/blob/master/crates/typescript/lang/src/tsconfig.rs#L130 But maybe we're missing a field.

bryanjswift commented 1 year ago

@bryanjswift Do you happen to know which field is changing?

We do attempt to avoid writing if nothing has changed: https://github.com/moonrepo/moon/blob/master/crates/typescript/lang/src/tsconfig.rs#L130 But maybe we're missing a field.

Based on git status and git diff nothing in the file on disk has changed. I have not done any digging into this one because it is a fairly minor inconvenience. I'll note that I have the following typescript toolchain settings (on v0.22.0)

# Configures how moon integrates with TypeScript.
typescript:
  # When `syncProjectReferences` is enabled and a dependent project reference
  # *does not* have a `tsconfig.json`, automatically create one.
  createMissingConfig: true

  # Name of `tsconfig.json` file in each project root.
  # projectConfigFileName: 'tsconfig.json'

  # Name of `tsconfig.json` file in the workspace root.
  # rootConfigFileName: 'tsconfig.json'

  # Name of the config file in the workspace root that defines shared compiler
  # options for all project reference based config files.
  # rootOptionsConfigFileName: 'tsconfig.options.json'

  # Update a project's `tsconfig.json` to route the `outDir` compiler option
  # to moon's `.moon/cache` directory.
  routeOutDirToCache: false

  # Sync a project's `dependsOn` as project references within the
  # project's `tsconfig.json` and the workspace root `tsconfig.json`.
  syncProjectReferences: false

  # Sync a project's project references as import aliases to the `paths`
  # compiler option in each applicable project.
  syncProjectReferencesToPaths: false
bryanjswift commented 1 year ago

This is partial output from a build (with MOON_LOG=trace) that is triggering a write to tsconfig.json. In my case ~/Documents/little-cinema/projects/backstage/packages/messaging-api/tsconfig.json is the file being written but with no changes. I would have expected with syncProjectReferences and syncProjectReferencesToPaths it would not have tried to update the tsconfig file.

▪▪▪▪ api-types:gen-s3-object-created (cached from previous run, a865a5fb)
[trace 16:23:20] moon:action-pipeline:batch:3:2 Processed action RunTarget(api-types:gen-s3-object-created) in 12.841666ms
[debug 16:23:20] moon:action:sync-project Syncing project module-tree-shared
[trace 16:23:20] moon:lang:config Loading ~/Documents/little-cinema/projects/backstage/packages/module-tree-shared/tsconfig.json
[trace 16:23:20] moon:lang:config Syncing ~/Documents/little-cinema/projects/backstage/packages/module-tree-shared/tsconfig.json with changes
[trace 16:23:20] moon:action-pipeline:batch:3:6 Processed action SyncNodeProject(module-tree-shared) in 13.041375ms
[trace 16:23:20] moon:action-pipeline:batch:4 Running 3 actions in batch 4
[trace 16:23:20] moon:action-pipeline:batch:4:1 Processing action RunTarget(api-types:build)
[trace 16:23:20] moon:action-pipeline:batch:4:2 Processing action RunTarget(pg:build)
[trace 16:23:20] moon:action-pipeline:batch:4:3 Processing action SyncNodeProject(messaging-api)
[trace 16:23:20] moon:cache:item Cache hit for ~/Documents/little-cinema/projects/backstage/.moon/cache/states/api-types/build/lastRun.json, reading
[trace 16:23:20] moon:cache:item Cache hit for ~/Documents/little-cinema/projects/backstage/.moon/cache/states/pg/build/lastRun.json, reading
[debug 16:23:20] moon:action:sync-project Syncing project messaging-api
[debug 16:23:20] moon:node-platform:sync-project Syncing analytics-api as a dependency to messaging-api's package.json
[debug 16:23:20] moon:action:run-target Running target api-types:build
[debug 16:23:20] moon:action:run-target Running target pg:build
[debug 16:23:20] moon:node-platform:sync-project Syncing api-types as a dependency to messaging-api's package.json
[debug 16:23:20] moon:node-platform:sync-project Syncing module-tree-shared as a dependency to messaging-api's package.json
[debug 16:23:20] moon:node-platform:sync-project Syncing secrets as a dependency to messaging-api's package.json
[debug 16:23:20] moon:node-platform:sync-project Syncing lambda-helpers as a dependency to messaging-api's package.json
[debug 16:23:20] moon:node-platform:sync-project Syncing pg as a dependency to messaging-api's package.json
[debug 16:23:20] moon:node-platform:sync-project Syncing asset-management-api as a dependency to messaging-api's package.json
[trace 16:23:20] moon:lang:config Syncing ~/Documents/little-cinema/projects/backstage/packages/messaging-api/package.json with changes
[trace 16:23:20] moon:lang:config Loading ~/Documents/little-cinema/projects/backstage/packages/messaging-api/tsconfig.json
[trace 16:23:20] moon:lang:config Syncing ~/Documents/little-cinema/projects/backstage/packages/messaging-api/tsconfig.json with changes
[trace 16:23:20] moon:action-pipeline:batch:4:3 Processed action SyncNodeProject(messaging-api) in 1.087291ms
[trace 16:23:20] moon:utils:process Running command git hash-object --stdin-paths - .moon/project.yml .moon/toolchain.yml .moon/workspace.yml packages/api-types/package.json packages/api-types/tsconfig.json (in ~/Documents/little-cinema/p
rojects/backstage)
[trace 16:23:20] moon:utils:process Running command git ls-tree HEAD -r packages/api-types (in ~/Documents/little-cinema/projects/backstage)
[debug 16:23:20] moon:runner Generated hash 73c0bce3978d26c7f799b19a19defac29dc7f99d55ef5402812c9e9a90a1a200 for target api-types:build
[debug 16:23:20] moon:runner Cache hit for hash 73c0bce3978d26c7f799b19a19defac29dc7f99d55ef5402812c9e9a90a1a200, reusing previous build
milesj commented 1 year ago

This is helpful, thanks. Digging into.

milesj commented 1 year ago

@bryanjswift I think I figured it out. Does your tsconfig have compiler options?

bryanjswift commented 1 year ago

Apologies, I could have provided this. It does indeed have compilerOptions

{
  "extends": "@tsconfig/node16/tsconfig.json",
  "compilerOptions": {
    "incremental": true,
    "noUncheckedIndexedAccess": true,
    "outDir": "dist/"
  },
  "ts-node": {
    "transpileOnly": true,
    "files": true
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules"
  ],
  "references": [
    {
      "path": "../analytics-api/tsconfig.ref.json"
    },
    {
      "path": "../api-types/tsconfig.ref.json"
    },
    {
      "path": "../asset-management-api/tsconfig.ref.json"
    },
    {
      "path": "../lambda-helpers/tsconfig.ref.json"
    },
    {
      "path": "../module-tree-shared/tsconfig.ref.json"
    },
    {
      "path": "../pg/tsconfig.ref.json"
    },
    {
      "path": "../secrets/tsconfig.ref.json"
    }
  ]
}
milesj commented 1 year ago

Ty. I believe this fixes it: https://github.com/moonrepo/moon/issues/607

bryanjswift commented 1 year ago

Ty. I believe this fixes it: #607

Amazing, thanks!

milesj commented 1 year ago

Whoops linked the wrong thing https://github.com/moonrepo/moon/pull/610

milesj commented 1 year ago

Ok this landed in v0.24. Let me know if it's still an issue.

bryanjswift commented 1 year ago

I can confirm the changes in v0.24 have resolved this issue in my project. Thanks!

milesj commented 1 year ago

Awesome 🙏