Skip to content

Recompile only changed file #228

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
cajoy opened this issue Nov 4, 2015 · 9 comments
Closed

Recompile only changed file #228

cajoy opened this issue Nov 4, 2015 · 9 comments
Labels

Comments

@cajoy
Copy link

cajoy commented Nov 4, 2015

Is there any way to watch change and recompile only changed file?

When I do have 1000 .ts file it takes too much time to recompile them all

@ivogabe
Copy link
Owner

ivogabe commented Nov 4, 2015

It's not possible to compile only a subset of your files, since the compiler needs all files for type information. However, there are two ways to speed up compilation:

  • With incremental compilation some time is saved because unchanged files are not re-parsed and global project-structure is reused (if possible, depending on the changes you made between two compilations). You can expect a speed decrease of up to 50%. In the readme you can find examples.
  • With isolatedModules only changed files will be recompiled, though you will loose all type checking. For quick development this is really useful: your IDE can report these type errors during development, and when doing a release you can compile without isolatedModules. You can only use this option if you're using external modules (like import * as foo from './foo'). Recompiling a changed file costs about 10-100ms.

Does one of these options solve your issue?

@chanon
Copy link

chanon commented Nov 9, 2015

I've been trying to write a gulp task that compiles only the changed files using gulp-watch together with this module. It is almost perfect, but because I have to use isolatedModules it can't do type checking.

I'm using tsconfig file with all typescript files listed in it.

var gulp = require('gulp'),
    gulpTypescript = require('gulp-typescript'),
    sourcemaps = require('gulp-sourcemaps'),
    gulpDebug = require('gulp-debug'),
    gulpFilter = require('gulp-filter'),
    gulpPlumber = require('gulp-plumber'),
    babel = require('gulp-babel'),
    watch = require('gulp-watch');

var tsProject = gulpTypescript.createProject("./tsconfig.json", {
    typescript: require('typescript')
});

gulp.task('watch', ['default'], function(cb) {  // we call 'default' to do a normal compile once first
    return tsProject.src()
        .pipe(watch(tsProject.config.files))    // watch just the input files
        .pipe(gulpFilter((file) => { file.base = '.'; return file.event === 'change'; }))   // just when a file changes, the file.base is a hack because watch doesn't set the correct one
        .pipe(gulpPlumber())    // don't break when error occurs
        .pipe(gulpDebug({title: 'changed'}))    // list the files we got in
        .pipe(sourcemaps.init())
            .pipe(gulpDebug({title: 'a'}))  // still there?
            .pipe(gulpTypescript( PROJECT_OR_OPTIONS )) // explained below
            .js
            .pipe(gulpDebug({title: 'b'}))  // doesn't get here if using project
            .pipe(babel(babelOptions))  // my babel stuff .. other processing could follow
            .pipe(gulpDebug({title: 'compiled'}))
        .pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: '.'}))
        .pipe(gulp.dest('.'));
});

So, if I send the tsProject to the gulpTypescript function, it just hangs doing nothing. It never goes to 'b'.

However, if I send in compiler options using isolatedModules, it works. It will compile only the changed file, but I don't get type checking.

I think this can be fixed/improved if the following was implemented:

  • Add a similar option to isolatedModules that compiles files as they come in, but with type checks.
  • Add another option to allow specifying d.ts files that should always be included in compiling.

These two options together will allow correctly compiling single ts files one by one as they are modified.

This is because usually with tsc, you can correctly compile a single ts file if you supply any d.ts files that are required but were not referenced inside the .ts file.

@chanon
Copy link

chanon commented Nov 10, 2015

Actually, after thinking about it some more, to make it perfect, it might need to use a new kind of tsProject that keeps track of which source files depend on which. Then when one file changes, it should compile that file and also any files that directly depend on that file. (But not the whole project.) This is so you can see if the changed file affects/causes any other files in the project to error.

I actually wrote my own tswatcher script that works this way. It goes through every source file to determine dependencies and compile only dependent files on change. However I can't use it anymore because I need to use babel and sourcemaps also.

For now, I'm happy with the gulp task above because it is very fast. And for type checks I can look at IDE (Visual Studio Code) or when doing full build.

@ivogabe
Copy link
Owner

ivogabe commented Nov 16, 2015

@chanon It's not easy to compile a part of the project. Type checking needs type information of the whole project, thus all files need to be passed to the compiler. The compiler needs both the files that depend on the input and the files on which the input depends. Recursively this would give the whole project (provided that all files in the project are somehow connected).

If you want to speed up this process you can give up type checking and use isolatedModules. Because this does file based analysis, it's not possible to do type checking with isolated modules.

I'd advise for big projects to use isolatedModules for development, and turn the option off for release builds.

@anjmao
Copy link

anjmao commented Jun 16, 2016

I saw angular-cli uses https://www.npmjs.com/package/broccoli-typescript for much faster builds :)

@ivogabe
Copy link
Owner

ivogabe commented Jun 16, 2016

They aren't using that package, they built this: [https://github.com/angular/angular/blob/master/tools/broccoli/broccoli-typescript.ts]. They seem to use file name conventions to recompile a part of the files.

@ngasst
Copy link

ngasst commented Jun 16, 2016

Not sure if this is something someone might still be looking for (seeing as this issue is closed). If so, hit reply and I'll share my workaround. It still requires an editor like VSCode for type-checking, but works. I could get the hack here to work.

@jbaxleyiii
Copy link

@ngasst I'd love to know a workaround, it makes running typescript watch and ava watch impossible as all files are retested on change

@jasselin
Copy link

jasselin commented Aug 24, 2016

@ngasst same here, still trying to make this work.
EDIT: this just saved my ass: https://github.com/mgechev/angular2-seed/wiki/Speeding-the-build-up

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants