Speed of Awesome-typescript-loader vs ts-loader · Issue #497 · s-panferov/awesome-typescript-loader (original) (raw)

After using awesome-typescript-loader for over a year, I decided to switch to TS-loader to test the speed difference. I'm glad I did. My angular 4 webpack-dev-server build went from 41 seconds down to 15 seconds, with absolutely no changes at all to config, only adding fork-ts-checker-webpack-plugin, which awesome-typescript-loader does by default.

Also, since TS-loader is compatible with HappyPack for parallel build processes, I got devserver build time down to 13 seconds. With webpack thread-loader (instead of HappyPack) i got it down to 12 seconds

My AOT production build dropped from 122 seconds down to 93 seconds. With HappyPack/thread-loader, down to 79 seconds. Awesome!!

Awesome-typescript-loader, thanks for your hard work, the plugin works but ts-loader is much faster (for my specific setup) and that is important.

My question is, why is ts-loader so much faster than awesome-typescript-loader - or why perhaps might it be? 30 seconds saving is a lot of time.

In case anyone wants to see my new setup that is down to about 12 seconds, here it is

(this is for Angular 4+)

/** * TypeScript loader support for *.ts files */

     {
        test   : /\.ts$/,
        exclude: [ENV !== 'test'
           ? /\.(spec|e2e)\.ts$/
           : '//'],
        use    : [

           // {
           //    // If any of the npm packages or loader configutation changes, you need to invalidate/delete the .cache folder. It should happen automatically though.
           //    loader: 'cache-loader',
           //    options: {
           //       cacheDirectory: isDevServer
           //          ? Helpers.root('./.cache/cache-loader/dev/[confighash]')
           //          : isDebug
           //              ? Helpers.root('./.cache/cache-loader/debug/[confighash]')
           //              : Helpers.root('./.cache/cache-loader/prod/[confighash]')
           //       }
           //    },
           {
              loader : '@angularclass/hmr-loader',
              options: {
                 pretty: !isProduction,
                 prod  : isProduction
              }
           }, {
              /**
               * Lazy Module loader
               *  MAKE SURE TO CHAIN VANILLA JS CODE, I.E. TS COMPILATION OUTPUT.
               */
              loader : 'ng-router-loader',
              options: {
                 loader: 'async-import',
                 genDir: 'compiled',
                 aot   : AOT
              }
           }, {
              loader : 'thread-loader',
              options: {
                 // there should be 1 cpu for the fork-ts-checker-webpack-plugin
                 // workers: require('os').cpus().length - 1,
                 workers: isDevServer
                    ? 3
                    : require('os').cpus().length - 1 // fastest build time for devServer: 3 threads; for production: 7 threads (os cpus minus 1)
              }
           },

           {
              loader : 'ts-loader',
              options: {
                 // disable type checker - we will use it in fork plugin
                 transpileOnly: true,
                 happyPackMode: true
              }
           }, {
              loader: 'angular2-template-loader'
           }]
     },

Basically you just pipe ts-loader to thread-loader.

As an EXTRA bonus, I just learned about hard-source-webpack-plugin. Using this plugin affects the above config like this, taking it from 14 seconds to:

Initial build: 22 seconds (twice as slow)
Rebuild: 6 seconds (double as fast)

What is does is write cache to disk, and makes it slower at first, but really fast on rebuild.

Here's how to enable that. I set it up to use a different cache for webpackDevServer, debug-production, and production build.

plugins: [
 /**
       * Makes a hard cache of webpack builds to speed up build times.
       *
       * Increases initial build time by double but decreases subsequent rebuilds by 2X-4X
       * If any of the npm packages or any webpack configutation changes (excluding comments), a new cache will be generated automatically, and the old can be
       * deleted manually.
       *
       * See: https://github.com/mzgoddard/hard-source-webpack-plugin
       */

      new HardSourceWebpackPlugin({
         cacheDirectory : isDevServer
            ? Helpers.root('./.cache/hard-source/dev/[confighash]')
            : isDebug
               ? Helpers.root('./.cache/hard-source/debug/[confighash]')
               : Helpers.root('./.cache/hard-source/prod/[confighash]'),
         recordsPath    : isDevServer
            ? Helpers.root('./.cache/hard-source/dev/[confighash]/records.json')
            : isDebug
               ? Helpers.root('./.cache/hard-source/debug/[confighash]/records.json')
               : Helpers.root('./.cache/hard-source/prod/[confighash]/records.json'),
         configHash     : require('node-object-hash')({ sort: false }).hash,
         environmentHash: {
            directories: ['node_modules'],
            files      : ['npm-shrinkwrap.json', 'yarn.lock'],
            root       : process.cwd()
         }
      }),
]

An alternative version of HardSourceWebpackPlugin is cache-loader. Its very similar, but a little faster on initial and a little slower on rebuild compared to HardSourceWebpackPlugin

Instead of being a plugin, its a loader, that goes as the very FIRST loader in the array, which means its the last loader executed by webpack. It is commented out in my example above for reference.

I hope this helps!