ts-loader: ProjectReferences: ts-loader doesnt build dependent projects

Expected Behaviour

Based on this highly anticipated and recently merged PR: https://github.com/TypeStrong/ts-loader/pull/935 by @sheetalkamat I would expect ts-loader to build dependent projects if projectReferences: true.

Actual Behaviour

Dependent project reference is not built when building project.

The test projectReferencesNotBuilt referenced in the “steps to reproduce” section seems to account for the fact that the dependent project may not already be built. However, the expected output of that test is just the TypeScript error saying the project hasn’t been built and to run tsc --build to build the dependent project. I would expect the projectReferences config option to basically run the API equivalent of tsc --build.

Actual application error:

Module build failed (from ../node_modules/ts-loader/index.js):
Error: Could not find output JavaScript file for input assets/scripts/api/api.ts (looked at assets/scripts/lib/api/api.js).
The input file is part of a project reference located at tsconfig.json, so ts-loader is looking for the project’s pre-built output on disk. Try running `tsc --build` to build project references.
    at successLoader (/src/node_modules/ts-loader/dist/index.js:46:19)
    at Object.loader (/src/node_modules/ts-loader/dist/index.js:22:12)
 @ ./portal/assets/scripts/actions/Dashboard.tsx 28:0-129 42:15-37 43:19-37 44:23-45 45:16-41
 @ ./portal/assets/scripts/router.ts
 @ ./portal/assets/scripts/index.tsx
./assets/scripts/api/methods.ts

Steps to Reproduce the Problem

Typescript: v3.6.3 ts-loader: v6.1.0

yarn run comparison-tests --single-test projectReferencesNotBuilt                                                    09/17 15:40:15 121.372s
yarn run v1.17.3
$ tsc --project "./test/comparison-tests" && npm link ./test/comparison-tests/testLib && node test/comparison-tests/run-tests.js --single-test projectReferencesNotBuilt
npm WARN lib@0.0.1 No repository field.
npm WARN lib@0.0.1 No license field.

up to date in 0.276s
found 0 vulnerabilities

/Users/justin/.fnm/node-versions/v12.3.1/installation/lib/node_modules/lib -> /src/ts-loader/test/comparison-tests/testLib
/src/ts-loader/node_modules/lib -> /Users/justin/.fnm/node-versions/v12.3.1/installation/lib/node_modules/lib -> /src/ts-loader/test/comparison-tests/testLib

-------------------------------------------------------------------------

Starting to run test suites...



  projectReferencesNotBuilt
    1) should have the correct output
    ✓ should work with transpileOnly (292ms)


  1 passing (2s)
  1 failing

  1) projectReferencesNotBuilt
       should have the correct output:

      Uncaught AssertionError [ERR_ASSERTION]: bundle.js is different between actual and expected
      + expected - actual

       /*!**********!*/
         !*** ./lib/index.ts ***!
         /**********/
       /*! no static exports found */
      -/***/ (function(module, exports, __webpack_require__) {
      -"use strict";
      -eval("
      -exports.__esModule = true;
      -exports.lib = {
      -    one: 1,
      -    two: 2,
      -    three: 3
      -};
      +/***/ (function(module, exports) {
      +eval("throw new Error(/"Module build failed (fromts-loader):/nError: Could not find output JavaScript file for input lib/index.ts (looked at lib/index.js)./nThe input file is part of a project reference located at lib/tsconfig.json, so ts-loader is looking for the project’s pre-built output on disk. Try running `tsc --build` to build project references./n    at successLoader (ts-loader)/n    at Object.loader (ts-loader)/");
       /# sourceURL=webpack://./lib/index.ts?");
       /***/ })
       /******/ });

      at compareActualAndExpected (test/comparison-tests/create-and-execute-test.js:467:16)
      at /src/ts-loader/test/comparison-tests/create-and-execute-test.js:333:13
      at Array.forEach (<anonymous>)
      at compareFiles (test/comparison-tests/create-and-execute-test.js:329:31)
      at Watching.handler (test/comparison-tests/create-and-execute-test.js:194:9)
      at /src/ts-loader/node_modules/webpack/lib/Watching.js:100:9
      at AsyncSeriesHook.eval [as callAsync] (eval at create (node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:32:10), <anonymous>:6:1)
      at AsyncSeriesHook.lazyCompileHook (node_modules/webpack/node_modules/tapable/lib/Hook.js:154:20)
      at Watching._done (node_modules/webpack/lib/Watching.js:99:28)
      at /src/ts-loader/node_modules/webpack/lib/Watching.js:73:19
      at Compiler.emitRecords (node_modules/webpack/lib/Compiler.js:366:39)
      at /src/ts-loader/node_modules/webpack/lib/Watching.js:54:20
      at /src/ts-loader/node_modules/webpack/lib/Compiler.js:352:14
      at AsyncSeriesHook.eval [as callAsync] (eval at create (node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:32:10), <anonymous>:6:1)
      at AsyncSeriesHook.lazyCompileHook (node_modules/webpack/node_modules/tapable/lib/Hook.js:154:20)
      at /src/ts-loader/node_modules/webpack/lib/Compiler.js:349:27
      at done (node_modules/neo-async/async.js:2854:11)
      at /src/ts-loader/node_modules/neo-async/async.js:2805:7
      at /src/ts-loader/node_modules/graceful-fs/graceful-fs.js:45:10
      at FSReqCallback.oncomplete (fs.js:137:23)

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 13
  • Comments: 28 (13 by maintainers)

Most upvoted comments

@B3zo0 Thank you for repro, I could see that change in mentioned file didn’t restart compilation. However your project is too large for me to investigate this in limited time. Can you or someone on this thread create small repro so I can look into it? Someone somewhere mentioned it has to do with transpileOnly option so in your config I removed that and still see the issue. So its definitely not just transpileOnly (also we have tests that work correctly for both transpile and non transpile modes)

Looks like I hadn’t rebuilt the src before running the tests. That test passes now. However, I don’t have a repro for you at this moment since our code base is private but it is still an issue. I will try to come up with a repro in the next couple days.

One other thing to note is that even when the referenced projects are built, our compile time increases from ~30s to ~1m20s. Maybe its related to this? https://github.com/TypeStrong/ts-loader/issues/988 Although we use react, not vue.

I’ve just migrated to the latest ts-loader to test a new project references and I have the same problem as @jleider.

My fresh build always throws a few “Output file [NAME] has not been built from source file [NAME]”. I don’t have this problem when I use tsc directly. To fix the errors I need to do a manual build using tsc compiler before executing webpack. Tested on Windows with typescript 3.6.3, ts-loader 6.2.0 and node 12.11.0

Unfortunately, the project is private so I can’t share it

Thanks @B3zo0! Hopefully someone can take a look at this now you’ve put this together

I’ve tried this new projectReferences option and while it builds the references projects for the first time it does not pick up changes when I change something in a referenced project. Is this the desired behavior?

@sheetalkamat I have three things to report:

  1. Between the 6.1.1 and 6.2.2 changes this is mostly working! However, there is still one issue that seems to be a race condition. The first time a project is built which contains a project reference, the referenced project will be built on the first run but the exported .d.ts files are not “present” for the compile of the parent project until the second run.

  2. If there are any .tsbuildinfo files hanging around from a previous build but there are no exported files due to being removed from the file system the .d.ts files will never be rebuilt. I am not sure if this is a ts-loader issue or if that is expected behavior of the tsc compiler in which case a user must tsc --force, tsc --clean the project or remove the .tsbuildinfo files first.

  3. There is an unexpected behavior of the placement of the .tsbuildinfo file. By default according to the ts compiler options, the .tsbuildinfo file should be located in the same directory as the tsconfig file. However, I see it being written to disk one level up from my rootDir or two directories up from my outDir. For example, if rootDir: "./assets/scripts and outDir: "./assets/scripts/lib" then the .tsbuildinfo file is written to ./assets/tsconfig.tsbuildinfo instead of what I would expect to be ./tsconfig.tsbuildinfo. Setting the tsBuildInfoFile: "./tsconfig.tsbuildinfo" directly gets around this issue but I don’t think should be necessary.