@mapbox/batfish
Version:
The React-powered static-site generator you didn't know you wanted
133 lines (118 loc) • 4.08 kB
JavaScript
//
;
const _ = require('lodash');
const webpack = require('webpack');
const path = require('path');
const chalk = require('chalk');
const EventEmitter = require('events');
const webpackMerge = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const errorTypes = require('./error-types');
const wrapError = require('./wrap-error');
const constants = require('./constants');
const createWebpackConfigClient = require('./create-webpack-config-client');
const createWebpackStatsError = require('./create-webpack-stats-error');
const watchContext = require('./watch-context');
const serverInitMessage = require('./server-init-message');
const writeWebpackStats = require('./write-webpack-stats');
// Returns an EventEmitter that fires notification and error events.
function watchWebpack(
batfishConfig ,
server
) {
const emitter = new EventEmitter();
const emitError = (error ) => {
emitter.emit(constants.EVENT_ERROR, error);
};
const emitNotification = (message ) => {
emitter.emit(constants.EVENT_NOTIFICATION, message);
};
const htmlWebpackPluginOptions = {
template: path.join(__dirname, '../webpack/html-webpack-template.ejs'),
cssBasename: _.isEmpty(batfishConfig.stylesheets)
? ''
: constants.BATFISH_CSS_BASENAME
};
let lastHash;
let hasCompiled = false;
createWebpackConfigClient(batfishConfig, {
devServer: true
})
.then(clientConfig => {
// Create an HTML file to load the assets in the browser.
const config = webpackMerge(clientConfig, {
plugins: [new HtmlWebpackPlugin(htmlWebpackPluginOptions)]
});
let compiler;
try {
compiler = webpack(config);
} catch (compilerInitializationError) {
emitError(
wrapError(compilerInitializationError, errorTypes.WebpackFatalError)
);
return;
}
const onCompilation = (compilationError, stats) => {
// Don't do anything if the compilation is just repetition.
// There's often a series of many compilations with the same output.
if (stats.hash === lastHash) return;
lastHash = stats.hash;
if (!hasCompiled) {
hasCompiled = true;
emitNotification(chalk.green.bold('Go!'));
emitNotification(
serverInitMessage(server.browserSyncInstance, batfishConfig)
);
}
if (compilationError) {
emitError(
wrapError(compilationError, errorTypes.WebpackCompilationError)
);
return;
}
if (stats.hasErrors()) {
emitError(createWebpackStatsError(stats));
}
writeWebpackStats(batfishConfig.outputDirectory, stats).catch(
emitError
);
if (batfishConfig.verbose) {
emitNotification(
stats.toString({
chunks: false,
colors: true
})
);
}
emitNotification('Webpack finished compiling.');
server.reload();
};
compiler.watch(
{
ignored: [
/node_modules/,
// Ignore page files because they are watched by watchContext.
path.join(
batfishConfig.pagesDirectory,
`./**/*.${constants.PAGE_EXT_GLOB}`
),
// Ignore temporary files because they are only re-generated by
// watchContext, and we don't want to double-compile.
path.join(batfishConfig.temporaryDirectory, './**/*')
]
},
onCompilation
);
// Watch pages separately, so we can rewrite the context module, which
// will capture changes to front matter, page additions and deletions.
watchContext(batfishConfig, {
onError: emitError,
afterCompilation: () => {
compiler.run(onCompilation);
}
});
})
.catch(emitError);
return emitter;
}
module.exports = watchWebpack;