Skip to content

Compile multiple packages in a mono-repo in a single compilation stepΒ #17611

Closed
@bajtos

Description

@bajtos

In https://github.com/strongloop/loopback-next, we are developing a set of Node.js modules using TypeScript as the language and lerna convention for the monorepo layout.

I am not able to figure out how to configure TypeScript to compile all our packages in a single step, also allowing us to use --watch mode. As a result, whenever we need to transpile our code, we have to run tsc for each package, which adds a lot of friction to our red-green-refactor loop. (I suspect tsc is wasting a lot of time by re-reading type definitions produced by previous tsc runs, which would have been avoided if everything was compiled in one tsc run.)

Let me show a small example to illustrate our project setup.

Source files committed to git:

packages/
  helper/
    src/
      helper.ts
      util.ts

  core/
    src/
      app.ts
      core.ts

Transpiled files that will be eventually published to npmjs.org in two packages (foo and bar):

packages/
  helper/
    lib/
      helper.js
      util.js

  core/
    lib/
      app.js
      core.js

Essentially, I need to configure TypeScript compiler to use outDir=packages/helper/lib when compiling files from packages/helper/src, but use a different outDir value packages/core/lib when compiling files from packages/core/src.

Additional caveats:

  • We have interdependencies between our packages, e.g. core depends on helper. lerna is taking care of running the build command in such order that dependencies are built first, dependants second.
  • I considered starting multiple tsc --watch processes (one for each package), however think this will not trigger rebuild when a dependency was changed (and rebuilt by another tsc --watch process).

The proposal

Allow outDir option to take a map value configuring different output directories for different source file locations. Alternatively, define a new option (e.g. outDirs or outDirMap).

{
  "outDir": {
    "packages/foo/src/**": "packages/foo/lib",
    "packages/bar/src/**": "packages/bar/lib",
  }
}

Another alternative that comes to my mind is to allow rootDir and outDir to contain a pattern matcher, where the value of the matcher from rootDir will be applied to outDir.

{
  "rootDir": "packages/*/src",
  "outDir": "packages/*/lib",
}

I understand this may be out of scope of TypeScript project (as mentioned in #7752). In which case, is there a compiler API allowing users to control the mapping from source to output files in such fine-grained way?

Metadata

Metadata

Assignees

Labels

CommittedThe team has roadmapped this issueScenario: Monorepos & Cross-Project ReferencesRelates to composite projects (a.k.a references between "medium sized projects")

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions