varan
Version:
A webpack starter kit for offline-first bring-your-own-code apps with server side rendering
172 lines • 9.75 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("lodash");
const path_1 = __importDefault(require("path"));
const webpack_1 = __importDefault(require("webpack"));
const chalk_1 = __importDefault(require("chalk"));
const listr_1 = __importDefault(require("listr"));
const webpack_stats_plugin_1 = require("webpack-stats-plugin");
const fs_extra_1 = __importDefault(require("fs-extra"));
const filesize_1 = __importDefault(require("filesize"));
const emojis_1 = __importDefault(require("./emojis"));
const getBuildStatsFromManifest_1 = __importDefault(require("./getBuildStatsFromManifest"));
const getCompilerStats_1 = __importDefault(require("./getCompilerStats"));
const getConfigs_1 = __importDefault(require("./getConfigs"));
const BuildError_1 = __importDefault(require("./BuildError"));
const createServerConfig_1 = __importDefault(require("../webpack/createServerConfig"));
const createClientConfig_1 = __importDefault(require("../webpack/createClientConfig"));
// Init
const getOpts = (options) => lodash_1.defaults({}, options, {
verbose: true,
configs: [createServerConfig_1.default, createClientConfig_1.default],
warnAssetSize: 512 * 1024,
warnChunkSize: 1024 * 1024,
env: 'production',
appDir: process.cwd(),
inputFileSystem: undefined,
outputFileSystem: undefined,
});
// Exports
async function build(options) {
const opts = getOpts(options);
// Setup
process.env.BABEL_ENV = opts.env;
const configs = getConfigs_1.default(opts.configs, opts);
const multiCompiler = webpack_1.default(configs.map((c) => lodash_1.omit(c, ['devServer'])));
if (opts.inputFileSystem)
multiCompiler.inputFileSystem = opts.inputFileSystem;
if (opts.outputFileSystem)
multiCompiler.outputFileSystem = opts.outputFileSystem;
const taskOptions = {
showSubtasks: true,
renderer: opts.verbose ? 'default' : 'silent',
nonTTYRenderer: opts.verbose ? 'verbose' : 'silent',
};
const tasks = new listr_1.default([
{
title: 'Build',
task: () => new listr_1.default([
...multiCompiler.compilers.map((compiler, i) => ({
title: `Build ${path_1.default.resolve(typeof opts.configs[i] === 'string'
? opts.configs[i].toString()
: compiler.options.name || i.toString())}`,
task: () => new listr_1.default([
{
title: 'Prepare',
task: (ctx) => {
if (!ctx.stats)
ctx.stats = [];
ctx.stats[i] = {
errors: [],
warnings: [],
};
return `${chalk_1.default.green(emojis_1.default.success)} Preparations completed successfully`;
},
},
{
title: 'Measure previous build',
skip: () => opts.silent || compiler.options.target === 'node',
task: async (ctx) => {
const statsPlugin = compiler.options.plugins &&
compiler.options.plugins.find((p) => p instanceof webpack_stats_plugin_1.StatsWriterPlugin);
if (statsPlugin) {
try {
const searchPath = compiler.outputPath;
const manifestFile = path_1.default.resolve(searchPath, statsPlugin.opts.filename);
const manifestRaw = await fs_extra_1.default.readFile(manifestFile);
const manifest = JSON.parse(manifestRaw.toString());
ctx.stats[i].previousBuild = await getBuildStatsFromManifest_1.default(searchPath, manifest);
}
catch (err) {
// Empty
}
}
},
},
{
title: 'Build',
task: (ctx) => new Promise((resolve, reject) => {
compiler.run((err, stats) => {
if (err)
return reject(err);
const info = stats.toJson();
ctx.stats[i].errors = info.errors;
ctx.stats[i].warnings = info.warnings;
if (stats.hasErrors() || info.errors.length > 0) {
const buildError = new BuildError_1.default('Build failed with errors');
buildError.errors = ctx.stats[i].errors;
buildError.warnings = ctx.stats[i].warnings;
return reject(buildError);
}
// Send data
const config = compiler.options;
ctx.stats[i].build = {
config,
stats,
configFile: path_1.default.resolve(typeof opts.configs[i] === 'string'
? opts.configs[i].toString()
: config.name || i.toString()),
outputPath: (config.output && config.output.path && path_1.default.dirname(config.output.path)) || undefined,
};
return resolve(`${chalk_1.default.green(emojis_1.default.success)} Build completed successfully!`);
});
}),
},
{
title: 'Measure current build',
skip: () => opts.silent || compiler.options.target === 'node',
task: async (ctx) => {
const statsPlugin = compiler.options.plugins &&
compiler.options.plugins.find((p) => p instanceof webpack_stats_plugin_1.StatsWriterPlugin);
if (statsPlugin) {
try {
const searchPath = compiler.outputPath;
const manifestFile = path_1.default.resolve(searchPath, statsPlugin.opts.filename);
const manifestRaw = await fs_extra_1.default.readFile(manifestFile);
const manifest = JSON.parse(manifestRaw.toString());
ctx.stats[i].currentBuild = await getBuildStatsFromManifest_1.default(searchPath, manifest);
// Check for chunk size violations
if (ctx.stats[i].currentBuild &&
Object.values(ctx.stats[i].currentBuild.chunks).some((chunk) => chunk.size > opts.warnChunkSize)) {
ctx.stats[i].warnings.push(`one or more chunks exceeds the set ${chalk_1.default.cyan('opts.warnChunkSize')} limit of ${chalk_1.default.cyan(filesize_1.default(opts.warnChunkSize))}.`);
}
// Check for asset size violations
if (ctx.stats[i].currentBuild &&
Object.values(ctx.stats[i].currentBuild.assets).some((asset) => asset.size > opts.warnAssetSize)) {
ctx.stats[i].warnings.push(`one or more assets exceeds the set ${chalk_1.default.cyan('opts.warnAssetSize')} limit of ${chalk_1.default.cyan(filesize_1.default(opts.warnAssetSize))}`);
}
}
catch (err) {
// Empty
}
}
},
},
]),
})),
], {
showSubtasks: true,
concurrent: true,
}),
},
{
title: 'Calculate build stats',
task: (ctx) => {
const stats = Object.values(ctx.stats)
.filter((s) => s.build && s.build.stats)
.map((s) => s.build.stats);
ctx.totals = getCompilerStats_1.default(stats);
return `${chalk_1.default.green(emojis_1.default.success)} Build statistics calculated successfully`;
},
},
], taskOptions);
/**
* Build project
*/
return { result: await tasks.run(), options: opts };
}
exports.default = build;
//# sourceMappingURL=build.js.map