Skip to content

Instantly share code, notes, and snippets.

@delfrrr
Created September 7, 2015 13:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save delfrrr/4ccc04afb91520306db2 to your computer and use it in GitHub Desktop.
Save delfrrr/4ccc04afb91520306db2 to your computer and use it in GitHub Desktop.
/**
* pack js and less for browser isolated
*/
/**
* @typedef {object} IsopackOptions
* @param {('js'|'less')} options.type
* @param {string} options.sourceId
*/
var Vow = require('vow'),
deps = require('module-deps'),
browserify = require('browserify'),
literalify = require('literalify'),
transformTools = require('browserify-transform-tools'),
/**
* stream for getting deps and process all less files
* @return {Stream}
*/
getLessTransformStream = function () {
var less = require('less'),
through = require('through'),
promises = [];
return through(function (data) {
var stream = this;
if (data.file.match(/\.less$/)) {
promises.push(less.render(data.source, {
filename: data.file
}).then(function (output) {
stream.queue(output.css);
}, function (err) {
console.error(err);
}));
}
}, function () {
var stream = this;
//wait for all less to be rendered
Vow.all(promises).always(function (p) {
stream.emit('end');
return p;
}).done();
}, {
autoDestroy: false
});
},
/**
* @param {Stream} stream
* @param {IsopackOptions} options
*/
pipeLess = function (stream, options) {
var depsStream = deps({
ignoreMissing: true,
//hack for not parsing native and package.json modules
filter: function (id) {
return id.match(/\//);
},
noParse: options.noParse
});
depsStream.on('error', function (err) {
if (!options.silent) {
console.error('isopack less error:', err);
}
stream.end();
});
depsStream.pipe(getLessTransformStream()).pipe(stream);
depsStream.end({
file: require.resolve(options.sourceId)
});
},
/**
* @param {Stream} stream
* @param {IsopackOptions} options
*/
pipeJs = function (stream, options) {
var bStream;
bStream = browserify({
fullPaths: true,
}).add(require.resolve(options.sourceId))
.transform(literalify.configure({react: 'window.React'}))
//remove .*node from client
//move to options
.transform(transformTools.makeRequireTransform('node-js-transform', {}, function (args, opts, cb) {
if (
args[0].match(/.*\.node(\.js)?$/) ||
args[0].match(/.*\.less$/)
) {
cb(null, 'null');
} else {
cb();
}
}))
.bundle();
bStream.on('error', function (err) {
if (!options.silent) {
console.error(err);
}
stream.end();
});
bStream.pipe(stream);
},
/**
* @param {IsopackOptions} options
* @return {function} middleware
*/
getLessMiddleware = function (options) {
//hack for require('some.less') can work
require.extensions['.less'] = function (module) {
module.exports = null;
};
return function (req, res) {
res.type('css');
pipeLess(res, options);
};
},
/**
* @param {IsopackOptions} options
* @return {function} middleware
*/
getJsMiddleware = function (options) {
return function (req, res) {
res.type('js');
pipeJs(res, options);
};
},
/**
* @param {IsopackOptions} options
*/
validateIsopackOptions = function (options) {
options = options || {};
if (!options.sourceId) {
throw new Error('Bad options.sourceId = ' + options.sourceId);
}
if (options.type !== 'js' && options.type !== 'less') {
throw new Error('Unknow options.type ' + options.type);
}
};
module.exports = {
/**
* pipe bundle into stream
* @param {Stream} stream
* @param {IsopackOptions} options
*/
pipe: function (stream, options) {
validateIsopackOptions(options);
if (options.type === 'less') {
return pipeLess(stream, options);
} else if (options.type === 'js') {
return pipeJs(stream, options);
}
},
/**
* get express middleware
* @param {IsopackOptions} options
* @return {function} middleware
*/
middleware: function (options) {
validateIsopackOptions(options);
if (options.type === 'less') {
return getLessMiddleware(options);
} else if (options.type === 'js') {
return getJsMiddleware(options);
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment