Skip to content

Instantly share code, notes, and snippets.

@dcousineau
Created March 22, 2016 21:17
Show Gist options
  • Save dcousineau/e1b0b02d4f9b1f34fb08 to your computer and use it in GitHub Desktop.
Save dcousineau/e1b0b02d4f9b1f34fb08 to your computer and use it in GitHub Desktop.
var fs = require('fs');
var path = require('path');
var cachingTransform = require('caching-transform');
var md5Hex = require('md5-hex');
var stripBom = require('strip-bom');
var objectAssign = require('object-assign');
module.exports = CachingPrecompiler;
function CachingPrecompiler(cacheDir, babelConfig) {
console.log("Initializing CachingPrecompiler with:", babelConfig);
if (!(this instanceof CachingPrecompiler)) {
throw new TypeError('Class constructor CachingPrecompiler cannot be invoked without \'new\'');
}
this.cacheDir = cacheDir;
this.filenameToHash = {};
this.transform = this._createTransform(babelConfig);
}
CachingPrecompiler.prototype._factory = function (babelConfig, cacheDir) {
// This factory method is only called once per process, and only as needed, to defer loading expensive dependencies.
var babel = require('babel-core');
var convertSourceMap = require('convert-source-map');
var presetStage2 = require('babel-preset-stage-2');
var presetES2015 = require('babel-preset-es2015');
var transformRuntime = require('babel-plugin-transform-runtime');
var powerAssert = this._createEspowerPlugin(babel);
function buildOptions(filename, code) {
// Extract existing source maps from the code.
var sourceMap = convertSourceMap.fromSource(code) || convertSourceMap.fromMapFileSource(code, path.dirname(filename));
var options = {babelrc: false};
console.log(":: buildOptions()");
if (!babelConfig || babelConfig === 'default') {
objectAssign(options, {presets: [presetStage2, presetES2015]});
console.log("Default Babel Config", options);
} else if (babelConfig === 'inherit') {
objectAssign(options, {babelrc: true});
console.log("Inherit Babel Config", options);
} else {
console.log("Overriding Babel Config", babelConfig);
objectAssign(options, babelConfig);
}
objectAssign(options, {
inputSourceMap: sourceMap && sourceMap.toObject(),
filename: filename,
sourceMaps: true,
ast: false
});
options.plugins = options.plugins || [];
options.plugins.push(powerAssert, transformRuntime);
console.log("Final Options", options);
return options;
}
return function (code, filename, hash) {
console.log("++ About to actually execute transform...");
code = code.toString();
var options = buildOptions(filename, code);
var result = babel.transform(code, options);
var mapFile = path.join(cacheDir, hash + '.map');
fs.writeFileSync(mapFile, JSON.stringify(result.map));
console.log("++ Finished transform");
return result.code;
};
};
CachingPrecompiler.prototype._createEspowerPlugin = function (babel) {
var createEspowerPlugin = require('babel-plugin-espower/create');
var enhanceAssert = require('./enhance-assert');
// initialize power-assert
return createEspowerPlugin(babel, {
patterns: enhanceAssert.PATTERNS
});
};
CachingPrecompiler.prototype._createTransform = function (babelConfig) {
console.log("_createTransform with:", babelConfig);
return cachingTransform({
factory: this._factory.bind(this, babelConfig),
cacheDir: this.cacheDir,
salt: new Buffer(JSON.stringify({
'babel-plugin-espower': require('babel-plugin-espower/package.json').version,
'ava': require('../package.json').version,
'babel-core': require('babel-core/package.json').version,
'babelConfig': babelConfig
})),
ext: '.js',
hash: this._hash.bind(this)
});
};
CachingPrecompiler.prototype._hash = function (code, filename, salt) {
var hash = md5Hex([code, filename, salt]);
this.filenameToHash[filename] = hash;
return hash;
};
CachingPrecompiler.prototype.precompileFile = function (filename) {
if (!this.filenameToHash[filename]) {
this.transform(stripBom(fs.readFileSync(filename)), filename);
}
return this.filenameToHash[filename];
};
CachingPrecompiler.prototype.generateHashForFile = function (filename) {
var hash = {};
hash[filename] = this.precompileFile(filename);
return hash;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment