UNPKG

antwar

Version:

A static site engine built with React and Webpack

203 lines (175 loc) 5.3 kB
const _fs = require("fs"); const _os = require("os"); const _path = require("path"); const async = require("neo-async"); const rimraf = require("rimraf"); const webpack = require("webpack"); const workerFarm = require("worker-farm"); const workers = workerFarm(require.resolve("./worker")); const write = require("./write"); module.exports = function({ environment, configurations, configurationPaths }) { return new Promise(function(resolve, reject) { const output = configurations.antwar.output; if (!output) { return reject(new Error("Missing output directory")); } // TODO: Instead of running webpack once in the beginning, we should // check the path definition and derive section data. That is then // divided to worker processes that generate each page (and possible // interactive bundles). return runWebpack(require("../config/build")({ configurations })) .then(generateParameters(configurations.antwar, configurations.webpack)) .then(writePages(environment, configurations.antwar, configurationPaths)) .then(removeSiteBundle(output)) .then(resolve) .catch(reject); }); }; function runWebpack(config) { return new Promise((resolve, reject) => { webpack(config, (err, stats) => { if (err) { return reject(err); } if (stats.hasErrors()) { return reject(stats.toString("errors-only")); } return resolve(stats); }); }); } function generateParameters(antwarConfiguration, webpackConfiguration) { const publicPath = webpackConfiguration.output ? webpackConfiguration.output.publicPath : ""; return stats => new Promise(resolve => { const assets = stats.compilation.assets; const cssFiles = Object.keys(assets) .map(asset => { if (_path.extname(asset) === ".css") { return assets[asset].existsAt; } return null; }) .filter(a => a); const jsFiles = []; // Copy template configuration to webpack side so the build process picks it up const template = { cssFiles: [], jsFiles: [], ...antwarConfiguration.template, }; const cwd = process.cwd(); const site = require(_path.join( cwd, antwarConfiguration.output, "site.js" )); const parameters = { cwd, renderPage: site.renderPage, allPages: site.allPages, output: _path.join(cwd, antwarConfiguration.output), config: antwarConfiguration, cssFiles, jsFiles, templates: { page: { ...template, // XXX: sync operation file: _fs.readFileSync( (template && template.file) || _path.join(__dirname, "../../templates/page.ejs"), { encoding: "utf8", } ), cssFiles: cssFiles.map( cssFile => publicPath + "/" + _path.basename(cssFile) ), jsFiles, }, // TODO: expose to the user? interactive: { file: _fs.readFileSync( _path.join(__dirname, "../../templates/interactive.ejs"), { encoding: "utf8", } ), }, interactiveIndex: { file: _fs.readFileSync( _path.join(__dirname, "../../templates/interactive_index.ejs"), { encoding: "utf8", } ), }, }, }; resolve(parameters); }); } function writePages(environment, antwarConfiguration, configurationPaths) { return parameters => new Promise((resolve, reject) => { const config = parameters.config; const assets = config && config.assets ? config.assets : []; if (parameters.cssFiles) { parameters.cssFiles.forEach(cssFile => { assets.push({ from: cssFile, to: "./" + _path.basename(cssFile), }); }); } write.pages(parameters, environment, configurationPaths)((err, tasks) => { if (err) { return reject(err); } executeTasks( tasks, antwarConfiguration.maximumWorkers, antwarConfiguration.console.log ) .then(() => resolve(parameters)) .catch(reject); }); }); } function executeTasks(tasks, maximumWorkers, log) { return new Promise((resolve, reject) => { async.eachLimit( tasks, maximumWorkers || _os.cpus().length, (o, cb) => { log("Starting to write pages"); workers(o, err => { log("Finished writing pages"); cb(err); }); }, err => { workerFarm.end(workers); if (err) { return reject(err); } log("BUILD FINISHED!"); return resolve(); } ); }); } function removeSiteBundle(outputDirectory) { return parameters => new Promise((resolve, reject) => { rimraf(_path.join(process.cwd(), outputDirectory, "site.js"), err => { if (err) { return reject(err); } return resolve(parameters); }); }); }