Skip to content

ts-node with project references in a lerna monorepo #897

Open

Description

@kerdany

I'm using lerna with typescript project references for a node application containing two packages. Package lib and package app (which depends on lib).

I've configured typescript project references so that package lib is built automatically whenever we run tsc --build inside package app (i.e. to build for production).

Here's how the tsconfig.json files are configured for each of the packages:

packages/lib/tsconfig.json:

{
  "compilerOptions": {
    "strict": true,
    "rootDir": "src",
    "outDir": "dist",
    "tsBuildInfoFile": "dist/.tsbuildinfo",
    "composite": true
  }
}

packages/app/tsconfig.json:

{
  "compilerOptions": {
    "strict": true,
    "rootDir": "src",
    "outDir": "dist",
    "tsBuildInfoFile": "dist/.tsbuildinfo",
    "incremental": true
  },
  "references": [
    { "path": "../lib" }
  ]
}

Currently, running tsc --build (inside app) compiles typescript to javascript in the dist directory in each of app and lib perfectly fine, the setup runs flawlessly in production mode.

The problem, however, is that trying to run the project in development with ts-node via nodemon --exec 'ts-node src/index.ts' in development fires the following error:

/path/to/packages/app/node_modules/ts-node/src/index.ts:245
    return new TSError(diagnosticText, diagnosticCodes)
           ^
TSError: ⨯ Unable to compile TypeScript:
src/index.ts(1,23): error TS2307: Cannot find module '@myproj/lib'.
...

What seems to be happening, is that ts-node is looking for the @myproj/lib package inside node_modules directory (symlinked by lerna), instead of compiling it on the fly through typetcript's project references, as is setup inside both tsconfig.json files.

I validated my theory by:

  • Running a regular tsc --build first (which also builds the lib/dist code).
  • Then running nodemon --exec 'ts-node src/index.ts' again, and it ran fine then.

Which means that ts-node in this case is loading lib via the compiled .js code inside lib/dist (symlinked by lerna), NOT via compiling its .ts code on the fly (via references).

I'm using ts-node@8.4.1 (currently the latest version).

Some questions:

  • Doesn't ts-node currently support project-references yet or passing the --build flag to tsc yet?

  • Am I doing something wrong in my (e.g. tsconfig.json) configurations that's causing ts-node not to compile/build lib.

  • I can see that a new --build flag is being added to ts-node in the master branch (commit), but it seems that it's irrelevant to tsc's --build flag.

Note: Currently I'm working around this (without ts-node) via nodemon --exec 'tsc --build && node dist/index.js' till I get this figured out.

Thanks!

Activity

  1. changed the title [-]ts-node with typescript project references[/-] [+]ts-node with typescript project references in a lerna monorepo[/+] on Oct 16, 2019
  2. changed the title [-]ts-node with typescript project references in a lerna monorepo[/-] [+]ts-node with project references in a lerna monorepo[/+] on Oct 16, 2019
  3. blakeembrey commented on Oct 16, 2019

    @blakeembrey
    Member
    1. I don't think so, though I can replicate project references working for other cases. It's using the language services API today which has typically had no problems, but I'd have to ask if you can build a simple repro for me to work with on this to confirm.
    2. I don't think so, more likely that references don't work as expected.
    3. Correct, I can probably rename to --emit to clarify the use-case. However, I run into issues with project references on the latest master build that need to be fixed (so your example might help me too) 😦
  4. kerdany commented on Oct 16, 2019

    @kerdany
    Author

    Thanks @blakeembrey

    1. Sure, I will prepare a sample repo to reproduce the issue first thing in the morning (UTC+2 here).

    Thanks!

  5. kerdany commented on Oct 17, 2019

    @kerdany
    Author

    Hi again,
    I've created code to reproduce issue here:
    https://github.com/kerdany/ts-node_issue-897

  6. blakeembrey commented on Oct 31, 2019

    @blakeembrey
    Member

    @kerdany Thanks! Interestingly I get the same error in development with VS Code and tsc, until I enable --build. This makes sense, since I assume that TypeScript is actually building references first when you specify --build. It does make it trickier for ts-node though, I guess it should also build those dependencies somehow. We might have to do something in memory to make this possible...

  7. blakeembrey commented on Oct 31, 2019

    @blakeembrey
    Member

    Another interesting part of this is that it's related to node and TypeScript's understanding of module resolution. You can actually make this work with the current release of ts-node by importing directly the other .ts file:

    import { greet } from "@myproj/lib/src/index";

    Edit: Don't expect this to work in the next major version though, I've been having a lot of trouble with getting project references working and this also fails with VS Code tsc.

  8. jomi-se commented on Dec 4, 2019

    @jomi-se

    Have you done any progress or got any clues for this? I just ran into the same issue as well

  9. impaler commented on Dec 7, 2019

    @impaler

    I also ran into this trying out packages in yarn workspaces. When wanting to debug with node -r ts-node/register as a work around for now I am composing a root tsconfig.json with all relevant references and running a tsc --build --watch running separately. Would be great to have project references resolve and build with ts-node alone.

  10. nickzelei commented on Jan 10, 2020

    @nickzelei

    FYI it looks like they've added API support for building project references.

    microsoft/TypeScript#31432

    interface SolutionBuilder<T extends BuilderProgram> {
        build(project?: string, cancellationToken?: CancellationToken): ExitStatus;
        clean(project?: string): ExitStatus;
        buildReferences(project: string, cancellationToken?: CancellationToken): ExitStatus;
        cleanReferences(project?: string): ExitStatus;
        getNextInvalidatedProject(cancellationToken?: CancellationToken): InvalidatedProject<T> | undefined;
    }
    
  11. krzkaczor commented on Jan 28, 2020

    @krzkaczor

    FYI: the obvious workaround is to set TS_NODE_TRANSPILE_ONLY=true but then you won't get any type checks.

  12. dchambers commented on Jan 30, 2020

    @dchambers

    @krzkaczor, I tried setting this on the command line (using --transpile-only and -T) and it makes no difference -- project references still aren't built.

  13. dchambers commented on Feb 10, 2020

    @dchambers

    I ended up using concurrently to build the project references for all the libraries within our monorepo (all inside a lib directory) like so:

    "scripts": {
      "start": "concurrently \"tsc -b -w ../lib\" \"nodemon -w ./src -w ../lib --ignore 'lib/*/src/*' -e js,jsx,gql,ts,tsx --exec ts-node src/server.ts\"",
    }
    

    Here, the lib directory contained a tsconfig.json with references to all the composite projects within the directory.

  14. 17 remaining items

  15. nicoabie commented on Aug 8, 2022

    @nicoabie

    https://github.com/calcom/cal.com/blob/d1d467d28d03811b50ec2942c8eeef82e2e425a5/packages/tsconfig/base.json#L20-L28

    thanks @zomars !!!

    I was having issues with a custom typing and the files: true flag solved the issue.

    This is my tsconfig.json of the test folder that references the source and has to reference a custom typing the source uses:

    {
      "extends": "../tsconfig.json",
      "compilerOptions": {
        "composite": true
      },
      "include": ["./", "../types/index.d.ts"],
      "references": [{ "path": "../src" }],
      "ts-node": {
        "files": true,
      }
    }
    
    
  16. pjanickovic-ph commented on Aug 4, 2023

    @pjanickovic-ph

    Hello, I was searching for a solution for like 2 weeks, and I think I found a perfect workaround. the whole idea is that I run my main app using nodemon and ts-node, and except watching my app folder, i added another folder to watch but not the src folder of my library but the build (output folder) and extended the watch to .js files as well. Then, run tsc -b -w on my library which watches the library itself, and rebuild if necessary, and if it emits new .js files, nodemon catches it as well. and it is even in the right order

  17. vorant94 commented on Aug 31, 2023

    @vorant94

    Hello, I was searching for a solution for like 2 weeks, and I think I found a perfect workaround. the whole idea is that I run my main app using nodemon and ts-node, and except watching my app folder, i added another folder to watch but not the src folder of my library but the build (output folder) and extended the watch to .js files as well. Then, run tsc -b -w on my library which watches the library itself, and rebuild if necessary, and if it emits new .js files, nodemon catches it as well. and it is even in the right order

    so assuming you have like 3 different libs and 1 app in your monorepo... do you start basically 4 processes each time you start coding (3 tsc -b -w and one nodemon)?

    also this workaround means that each change in the lib would be propagated within 2 rebuilds (1 of the lib itself and 1 of the app that is using the lib), but the changes in the app would be propagated within 1 rebuild, which means inconsistency of the time interval between saving changes and ability to run the code...

    it indeed does the job but not without tradeoffs

  18. daniel-savu commented on Oct 2, 2023

    @daniel-savu

    Ran into this issue today as well, although I'm just using yarn workspaces rather than lerna. Maybe worth changing the issue title since this is a broader problem? I've reproduced with a minimal setup here if it helps anyone: https://github.com/daniel-savu/ts-node-bug

  19. gemyago commented on Nov 1, 2023

    @gemyago

    I have an npm workspaces and have same issue

  20. JeffJassky commented on Mar 5, 2024

    @JeffJassky

    Anybody have any insight into this as of March 2024? Is this supported yet? Thanks!

  21. vorant94 commented on Mar 6, 2024

    @vorant94

    Anybody have any insight into this as of March 2024? Is this supported yet? Thanks!

    I ended up avoiding ts-node and other typesctipt runners. Here is an example repo for how achieve live-reload and so on solely with node built-in watch mode and tsc

    https://github.com/vorant94/typescript-monorepo

  22. adrian-gierakowski commented on Mar 6, 2024

    @adrian-gierakowski

    https://www.npmjs.com/package/tsc-watch can be used as well for tsc driven workflows

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions