UNPKG

nwb

Version:

A toolkit for React, Preact & Inferno apps, React libraries and other npm modules for the web, with no configuration (until you need it)

184 lines (151 loc) 5.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createBanner = createBanner; exports.createExternals = createExternals; exports.logBuildResults = logBuildResults; exports.logErrorsAndWarnings = logErrorsAndWarnings; exports.logGzippedFileSizes = logGzippedFileSizes; var _path = _interopRequireDefault(require("path")); var _chalk = _interopRequireDefault(require("chalk")); var _figures = _interopRequireDefault(require("figures")); var _filesize = _interopRequireDefault(require("filesize")); var _gzipSize = require("gzip-size"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const FRIENDLY_SYNTAX_ERROR_LABEL = 'Syntax error:'; let s = n => n === 1 ? '' : 's'; /** * Create a banner comment for a UMD build file from package.json config. */ function createBanner(pkg) { let banner = `${pkg.name} v${pkg.version}`; if (pkg.homepage) { banner += ` - ${pkg.homepage}`; } if (pkg.license) { banner += `\n${pkg.license} Licensed`; } return banner; } /** * Create Webpack externals config from a module → global variable mapping. */ function createExternals(externals = {}) { return Object.keys(externals).reduce((webpackExternals, packageName) => { let globalName = externals[packageName]; webpackExternals[packageName] = { root: globalName, commonjs2: packageName, commonjs: packageName, amd: packageName }; return webpackExternals; }, {}); } function formatMessage(message) { return message // Make some common errors shorter: .replace( // Babel syntax error 'Module build failed: SyntaxError:', FRIENDLY_SYNTAX_ERROR_LABEL).replace( // Webpack file not found error /Module not found: Error: Cannot resolve 'file' or 'directory'/, 'Module not found:') // Webpack loader names obscure CSS filenames .replace(/^.*css-loader.*!/gm, ''); } function isLikelyASyntaxError(message) { return message.includes(FRIENDLY_SYNTAX_ERROR_LABEL); } function formatMessages(messages, type) { return messages.map(message => `${type} in ${formatMessage(message)}`); } function getFileDetails(stats) { let outputPath = stats.compilation.outputOptions.path; return Object.keys(stats.compilation.assets).filter(assetName => /\.(css|js)$/.test(assetName)).map(assetName => { let size = (0, _gzipSize.sync)(stats.compilation.assets[assetName].source()); return { dir: _path.default.dirname(_path.default.join(_path.default.relative(process.cwd(), outputPath), assetName)), name: _path.default.basename(assetName), size, sizeLabel: (0, _filesize.default)(size) }; }); } function logBuildResults(stats, spinner) { if (stats.hasErrors()) { if (spinner) { spinner.fail(); console.log(); } logErrorsAndWarnings(stats); } else if (stats.hasWarnings()) { if (spinner) { spinner.stopAndPersist({ symbol: _chalk.default.yellow(_figures.default.warning) }); console.log(); } logErrorsAndWarnings(stats); console.log(); logGzippedFileSizes(stats); } else { if (spinner) { spinner.succeed(); console.log(); } logGzippedFileSizes(stats); } } function logErrorsAndWarnings(stats) { // Show fewer error details let json = stats.toJson({}, true); let formattedErrors = formatMessages(json.errors, _chalk.default.bgRed.white(' ERROR ')); let formattedWarnings = formatMessages(json.warnings, _chalk.default.bgYellow.black(' WARNING ')); if (stats.hasErrors()) { let errors = formattedErrors.length; console.log(_chalk.default.red(`Failed to compile with ${errors} error${s(errors)}.`)); if (formattedErrors.some(isLikelyASyntaxError)) { // If there are any syntax errors, show just them. // This prevents a confusing ESLint parsing error preceding a much more // useful Babel syntax error. formattedErrors = formattedErrors.filter(isLikelyASyntaxError); } formattedErrors.forEach(message => { console.log(); console.log(message); }); return; } if (stats.hasWarnings()) { let warnings = formattedWarnings.length; console.log(_chalk.default.yellow(`Compiled with ${warnings} warning${s(warnings)}.`)); formattedWarnings.forEach(message => { console.log(); console.log(message); }); } } /** * Take any number of Webpack Stats objects and log the gzipped size of the JS * and CSS assets they contain, largest-first. */ function logGzippedFileSizes(...stats) { let files = stats.reduce((files, stats) => files.concat(getFileDetails(stats)), []).filter(({ name }) => !/^runtime\.[a-z\d]+\.js$/.test(name)); let longest = files.reduce((max, { dir, name }) => { let length = (dir + name).length; return length > max ? length : max; }, 0); let pad = (dir, name) => Array(longest - (dir + name).length + 1).join(' '); console.log(`File size${s(files.length)} after gzip:`); console.log(); files.sort((a, b) => b.size - a.size).forEach(({ dir, name, sizeLabel }) => { console.log(` ${_chalk.default.dim(`${dir}${_path.default.sep}`)}${_chalk.default.cyan(name)}` + ` ${pad(dir, name)}${_chalk.default.green(sizeLabel)}`); }); console.log(); }