keystone
Version:
Web Application Framework and Admin GUI / Content Management System built on Express.js and Mongoose
165 lines (142 loc) • 3.8 kB
JavaScript
var chalk = require('chalk');
var crypto = require('crypto');
var fs = require('fs-extra');
var moment = require('moment');
var packages = require('../../client/packages');
var path = require('path');
var basedir = path.resolve(__dirname + '/../../client/');
var devMode = process.env.KEYSTONE_DEV === 'true';
var devWriteBundles = process.env.KEYSTONE_WRITE_BUNDLES === 'true';
var devWriteDisc = process.env.KEYSTONE_WRITE_DISC === 'true';
function ts () {
return chalk.gray(moment().format('YYYY-MM-DD HH:MM:SS '));
}
function logInit (file) {
console.log(chalk.grey('Watching ') + chalk.underline(file) + chalk.grey(' for changes...'));
}
function logRebuild (file) {
console.log(ts() + chalk.green('rebuilt ' + chalk.underline(file)));
}
function logError (file, err) {
console.log(ts() + chalk.red('error building ' + chalk.underline(file) + ':') + '\n' + err.message);
}
module.exports = function (opts) {
var stream = opts.stream;
var expose = opts.expose;
var file = opts.file;
var hash = opts.hash;
var writeToDisk = opts.writeToDisk;
var b;
var building = false;
var queue = [];
var src;
var etag;
var logName = file.replace(/^\.\//, '');
var fileName = logName;
var outputFilename = path.resolve(path.join(__dirname, '../../bundles/js', hash + '-' + fileName));
function updateBundle (newSrc) {
src = newSrc;
etag = crypto.createHash('md5').update(src).digest('hex').slice(0, 6);
}
function writeBundle (buff) {
if (devWriteBundles || writeToDisk) {
fs.outputFile(outputFilename, buff, 'utf8', function (err) {
if (err) {
return logError(fileName, err);
}
});
}
if (devWriteDisc) {
var discFile = fileName.replace('.js', '.html');
require('disc').bundle(buff, function (err, html) {
if (err) {
logError(discFile, err);
} else {
fs.outputFile(path.resolve(path.join(__dirname, '../../bundles/disc', discFile)), html, 'utf8');
console.log(ts() + chalk.green('wrote disc for ' + chalk.underline(file)));
}
});
}
}
function build () {
if (building) return;
building = true;
var babelify = require('babelify');
var browserify = require('browserify');
var watchify = require('watchify');
var opts = { basedir: basedir };
if (devMode) {
logInit(logName);
opts.debug = true;
opts.cache = {};
opts.packageCache = {};
}
if (devWriteDisc) {
opts.fullPaths = true;
}
if (stream) {
b = browserify(opts);
b.require(stream, { expose: expose });
} else {
b = browserify(file, opts);
}
b.transform(babelify.configure({
presets: ['@babel/preset-env', '@babel/preset-react'],
}));
b.exclude('FieldTypes');
packages.forEach(function (i) {
b.exclude(i);
});
if (devMode) {
b = watchify(b, { poll: 500 });
}
b.bundle(function (err, buff) {
if (err) return logError(logName, err);
updateBundle(buff);
queue.forEach(function (reqres) {
send.apply(null, reqres);
});
writeBundle(buff);
});
b.on('update', function () {
b.bundle(function (err, buff) {
if (err) return logError(logName, err);
else logRebuild(logName);
updateBundle(buff);
writeBundle(buff);
});
});
}
function serve (req, res) {
if (src) {
return send(req, res);
}
fs.readFile(outputFilename, function (err, data) {
if (data) {
updateBundle(data);
if (devMode) {
build();
}
send(req, res);
} else {
queue.push([req, res]);
build();
}
});
}
function send (req, res) {
res.setHeader('Content-Type', 'application/javascript');
if (req.get && (etag === req.get('If-None-Match'))) {
res.status(304);
res.end();
} else {
res.set('ETag', etag);
res.set('Vary', 'Accept-Encoding');
res.send(src);
}
}
return {
serve: serve,
build: build,
};
};