Skip to content
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

fix(plug-in): use absolute paths to reference entry points #71

Merged
merged 9 commits into from
Dec 21, 2014
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ There are three properties that are not passed directly:

* [transform](#transforms)
* [plugin](#plugins)
* [prebundle](#additional-bundle-configuration)
* [configure](#additional-bundle-configuration)

#### Transforms

Expand Down Expand Up @@ -91,12 +91,14 @@ The [browserify plugin](https://github.com/substack/node-browserify#bpluginplugi

#### Additional Bundle Configuration

You may perform additional configuration in a function that you pass as the `prebundle` option and that receives the bundle as an argument. This is useful when you need to set up things like [externals](https://github.com/substack/node-browserify#external-requires):
You may perform additional configuration in a function passed as the `configure` option and that receives the browserify instance as an argument. A custom `prebundle` event is emitted on the bundle right before a bundling operation takes place. This is useful when setting up things like [externals](https://github.com/substack/node-browserify#external-requires):

```javascript
browserify: {
prebundle: function(bundle) {
bundle.external('foobar');
configure: function(bundle) {
bundle.on('prebundle', function() {
bundle.external('foobar');
});
}
}
```
Expand Down Expand Up @@ -144,9 +146,10 @@ module.exports = function(karma) {
browserify: {
debug: true,
transform: [ 'brfs' ],
prebundle: function(bundle) {
// additional configuration, e.g. externals
bundle.external('foobar');
configure: function(bundle) {
bundle.on('prebundle', function() {
bundle.external('foobar');
});
}
}
});
Expand Down
102 changes: 42 additions & 60 deletions lib/bro.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ function Bro(bundleFile) {
// add bundle file to the list of files defined in the
// configuration. be smart by doing so.
addBundleFile(bundleFile, config);

return b;
}

framework.$inject = [ 'emitter', 'config', 'logger' ];
Expand All @@ -132,11 +134,17 @@ function Bro(bundleFile) {
}
});

var browserifyOptions = _.extend({}, watchify.args, _.omit(bopts, [
'transform', 'plugin', 'prebundle'
var browserifyOptions = _.extend({ basedir: config.basePath }, watchify.args, _.omit(bopts, [
'transform', 'plugin', 'configure', 'bundleDelay'
]));

if ('prebundle' in browserifyOptions) {
log.warn('The prebundle hook got removed in favor of configure');
}


var w = watchify(browserify(browserifyOptions));
w.setMaxListeners(Infinity);

_.forEach(bopts.plugin, function(p) {
// ensure we can pass plugin options as
Expand All @@ -156,9 +164,9 @@ function Bro(bundleFile) {
w.transform.apply(w, t);
});

// test if we have a prebundle function
if (bopts.prebundle && typeof bopts.prebundle === 'function') {
bopts.prebundle(w);
// test if we have a configure function
if (bopts.configure && typeof bopts.configure === 'function') {
bopts.configure(w);
}

// register rebuild bundle on change
Expand All @@ -167,26 +175,21 @@ function Bro(bundleFile) {

w.on('update', function(updated) {

var rebundleRequired = _.any(updated, function(f) {
return files.indexOf(f) === -1;
});
// we perform an update, karma will trigger one, too
// because the bundling is deferred only one change will
// be triggered. Anything else is the result of a
// raise condition or a problem of watchify firing file
// changes to late

if (rebundleRequired) {
log.debug('files changed');
deferredBundle();
} else {
log.debug('skipping update');
}
log.debug('files changed');
deferredBundle();
});
}

w.on('log', function(msg) {
log.info(msg);
});

// files contained in bundle
var files = [ ];


// update bundle file
w.on('bundled', function(err, content) {
Expand All @@ -207,86 +210,65 @@ function Bro(bundleFile) {
rebuild();
}


var MISSING_MESSAGE = /^Cannot find module '([^']+)'/;

var rebuild = _.debounce(function rebuild() {

// check if we already bundled once and
// restore transforms / plug-ins accordingly
// after resetting the bundle

if (w._bundled) {
log.debug('resetting bundle');

var recorded = w._recorded;
w.reset();

log.debug('resetting bundle');

recorded.forEach(function (tr) {
if (tr.transform) {
w.pipeline.write(tr);
recorded.forEach(function(e) {
// we remove missing files on the fly
// to cope with bundle internals missing
if (e.file && !fs.existsSync(e.file)) {
log.debug('removing missing file', path.relative(config.basePath, e.file));
} else {
w.pipeline.write(e);
}
});
}

log.debug('bundling');
w.emit('prebundle', w);

files.forEach(function(f) {
w.require(f, { expose: path.relative(config.basePath, f) });
});
log.debug('bundling');

w.bundle(function(err, content) {

if (err) {
log.error('bundle error');
log.error(String(err));

// try to recover from removed test case
// rebuild, if successful
var match = MISSING_MESSAGE.exec(err.message);
if (match) {
var idx = files.indexOf(match[1]);

if (idx !== -1) {
log.debug('removing %s from bundle', match[1]);
files.splice(idx, 1);

log.debug('attempting rebuild');
return rebuild();
}
}
}

w.emit('bundled', err, content);
});
}, 500);
}, bopts.bundleDelay || 700);


w.bundleFile = function(file, done) {

var absolutePath = file.path,
relativePath = path.relative(config.basePath, absolutePath);
relativePath = path.relative(config.basePath, absolutePath),
cache = w._options.cache;

if (files.indexOf(absolutePath) === -1) {
// add file
log.debug('updating %s in bundle', relativePath);

// add file
log.debug('adding %s to bundle', relativePath);

files.push(absolutePath);
}
// add the file during next prebundle step
w.once('prebundle', function() {
w.require('./' + relativePath, { expose: absolutePath });
});

deferredBundle(function(err) {
done(err, 'require("' + escape(relativePath) + '");');
done(err, 'require("' + absolutePath + '");');
});
};


/**
* Wait for the bundle creation to have stabilized (no more additions) and invoke a callback.
*
* @param {Function} cb
* @param {Number} delay
* @param {Number} timeout
* @param {Function} [callback] invoked with (err, content)
*/
w.deferredBundle = deferredBundle;

Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
},
"bugs": "https://github.com/Nikku/karma-browserify/issues",
"dependencies": {
"browserify": "~7.0.2",
"browserify": "Nikku/node-browserify.git#local-fix",
"convert-source-map": "~0.3.3",
"js-string-escape": "^1.0.0",
"lodash": "~2.4.1",
Expand All @@ -33,6 +33,7 @@
},
"devDependencies": {
"brfs": "^1.2.0",
"browser-unpack": "~1.0.0",
"chai": "^1.9.1",
"chai-spies": "^0.5.1",
"grunt": "~0.4.4",
Expand All @@ -41,9 +42,11 @@
"grunt-mocha-test": "^0.11.0",
"grunt-release": "~0.7.0",
"karma": "^0.12.19",
"karma-jasmine": "^0.1.5",
"karma-phantomjs-launcher": "^0.1.4",
"load-grunt-tasks": "~0.4.0",
"tsify": "^0.6.1",
"browser-unpack": "~1.0.0"
"touch": "0.0.3",
"tsify": "^0.6.1"
},
"peerDependencies": {
"karma": ">=0.10"
Expand Down
File renamed without changes.
7 changes: 7 additions & 0 deletions test/integration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,11 @@ karma start

```
karma start --auto-watch --no-single-run --browsers=Chrome
```


## Recreate prebundled common module

```
npm install browserify && node_modules/.bin/browserify -r ./lib/common.js -o prebundled/common.js
```
12 changes: 12 additions & 0 deletions test/integration/auto-watch.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';

var base = require('./single-run.conf');

module.exports = function(karma) {
base(karma);

karma.set({
singleRun: false,
autoWatch: true
});
};
17 changes: 15 additions & 2 deletions test/integration/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
module.exports = function(karma) {
karma.set({

plugins: ['karma-*', require('../..')],

frameworks: [ 'jasmine', 'browserify' ],

files: [
// external (non-browserified) library that exposes a global
'vendor/external.js',

// external (browserified) bundle
'prebundled/common.js',

// source file, accidently included
// (there is usually no reason to do this)
'lib/a.js',
Expand All @@ -25,7 +30,7 @@ module.exports = function(karma) {
preprocessors: {
'lib/a.js': [ 'browserify' ],
'test/*Spec.js': [ 'browserify' ],
'test/helper.js': [ 'browserify' ],
'test/helper.js': [ 'browserify' ]
},

browsers: [ 'PhantomJS' ],
Expand All @@ -38,7 +43,15 @@ module.exports = function(karma) {
// browserify configuration
browserify: {
debug: true,
transform: [ 'brfs' ]
transform: [ 'brfs' ],

// configure browserify
configure: function(b) {

b.on('prebundle', function() {
b.external('lib/common.js');
});
}
}
});
};
2 changes: 1 addition & 1 deletion test/integration/lib/a.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
module.exports = require('./c');
module.exports = require('./common').a;
1 change: 0 additions & 1 deletion test/integration/lib/c.js

This file was deleted.

6 changes: 6 additions & 0 deletions test/integration/lib/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* This file gets prebundled into a dist/common.js bundle.
*
* It is included before the browserified test files.
*/
module.exports.a = 'A';
22 changes: 0 additions & 22 deletions test/integration/package.json

This file was deleted.

8 changes: 8 additions & 0 deletions test/integration/prebundled/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"/lib/common.js":[function(require,module,exports){
/*
* This file gets prebundled into a dist/common.js bundle.
*
* It is included before the browserified test files.
*/
module.exports.a = 'A';
},{}]},{},[]);
22 changes: 22 additions & 0 deletions test/integration/single-run.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict';

var base = require('./karma.conf');

module.exports = function(karma) {
base(karma);

karma.set({
files: [
'vendor/external.js',
'test/externalSpec.js'
],

preprocessors: {
'test/externalSpec.js': [ 'browserify' ]
},

reporters: [],

logLevel: 'ERROR',
});
};
Loading