Skip to content
This repository was archived by the owner on Mar 6, 2024. It is now read-only.

TypeScript support#56

Closed
amireh wants to merge 5 commits intomasterfrom
awesome-typescript-loader-support
Closed

TypeScript support#56
amireh wants to merge 5 commits intomasterfrom
awesome-typescript-loader-support

Conversation

@amireh
Copy link
Copy Markdown
Owner

@amireh amireh commented Jun 24, 2016

Things to do/check:

ts-loader support:

  • compiles files
  • reports module-level errors
  • reports program-level errors (aggregated)
  • works in --watch mode
  • reports errors in changed module in --watch mode
  • works with happy's cache (caching of code/map)
  • works with the transpileOnly compiler option
  • works with --bail
  • replays errors/warnings for cached modules

awesome-typescript-loader support:

  • compiles files
  • reports module-level errors
  • reports program-level errors (aggregated, this sorta works but can contain duplicate errors)
  • works in --watch mode
  • reports errors in changed module in --watch mode
  • works with happy's cache (caching of code/map)
  • works with --bail
  • replays errors/warnings for cached modules

To try out these changes, use the happypack-support branches in my forks of those repositories. For example, to install the happypack-supporting version of ts-loader:

// package.json
{
  "devDependencies": {
    "ts-loader": "amireh/ts-loader#happypack-support"
  }
}

You also need to clone this PR branch.

amireh and others added 5 commits June 24, 2016 23:23
This patch is the first in the series of introducing
awesome-typescript-loader support where it sets up a proxy channel for
the "after-compile" plugin. "watch-run" doesn't really work yet and is
needed for the loader, that'd be handled in the next patch.

APIs supported during "after-compile":

- compilation.addError(String|Error) -> void
- compilation.addFileDependency(String|Array.<String>) -> void

Note on shared state: since the mapping between threads and plugins can
be 1:N, we need to make sure that a plugin executor is called at most
once for any one thread. This is only achievable by tracking some shared
state between all plugin instances (that is scoped to the ThreadPool,
really).
Bugfixes
--------

- It seems that we were creating a foreground worker _everytime_ a
  "watch-run" plugin is applied... this is now fixed.

Internal Changes
----------------

- ThreadPool now itself performs the plugin binding (to "after-compile")
  so the plugins do not have to track any shared state themselves. Now
  it's safe to have multiple plugins use the same thread-pool and we'll
  have only one plugin handler installed per thread pool, as should be.

FakeCompiler Changes
--------------------

Added the following new APIs to the fake compiler:

- `purgeErrors(Object) -> void`:
  Purge compilation errors that match some attributes, like
  "loaderSource"
- `addModuleError(Error, Module) -> void`:
  Add an error that is bound to a module. We use the module.id, this
  might change to only accept the id.
- `purgeModuleErrors(Module, Object) -> void`:
  Like `purgeErrors` but at the module level.
- `addAsset(assetPath: String, { source: String, size: Number }) ->
  void`:
  Register an asset to the compilation. This goes to
  compilation.assets[assetPath].

"after-compile" plugin:

The first parameter, "compilation", now exposes:

- id: this is happypack-exclusive and is guaranteed to change between
  compilations in the same process (e.g in --watch mode) or in different
  processes (different builds). This ID can be used by loaders like
  ts-loader to perform things at most once per compilation.
- modules: maps to a skimmed-down version of "compilation.modules" that
  includes resource, errors, warnings, and static stuff
- errors: maps to a serializable version of "compilation.errors"

"watch-run" plugin:

The first parameter, "watching", now exposes:

- "mtimes": what is found inside
  `watching.compiler.watchFileSystem.watcher.mtimes` ...

FakeLoaderContext Changes
-------------------------

- A new API "emitModuleError" for emitting errors at the module level
  (this maps to this._module.errors on the foreground loader)
- A new API "writeModuleMetaAttribute" for defining stuff on the
  foreground loader's "this._module.meta" map
We'll just treat this as a special case because it's the most common and
loader authors should be responsible enough not to add cyclic properties
to an error, really.

This *will* bite us later but until then.
@amireh amireh changed the title [WIP] Add initial support for after-compile plugin TypeScript support Jun 27, 2016
@amireh
Copy link
Copy Markdown
Owner Author

amireh commented Jun 28, 2016

One thing I noticed is that "warming up" a typescript loader takes a considerable amount of time (~700ms in my samples). In the regular webpack build, using either loader, it took around ~800ms to build the example, which contains only 3 sources. With happypack, there's about ~100ms overhead for the entire build, so it takes 900ms if you're using a single thread, and ~700ms for every consecutive thread. It's very unfortunate. Compiling the example using happypack in 2 threads takes somewhere between 1500-1700ms (using either loader - it's almost the same.)

I digged a bit into tsserver trying to see if we can make the loaders use/connect to a stand-alone version of the servers, but my research was futile. There seems to be very little documentation around tsserver.

In my opinion, this should either be solved at the TypeScript level (e.g. have tsserver distribute the compilation to multiple threads internally, like what HappyPack does to Webpack), or find out how to launch stand-alone instances of tsserver that one can have running in the background, then instruct our loaders to connect to them.

This should be doable because I checked Sublime Text's TS plugin and it seems to have a tsserver instance in the background to do the diagnostics/type-checking.

TL;DR - don't expect fascinating results unless your builds take ~15 seconds or longer already.

@amireh
Copy link
Copy Markdown
Owner Author

amireh commented Jun 28, 2016

It might be useful if you guys can pull in some TypeScript experts to this thread because this is out of my scope.

@TheLarkInn
Copy link
Copy Markdown

TheLarkInn commented Jun 28, 2016

CC @jbrantly @s-panferov @DanielRosenwasser is this 'warmup' that @amireh mentions a typescript issue?

@amireh
Copy link
Copy Markdown
Owner Author

amireh commented Jul 3, 2016

Also, is there any large open-source TypeScript project that can be built with webpack that we (I) can test on?

@TheLarkInn
Copy link
Copy Markdown

angular2-webpack-starter is a good one.

@IAMtheIAM
Copy link
Copy Markdown

IAMtheIAM commented Jul 5, 2016

I could not get either to work. I first installed these packaged

    "awesome-typescript-loader": "amireh/awesome-typescript-loader#happypack-support",
    "ts-loader": "amireh/ts-loader#happypack-support",

Then I copied the awesome-typescript-loader-support branch into nodemodules/happypack (deleting original happy pack files

And then tried to compile.

Your fork of awesome-typescript-loader was 40 seconds longer than not using happypack (68 sec instead of 28 sec). It completed build modules in 28 sec like normal, but took 40 seconds more for other stuff. It produced these errors in my build:

Happy[ts]: Version: 2.1.1. Using cache? no. Threads: 5 (shared pool)
Happy[ts]: All set; signalling webpack to proceed.
 32% 20/53 build modulesapplying "after-compile"...
28827ms build modules
62ms seal
172ms optimize
63ms hashing
109ms create chunk assets
67ms additional chunk assets
5039ms optimize chunk assets
 90% optimize assetsapplying "after-compile"...
33261ms optimize assets
122ms emit
this is happening!!
this is happening!!
this is happening!!
this is happening!!
this is happening!!
this is happening!!
this is happening!!
Version: webpack 1.13.1
Time: 68314ms
                                          Asset       Size  Chunks             Chunk Names
                                     4.chunk.js  179 bytes       4  [emitted]
                  /assets/fonts/Roboto-Bold.eot      21 kB          [emitted]
                /assets/fonts/Roboto-Medium.eot    21.4 kB          [emitted]
               /assets/fonts/Roboto-Regular.eot    21.3 kB          [emitted]
                  /assets/fonts/Roboto-Thin.eot    21.7 kB          [emitted]
                  /assets/fonts/Roboto-Bold.ttf     128 kB          [emitted]
                 /assets/fonts/Roboto-Light.ttf     127 kB          [emitted]
                /assets/fonts/Roboto-Medium.ttf     127 kB          [emitted]
               /assets/fonts/Roboto-Regular.ttf     126 kB          [emitted]
                  /assets/fonts/Roboto-Thin.ttf     128 kB          [emitted]
                 /assets/fonts/Roboto-Bold.woff    62.9 kB          [emitted]
                /assets/fonts/Roboto-Bold.woff2      50 kB          [emitted]
                /assets/fonts/Roboto-Light.woff    62.3 kB          [emitted]
               /assets/fonts/Roboto-Light.woff2    49.4 kB          [emitted]
               /assets/fonts/Roboto-Medium.woff      63 kB          [emitted]
              /assets/fonts/Roboto-Medium.woff2    50.2 kB          [emitted]
              /assets/fonts/Roboto-Regular.woff    61.7 kB          [emitted]
             /assets/fonts/Roboto-Regular.woff2    49.2 kB          [emitted]
                 /assets/fonts/Roboto-Thin.woff    61.6 kB          [emitted]
                /assets/fonts/Roboto-Thin.woff2    48.5 kB          [emitted]
                            polyfills.bundle.js     559 kB       0  [emitted]  polyfills
                                     1.chunk.js    11.2 kB       1  [emitted]
                              vendors.bundle.js    4.14 MB       2  [emitted]  vendors
                                  app.bundle.js     584 kB       3  [emitted]  app
                 /assets/fonts/Roboto-Light.eot    20.9 kB          [emitted]
                                  polyfills.map     681 kB       0  [emitted]  polyfills
                                          1.map    15.7 kB       1  [emitted]
                                    vendors.map    5.04 MB       2  [emitted]  vendors
                                        app.map     733 kB       3  [emitted]  app
                                          4.map  447 bytes       4  [emitted]
                                 _Layout.cshtml    3.88 kB          [emitted]
                               assets/data.json   33 bytes          [emitted]
                       assets/service-worker.js   45 bytes          [emitted]
                  assets/icon/browserconfig.xml  282 bytes          [emitted]
                              assets/robots.txt   34 bytes          [emitted]
               assets/img/logo-helios-login.png    2.17 kB          [emitted]
                        assets/icon/favicon.ico    1.15 kB          [emitted]
                   assets/img/password-icon.png  493 bytes          [emitted]
                       assets/img/user-icon.png  615 bytes          [emitted]
                assets/fonts/OpenSans-Light.ttf     107 kB          [emitted]
    assets/styles/bootstrap/customizations.scss  318 bytes          [emitted]
                assets/mock-data/mock-data.json   48 bytes          [emitted]
                              assets/humans.txt  268 bytes          [emitted]
assets/styles/bootstrap/pre-customizations.scss  953 bytes          [emitted]
              assets/styles/shared/appwide.scss    2.03 kB          [emitted]
               assets/styles/shared/mixins.scss    3.06 kB          [emitted]
                   assets/img/login-ellipse.png     477 kB          [emitted]
          assets/styles/shared/susy-config.scss    1.24 kB          [emitted]
            assets/styles/shared/variables.scss    1.88 kB          [emitted]

ERROR in   Error: Child compilation failed:

  - compiler.js:88
    [starterproject]/[html-webpack-plugin]/lib/compiler.js:88:16

  - Compiler.js:214 Compiler.<anonymous>
    [starterproject]/[webpack]/lib/Compiler.js:214:10

  - Compiler.js:403
    [starterproject]/[webpack]/lib/Compiler.js:403:12

  - Tapable.js:67 Compiler.next
    [starterproject]/[webpack]/[tapable]/lib/Tapable.js:67:11

  - HappyThreadPool.js:81
    [starterproject]/[happypack]/lib/HappyThreadPool.js:81:11

  - async.js:721
    [starterproject]/[happypack]/[async]/lib/async.js:721:13

  - async.js:52
    [starterproject]/[happypack]/[async]/lib/async.js:52:16

  - async.js:269
    [starterproject]/[happypack]/[async]/lib/async.js:269:32

  - async.js:44
    [starterproject]/[happypack]/[async]/lib/async.js:44:16

  - async.js:718 Object.<anonymous>
    [starterproject]/[happypack]/[async]/lib/async.js:718:17

  - async.js:167 Object.APPLY_PLUGIN:after-compile
    [starterproject]/[happypack]/[async]/lib/async.js:167:37

  - HappyThread.js:70 ChildProcess.acceptMessageFromWorker
    [starterproject]/[happypack]/lib/HappyThread.js:70:58

  - child_process.js:695 handleMessage
    internal/child_process.js:695:10

  - child_process.js:440 Pipe.channel.onread
    internal/child_process.js:440:11

  - From previous event:

  - compiler.js:69 Object.compileTemplate
    [starterproject]/[html-webpack-plugin]/lib/compiler.js:69:10

  - index.js:47 Compiler.<anonymous>
    [starterproject]/[html-webpack-plugin]/index.js:47:40

  - Tapable.js:107 Compiler.applyPluginsParallel
    [starterproject]/[webpack]/[tapable]/lib/Tapable.js:107:14

  - Compiler.js:394 Compiler.compile
    [starterproject]/[webpack]/lib/Compiler.js:394:7

  - Compiler.js:46 Watching.<anonymous>
    [starterproject]/[webpack]/lib/Compiler.js:46:17

  - Tapable.js:67 Compiler.next
    [starterproject]/[webpack]/[tapable]/lib/Tapable.js:67:11

  - middleware.js:80 Compiler.invalidAsyncPlugin
    [starterproject]/[webpack-dev-server]/[webpack-dev-middleware]/middleware.js:80:3

  - Tapable.js:69 Compiler.next
    [starterproject]/[webpack]/[tapable]/lib/Tapable.js:69:14

  - async.js:721
    [starterproject]/[happypack]/[async]/lib/async.js:721:13

  - async.js:52
    [starterproject]/[happypack]/[async]/lib/async.js:52:16

  - async.js:269
    [starterproject]/[happypack]/[async]/lib/async.js:269:32

  - async.js:44
    [starterproject]/[happypack]/[async]/lib/async.js:44:16

  - async.js:718
    [starterproject]/[happypack]/[async]/lib/async.js:718:17

  - async.js:167
    [starterproject]/[happypack]/[async]/lib/async.js:167:37

  - HappyPlugin.js:253 markStarted
    [starterproject]/[happypack]/lib/HappyPlugin.js:253:7

  - async.js:713
    [starterproject]/[happypack]/[async]/lib/async.js:713:13

  - async.js:262 iterate
    [starterproject]/[happypack]/[async]/lib/async.js:262:13

  - async.js:274
    [starterproject]/[happypack]/[async]/lib/async.js:274:29

  - async.js:44
    [starterproject]/[happypack]/[async]/lib/async.js:44:16

  - async.js:718
    [starterproject]/[happypack]/[async]/lib/async.js:718:17

  - async.js:167
    [starterproject]/[happypack]/[async]/lib/async.js:167:37

  - async.js:721
    [starterproject]/[happypack]/[async]/lib/async.js:721:13

  - async.js:52
    [starterproject]/[happypack]/[async]/lib/async.js:52:16

  - async.js:246 done
    [starterproject]/[happypack]/[async]/lib/async.js:246:17

  - async.js:44
    [starterproject]/[happypack]/[async]/lib/async.js:44:16



ERROR in [default] C:/Source/POC/Atlas.Prototype/src/starterproject/typings/globals/node/index.d.ts:415:10
Interface 'NodeBuffer' incorrectly extends interface 'Uint8Array'.
  Types of property 'fill' are incompatible.
    Type '(value: any, offset?: number, end?: number) => Buffer' is not assignable to type '(value: number, start?: number, end?: number) => this'.
      Type 'Buffer' is not assignable to type 'this'.
Child html-webpack-plugin for "_Layout.cshtml":
             Asset    Size  Chunks       Chunk Names
    _Layout.cshtml  608 kB       0

    ERROR in

    ERROR in

    ERROR in

    ERROR in

    ERROR in

    ERROR in

    ERROR in
webpack: bundle is now VALID.

Using your fork of ts-loader I got:

Happy[ts]: All set; signalling webpack to proceed.
 40% 6/12 build modulests-loader: Using typescript@1.8.10 and C:\Source\POC\Atlas.Prototype\src\starterproject\tsconfig.json
 25% 11/43 build modulesapplying "after-compile"...
 57% 56/70 build modulests-loader: Using typescript@1.8.10 and C:\Source\POC\Atlas.Prototype\src\starterproject\tsconfig.json
 58% 57/70 build modulests-loader[1_default] applying "after-compile" for compilation#32680
 41% 97/187 build modulesC:\Source\POC\Atlas.Prototype\src\starterproject\node_modules\ts-loader\node_modules\typescript\lib\typescript.js:39964
                throw e;
                ^

Error: Debug Failure. False expression:
    at Object.assert (C:\Source\POC\Atlas.Prototype\src\starterproject\node_modules\ts-loader\node_modules\typescript\lib\typescript.js:1721:23)
    at reportError (C:\Source\POC\Atlas.Prototype\src\starterproject\node_modules\ts-loader\node_modules\typescript\lib\typescript.js:19612:26)
    at enumRelatedTo (C:\Source\POC\Atlas.Prototype\src\starterproject\node_modules\ts-loader\node_modules\typescript\lib\typescript.js:20225:29)
    at isRelatedTo (C:\Source\POC\Atlas.Prototype\src\starterproject\node_modules\ts-loader\node_modules\typescript\lib\typescript.js:19645:34)
    at propertiesRelatedTo (C:\Source\POC\Atlas.Prototype\src\starterproject\node_modules\ts-loader\node_modules\typescript\lib\typescript.js:20015:43)
    at objectTypeRelatedTo (C:\Source\POC\Atlas.Prototype\src\starterproject\node_modules\ts-loader\node_modules\typescript\lib\typescript.js:19934:30)
    at isRelatedTo (C:\Source\POC\Atlas.Prototype\src\starterproject\node_modules\ts-loader\node_modules\typescript\lib\typescript.js:19731:38)
    at compareSignaturesRelated (C:\Source\POC\Atlas.Prototype\src\starterproject\node_modules\ts-loader\node_modules\typescript\lib\typescript.js:19486:31)
    at signatureRelatedTo (C:\Source\POC\Atlas.Prototype\src\starterproject\node_modules\ts-loader\node_modules\typescript\lib\typescript.js:20118:24)
    at signaturesRelatedTo (C:\Source\POC\Atlas.Prototype\src\starterproject\node_modules\ts-loader\node_modules\typescript\lib\typescript.js:20095:47)

Looks like i'm doing something wrong because I can't figure out how to get either to compile. FYI I cannot get my project to build using ts-loader even without happypack. It only compiles properly with awesome-typescript-loader. My project is also based on angular2-webpack-starter

@amireh
Copy link
Copy Markdown
Owner Author

amireh commented Jul 7, 2016

😱 that is not exciting news. I didn't get the chance to check out the angular project yet so I can't verify, but will take a look as soon as I can.

Also, more work was done on ts-loader than awesome-typescript-loader so far so there's definitely something up. Is your project open-source by any chance or would the starter project do just as well?

@DanielRosenwasser
Copy link
Copy Markdown

DanielRosenwasser commented Jul 7, 2016

is this 'warmup' that @amireh mentions a typescript issue?

Sorry, I just saw this message. This might just be the initial parse/bind time (parsing & binding lib.d.ts is on its own often a bottleneck) - you can see if --skipLibCheck from our nightly builds helps there at all.

@TheLarkInn
Copy link
Copy Markdown

@DanielRosenwasser is this a tsconfig option that can be used?

@DanielRosenwasser
Copy link
Copy Markdown

DanielRosenwasser commented Jul 7, 2016

It should be (in the nightlies) - check out microsoft/TypeScript#8735

@IAMtheIAM
Copy link
Copy Markdown

@amireh I will post my project source code up at my next opportunity and post the link here.

@IAMtheIAM
Copy link
Copy Markdown

IAMtheIAM commented Jul 28, 2016

Hey @amireh, here is the source code for the project I'm working on, and trying to get HappyPack working with typescript.

https://drive.google.com/open?id=0B6I99RX-ZH6gRzRqa2FtY2R0OTg

To run, follow these commands

npm run install:all
npm run start

Install will take about 5 minutes usually. To view the app, go to

http://localhost:4000

The only view of the Angular2 app you'll have access to is the login screen, but that should be fine since you're working on compilation stuff and not the app components.

Webpack config is located in /config and there are 3 webpack configs, common, development, and production. All the loaders are in webpack.common.js. The angular2 app lives in /src

@IAMtheIAM
Copy link
Copy Markdown

Hey @amireh , just wondering if this is still on your mental to do list as a possibility?

@amireh
Copy link
Copy Markdown
Owner Author

amireh commented Sep 17, 2016

@IAMtheIAM

just wondering if this is still on your mental to do list as a possibility?

I've asked webpack core for help on this, to see how webpack may be able to help typescript loaders do their job without the use of internal objects, see this discussion if you're interested. That's what's making it very difficult to support them in happypack.

I didn't do additional work on this PR because I'm not sure the approach is feasible at all; we might end up with worse performance than without happypack like you've seen so far or it will make things a maintenance nightmare on my end. I'm hoping that I could get some clues out of that discussion which would enable us to apply fixes in happypack ahead of time until webpack core officially supports this use case (this won't be until webpack 3 I believe so it's still some time away.)

So, yes, it's still on the to-do list and I hope it gets moving soon. :)

@abergs
Copy link
Copy Markdown

abergs commented Jan 18, 2017

@amireh Any new updates on this? Our build times using webpack is about 120s... we would love to use Happypack to speed things up.

@amireh
Copy link
Copy Markdown
Owner Author

amireh commented Jan 20, 2017

@abergs I'd love to help out in this but given how complicated ts loaders are, and the fact that it's a hit/miss thing (i don't really know if it can be solved at happypack's layer at all) it's going to take a lot of time to figure this out, and I don't have that time. If you're willing to sponsor the work, maybe I can investigate but otherwise I'm afraid there isn't much to do.

Did you guys try the suggestion of using the ts loader only for transpiling without the error reporting? I've heard that that works with happypack (and then you can use your editor or a separate linter to receive program-wide reports.) That may be a viable alternative?

@abergs
Copy link
Copy Markdown

abergs commented Feb 13, 2017

Hey @amireh - Thanks for getting back to me. I'm now indeed using awesome-typescript-loader only for transpiling but have yet to try HappyPack.

@amireh amireh closed this Jun 3, 2017
@amireh amireh deleted the awesome-typescript-loader-support branch June 3, 2017 00:10
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants