Skip to content

File watcher that manages JSPM bundling and cache invalidation

License

Notifications You must be signed in to change notification settings

fyodorvi/jspm-watch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JSPM Watch

Inspired by jspm-dev-builder JSPM Watch keeps your code changes in immediate sync with the browser no matter how big your app is and how many dependencies you have. JSPM Watch is designed for a long run: no matter what you do to your project files, whenever you add or remove new dependencies, have compilation errors, or simply switch branches - it should keep running, with no need to ever restart it. There's also an option to do simultaneous unit tests build, so you can do tdd and run the app at the same time.

Why

As your project grows it may take enormous amount of time to reload the application after a file change. JSPM Watch solves that issue by pre-bundling the app, which takes some time at first, but then upon any file change it invalidates it from cache and re-bundles the app, which takes about a second.

Table of Contents

Features

  • proper dependencies addition/removal handling: ideally, no need to restart the process ever
  • minimum and straightforward configuration
  • hassle-free file watching with built-in chokidar
  • both windows and unix support
  • unit tests build support
  • proper compilation error handling
  • informative console output
  • non-javascript modules support - css and html

Other solutions like jspm-dev-builder or systemjs-hot-reloader lack these features (especially first one).

Requirements

Installed JSPM of at least 0.16.12 version within the project.

Install

npm i jspm-watch

Usage

Please refer to the test-project for full usage example.

Minimum configuration

var JspmWatch = require('jspm-watch');

watcher = new JspmWatch({
   app: {
      input: 'src/my-app.js',
      output: 'dist/my-app.js'
   }
});

watcher.start();

Tip: The "input" attribute of the "app" key, is optional if jspm.main is defined in package.json

Extended configuration with unit tests build

var JspmWatch = require('jspm-watch');

watcher = new JspmWatch({
   app: {
      input: 'src/my-app.js',
      output: 'dist/my-app.js',
      buildOptions: {
        minify: false,
        mangle: false,
        sourceMaps: false
      }
   },
   tests: {
      watch: 'src/**/*.spec.js',
      input: 'src/unit-tests.js', // this file will be auto-generated
      output: 'dist/unit-tests.js' // this file should be consumed by your test runner e.g. karma
   },
   batchDelay: 250 // build delay when processing batch changes
});

watcher.start().on('change', function(event) {
    if (!event.hasError) {
       if (event.type == 'app') {
          browserSync.reload();
       }
       if (event.type == 'tests') {
          karmaServer.refreshFiles();
       }
    }
});

Documentation

Constructor

Returns an instance of JSPM Watch.

var JspmWatch = require('jspm-watch');

watcher = new JspmWatch({
    app: {
        watch: ['src/**/*.js', 'src/**/*.html', 'src/**/*.css'],
        input: 'src/my-app.js',
        output: 'dist/my-app.js'
    }
});

Constructor options

app.watch (optional)

Since 0.2.0 by default jspm-watch uses SystemJS Builder trace() method to watch file changes. Use app.watch to override it and provide an array or string of files to watch that will be passed to chokidar. You don't need to exclude jspm_packages, it's done by default. Tests files are excluded by default if tests section is provided.

app.input

You app entry point.

app.output

You app ouput destination file .

app.buildOptions

Build options which are going to be passed to SystemJS Builder. Default options are:

{
    sfx: false,
    minify: false,
    mangle: false,
    sourceMaps: true,
    lowResSourceMaps: true
}

sfx option is non-overridable, self extracting bunding is not supported at the moment. jackfranklin/jspm-dev-builder#9

tests.watch

Unit tests files to watch. Don't need to provide app files pattern if app.watch is configured:

watcher = new JspmWatch({
    app: {
       watch: ['src/**/*.js']
    },
    tests: {
       watch: ['src/**/*.spec.js'],
       input: 'src/unit-tests.js',
       output: 'dist/unit-tests.js'
    }
});
watcher.start();

tests.input

Path for a file which will be auto-generated by JSPM Watch with imports of all spec files.

tests.output

Tests bundle output destination. Should be consumed by tests runner.

tests.buildOptions

Same as app.buildOptions.

batchDelay

Delay in milliseconds before build will be fired. Default is 250.

usePolling

Turns on chokidar polling option. Try to use it if you are having trouble with fs events. Default is false.

debug

Turns on debug output. Useful when trying to understand problems. Default is false.

start([options])

Returns instance of JSPM Watch for chaining.

Does initial build and starts watching for file changes. If no options provided watches both tests and app changes.

watcher.start();

Start options

Start options are usefull when you have watcher configured just once and then you have different gulp (or any other) tasks.

App only

Tells watcher to watch only app changes ingnoring tests.

watcher.start({ appOnly: true });

Tests only

Tells watcher to watch only tests changes ingnoring app.

watcher.start({ testsOnly: true });

emitter

JSPM Watch manages events with node EventEmitter which is stored in emitter property.

watcher.emitter.on('started', method);

However, there are shorthand methods for on and once:

watcher.on('started', method); // equivalent of watcher.emitter.on
watcher.once('change', method);  // equivalent of watcher.emitter.once

Events

started

Emitted when JSPM Watch started and done initial build (both app and tests if configured). May be usefull for task runner.

gulp.task('watch', function(done) {
    watcher.start().on('started', function() {
       done();
    });
})

change

Emitted when JSPM Watch detected file change and perfomed a build. Even if build fails with error, event is still emitted. Provides event object with two properties: type and hasError.

watcher.start().on('change', function(event) {
   if (!event.hasError) {
       if (event.type == 'app') {
          browserSync.reload();
       }
       if (event.type == 'tests') {
          karmaServer.refreshFiles();
       }
    }
});

event.type

Possible options are 'app' and 'tests'. Indicates which build has happend.

event.hasError

Indicates whether build has compilation error.

beforeBuild

Emitter when JSPM Watch is going to perform a build of any kind. May be usefull for some build pre-hook actions. Provides event object with two properties: type and buildState.

 watcher.start().on('beforeBuild', function(event) {
   if (event.type == 'app') {
        fs.closeSync(fs.openSync(paths.src+'/styles.css', 'w'));
        jspmWatch.once('change', function () {
            fs.unlinkSync(paths.src+'/styles.css');
        });
    }
});

event.type

Possible options are 'app' and 'tests'. Indicates which build has happend.

event.buildState

An object, which properties include:

{
    entireBuild: true, // indicates that it's going to be a full build
    hasError: true, // indicates that previous build had an error
    changedModules: [{ moduleName: 'app.js', event: 'change' }] // array of changed modules with names and events (vinyl: change, add, unlink)
}

Unit tests bundle approach described

The idea is simple: JSPM Watch bundles every spec file and app files into single giant file which should be consumed by test runner. Otherwise it make take enormous amout of time to load all dependencies with karma-jspm, which makes tdd impossibly painfull. Since your project should be fully covered by tests, build time should be marginally the same for watcher.start({ testsOnly: true }) and watcher.start() since internally JSPM Watch uses single instance of SystemJS Builder, so cache is shared.

Change log

1.0.2

  • added usePolling option

0.3.0

  • input attribute of app, is optional if jspm.main is defined in package.json
  • baseURL is auto assumed "." instead of causing app build failure
  • Moves JSPM Builder into separate process to avoid annoying memory leak on config change

0.2.0

  • Changed app.watch to be an optional configuration param, by default JSPM Watch will use SystemJS trace to get the list of files
  • Added progress bar when building entire app
  • Unit tests import file is no longer generated and removed upon each file update, it's being written only when needed and removed only on process exit

0.1.9

  • JSPM is a peerDependency now, no need to pass it as a constructor option
  • Fixed JSPM config changes handling

0.1.0

  • Initial commit

License

MIT

About

File watcher that manages JSPM bundling and cache invalidation

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •