Fork-ts-checker-webpack-plugin: Compiler option `"noEmit": true` is not honoured

Created on 13 Aug 2020  路  9Comments  路  Source: TypeStrong/fork-ts-checker-webpack-plugin

Current behavior

If I specify the compiler option "noEmit": true, it seems that TypeScript is still running the emit phase.

Our emit phase is extremely slow for some unknown reason (multiple minutes). To workaround this, when we run tsc for type checking purposes we specify noEmit to skip the slow emit phase, which just leaves the type checking part which is very quick (multiple seconds). Unfortunately, when I tried to do the same thing using this plugin, it seems the emit phase is still running. To verify this I enabled the typescript.profile option, which gave me these results:

Parse Configuration:                  0.09 s
Create Watch Compiler Host:           0.00 s
I/O Read:                             0.31 s
Parse:                                1.40 s
ResolveTypeReference:                 0.07 s
ResolveModule:                        4.27 s
Program:                              6.47 s
Bind:                                 1.09 s
Syntactic Diagnostics:                0.00 s
Check:                               17.47 s
transformTime:                      230.97 s
Emit:                               232.62 s
Semantic Diagnostics:               250.87 s
Create Watch Program:               259.00 s
Poll And Invoke Created Or Deleted:   0.04 s
Queued Tasks:                         0.00 s

Expected behavior

noEmit should be honoured, like it is when we run tsc.

Steps to reproduce the issue

Enable typescript.profile and noEmit. In the profile results you will see the emit phase is still running, unlike when we run tsc.

Issue reproduction repository

Environment

  • fork-ts-checker-webpack-plugin: 5.0.14
  • typescript: 3.9.2
  • eslint: N/A
  • webpack: 4.43.0
  • os: macOS latest

Potentially related to https://github.com/TypeStrong/fork-ts-checker-webpack-plugin/issues/453

bug

Most helpful comment

That's a good point. I'm open for a PR to add another mode when we don't use watch mode (similar as we have special case for build: true) :) We didn't add it as it's additional complexity and the main use-case for this plugin is watch mode :)

All 9 comments

Hi! Thanks for reporting that. Could you share your webpack config?

@piotr-oles Sure, here's a full reduced test case: https://github.com/OliverJAsh/fork-ts-checker-webpack-plugin-no-emit-bug.

The emit time in this example is very fast, but we can still see that the emit phase is happening even though we're specifying noEmit in tsconfig.json.

@OliverJAsh
I was trying to re-create this issue using reproduction repository that you provided but with no success :/

  1. I checked the compilerOptions values and noEmit is properly passed to the typescript
  2. I ran the profiler first on fork-ts-checker-webpack-plugin and then on tsc:

fork-ts-checker-webpack-plugin
Zrzut ekranu 2020-08-22 o 21 40 44

tsc
Zrzut ekranu 2020-08-22 o 21 44 04

As you can see they are nearly identical and I didn't found any major difference or additional emit phase.

Could you check if it's possible to reproduce this issue with the provided repository?

@piotr-oles The emit time is very fast but the issue is that it's still happening at all, even though we specify noEmit.

Ideally I would be able to provide a better reduced test case which demonstrated a slow emit phase. However, I'm not sure what exactly is causing the slow emit phase, and that's a separate issue (something for TS to fix, probably).

In any case, the issue I filed here is not really about the slow emit phase per se鈥攊t's more that the emit phase is running even when we tell it not to (which is a significant issue if the emit phase is slow for whatever reason, as it is on the project I work on).

We can see that the emit phase is running even when we specify noEmit by looking at the output of typescript.profile in the console. When I run the reduced test case on my machine, this is output I'm seeing:

$ webpack
Parse Configuration:                0.01 s
Create Watch Compiler Host:         0.00 s
I/O Read:                           0.02 s
Parse:                              0.33 s
ResolveTypeReference:               0.01 s
ResolveModule:                      0.10 s
Program:                            0.48 s
Bind:                               0.19 s
Check:                              0.01 s
transformTime:                      0.00 s
Emit:                               0.01 s
Semantic Diagnostics:               0.03 s
Create Watch Program:               0.72 s
Poll And Invoke Created Or Deleted: 0.01 s
Queued Tasks:                       0.00 s
Hash: 842f76e5ee7ec0f2eec2
Version: webpack 4.44.1
Time: 769ms
Built at: 08/24/2020 10:24:10
  Asset      Size  Chunks             Chunk Names
main.js  72.2 KiB       0  [emitted]  main
Entrypoint main = main.js
[0] ./src/index.ts 120 bytes {0} [built]
[2] (webpack)/buildin/global.js 472 bytes {0} [built]
[3] (webpack)/buildin/module.js 497 bytes {0} [built]
    + 1 hidden module

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

The emit phase is indeed very fast (0.01s), but nonetheless my question remains: why is the emit phase running at all, even though we specified noEmit?

If you run tsc --extendedDiagnostics you will see that tsc also will have 0.01s for emit even with "noEmit": true option :)

@piotr-oles I don't see it here?

$ tsc --extendedDiagnostics
Files:                         22
Lines:                      38494
Nodes:                     169672
Identifiers:                66241
Symbols:                    71686
Types:                      19985
Instantiations:             25088
Memory used:               99819K
Assignability cache size:    4291
Identity cache size:           50
Subtype cache size:             0
Strict subtype cache size:      0
I/O Read time:              0.01s
Parse time:                 0.36s
ResolveTypeReference time:  0.01s
ResolveModule time:         0.01s
Program time:               0.40s
Bind time:                  0.21s
Check time:                 0.99s
Total time:                 1.60s

If I remove noEmit then I do see it.

Could you try with --watch? This is more accurate comparison to the fork-ts-checker-webpack-plugin. I don't have a time to check it right now, but I did saw it also for tsc :/

Ah, you're right that it appears when we use watch. I guess that makes sense. IIUC, TypeScript needs to run the emit phase when using watch.

However, in this case I'm not running webpack in watch mode. Should this plugin only use watch mode when webpack itself is using watch mode?

That's a good point. I'm open for a PR to add another mode when we don't use watch mode (similar as we have special case for build: true) :) We didn't add it as it's additional complexity and the main use-case for this plugin is watch mode :)

Was this page helpful?
0 / 5 - 0 ratings