Skip to content

Speeding the build up

Brian Kotek edited this page Jul 15, 2016 · 5 revisions

TypeScript performs compile-time type checking over all your files. The build invokes the tasks which cleans the dist directory and performs transpilation of the TypeScript files on each change. Obviously, there are places for improvements.

TYPED_COMPILE_INTERVAL config option

The project build configuration now exposes a field called TYPED_COMPILE_INTERVAL. By default, this is set to 0, meaning a fully typed TypeScript compilation will be executed after each file change is saved. Changing this value in your project.config.ts can dramatically speed up the TypeScript compilation task.

For example, setting TYPED_COMPILE_INTERVAL=5; means that a fully typed compile will be performed when running npm start. Then, the next 5 changes will trigger a cached, typeless compilation (using gulp-cached and isolatedModules). The next compile will be a fully typed compile, then 5 more typeless compiles, and so on.

Finally, if a compile error is encountered at any time, the build will force fully typed compiler runs until the compile error is eliminated. Once any error(s) are fixed, the build then proceeds with alternating between typed and typeless compiles again.

This setup provides an acceptable balance between build speed and type checking. So don't set TYPED_COMPILE_INTERVAL to a value that is too large, since the longer the interval, the longer it may take for a typed compile to run and identify type errors.

isolatedModules

Using isolatedModules will lead to:

Compiles files seperately and doesn't check types, which causes a big speed increase. You have to use gulp-plumber and TypeScript 1.5+.

However, this way you're giving up the main feature of TypeScript - type checking. It is not recommended to enable this option for your production build, however, for development it could be a good strategy for increasing your build's speed. Most IDEs and text editors invoke the TypeScript compiler behind the scene and point out the type errors we did in our source files. In such case in order to speedup the build you can disable type checking in the build and let your text editor handles the rest.

In order to enable the isolatedModules config for your dev build override your build.js.dev tasks with the following:

// tools/tasks/project/build.js.dev.ts

import * as gulp from 'gulp';
import * as gulpLoadPlugins from 'gulp-load-plugins';
import {join} from 'path';
import {APP_SRC, APP_DEST, TOOLS_DIR} from '../../config';
import {templateLocals, makeTsProject} from '../../utils';
const plugins = <any>gulpLoadPlugins();

export = () => {
  let tsProject = makeTsProject({
    isolatedModules: true
  });
  let src = [
    'typings/browser.d.ts',
    TOOLS_DIR + '/manual_typings/**/*.d.ts',
    join(APP_SRC, '**/*.ts'),
    '!' + join(APP_SRC, '**/*.spec.ts'),
    '!' + join(APP_SRC, '**/*.e2e.ts')
  ];
  let result = gulp.src(src)
    .pipe(plugins.plumber())
    .pipe(plugins.sourcemaps.init())
    .pipe(plugins.typescript(tsProject));

  return result.js
    .pipe(plugins.sourcemaps.write())
    .pipe(plugins.template(templateLocals()))
    .pipe(gulp.dest(APP_DEST));
};

Disable linting tasks

Most text editors and IDEs run tslint behind the scene. This way, during development, we run linting (at least) twice:

  • Inside of the text editor/IDE
  • By the gulp task build.dev

In order to speedup the build you can just comment the tslint and css-lint tasks and let your text editor/IDE takes care of pointing out the errors you did.

Use gulp-cached

This keeps an in-memory cache of files (and their contents) that have passed through it. If a file has already passed through on the last run it will not be passed downstream. This means you only process what you need and save time + resources.

This means that files which haven't changed will not be processed, i.e. will not be stored onto the disk. The build has a clean task, which on each change of a file will remove dist/dev or dist/prod. This happens because we don't want to have files which have already been removed from your src directory existing in dist/ENV, since this can lead to unpredictable bugs.

In order to take advantage of gulp-cached you must disable the relevant clean.{ENV} task in gulpfile.ts (e.g. inside build.dev). Otherwise, only the changed (uncached) build output files will remain (since everything else is removed during clean). Finally, in your JS build task, separate your source files from your typings and then pipe your source files through gulp-cached:

// Inside tools/tasks/project/build.js.dev.ts
import * as merge from 'merge-stream';
//...

let typings = gulp.src([
        'typings/browser.d.ts',
        join(config.TOOLS_DIR + '/manual_typings/**/*.d.ts')]);
let projectFiles = gulp.src(src)
        .pipe(plugins.cached());
let result = merge(typings,projectFiles)
        .pipe(plugins.debug())
        .pipe(plugins.plumber())
        .pipe(plugins.sourcemaps.init())
        .pipe(plugins.typescript(tsProject));

Further discussions

For further discussions on tuning the performance, take a look at this issue.