From 8a67378f979a2be55b63581ed390e50e394860fa Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Tue, 29 May 2018 14:59:57 -0300 Subject: [PATCH] Nicer logging on build script (#4590) --- scripts/build/build.js | 227 +++++------------------- scripts/build/bundler.js | 183 +++++++++++++++++++ scripts/build/{bundles.js => config.js} | 8 +- 3 files changed, 230 insertions(+), 188 deletions(-) create mode 100644 scripts/build/bundler.js rename scripts/build/{bundles.js => config.js} (96%) diff --git a/scripts/build/build.js b/scripts/build/build.js index 2577ffb1..1fa4f7da 100644 --- a/scripts/build/build.js +++ b/scripts/build/build.js @@ -1,198 +1,54 @@ "use strict"; -const path = require("path"); -const { rollup } = require("rollup"); -const webpack = require("webpack"); -const resolve = require("rollup-plugin-node-resolve"); -const commonjs = require("rollup-plugin-commonjs"); -const nodeGlobals = require("rollup-plugin-node-globals"); -const json = require("rollup-plugin-json"); -const replace = require("rollup-plugin-replace"); -const uglify = require("rollup-plugin-uglify"); -const babel = require("rollup-plugin-babel"); -const nativeShims = require("./rollup-plugins/native-shims"); -const executable = require("./rollup-plugins/executable"); - -const Bundles = require("./bundles"); +const chalk = require("chalk"); +const stringWidth = require("string-width"); +const bundler = require("./bundler"); +const bundleConfigs = require("./config"); const util = require("./util"); -const EXTERNALS = [ - "assert", - "buffer", - "constants", - "crypto", - "events", - "fs", - "module", - "os", - "path", - "stream", - "url", - "util", - "readline", - - // See comment in jest.config.js - "graceful-fs" -]; - -function getBabelConfig(bundle) { - const config = { - babelrc: false, - plugins: [] - }; - if (bundle.type === "core") { - config.plugins.push( - require.resolve("./babel-plugins/transform-custom-require") - ); +// Errors in promises should be fatal. +const loggedErrors = new Set(); +process.on("unhandledRejection", err => { + if (loggedErrors.has(err)) { + // No need to print it twice. + process.exit(1); } - const targets = { node: 4 }; - if (bundle.target === "universal") { - // From https://jamie.build/last-2-versions - targets.browsers = [">0.25%", "not ie 11", "not op_mini all"]; + throw err; +}); + +const OK = chalk.reset.inverse.bold.green(" DONE "); +const FAIL = chalk.reset.inverse.bold.red(" FAIL "); + +function fitTerminal(input) { + const columns = process.stdout.columns || 80; + const WIDTH = columns - stringWidth(OK) + 1; + if (input.length < WIDTH) { + input += Array(WIDTH - input.length).join(chalk.dim(".")); } - config.presets = [ - [require.resolve("@babel/preset-env"), { targets, modules: false }] - ]; - return config; + return input; } -function getRollupConfig(bundle) { - const relative = fp => `./${path.basename(fp).replace(/\.js$/, "")}`; - const paths = (bundle.external || []).reduce( - (paths, filepath) => - Object.assign(paths, { [filepath]: relative(filepath) }), - { "graceful-fs": "fs" } - ); +async function createBundle(bundleConfig) { + const { output } = bundleConfig; + process.stdout.write(fitTerminal(output)); - const config = { - entry: bundle.input, - paths, - - onwarn(warning) { - if ( - // We use `eval("require")` to enable dynamic requires in the - // custom parser API - warning.code === "EVAL" || - (warning.code === "CIRCULAR_DEPENDENCY" && - warning.importer.startsWith("node_modules")) - ) { - return; - } - - // web bundle can't have external requires - if ( - warning.code === "UNRESOLVED_IMPORT" && - bundle.target === "universal" - ) { - throw new Error( - `Unresolved dependency in universal bundle: ${warning.source}` - ); - } - - console.warn(warning); - } - }; - - const replaceStrings = { - "proces.env.NODE_ENV": JSON.stringify("production") - }; - if (bundle.target === "universal") { - // We can't reference `process` in UMD bundles and this is - // an undocumented "feature" - replaceStrings["process.env.PRETTIER_DEBUG"] = "global.PRETTIER_DEBUG"; - } - Object.assign(replaceStrings, bundle.replace); - - const babelConfig = getBabelConfig(bundle); - - config.plugins = [ - replace(replaceStrings), - executable(), - json(), - bundle.target === "universal" && - nativeShims(path.resolve(__dirname, "shims")), - resolve({ - extensions: [".js", ".json"], - preferBuiltins: bundle.target === "node" - }), - commonjs(bundle.commonjs || {}), - bundle.target === "universal" && nodeGlobals(), - babelConfig && babel(babelConfig), - bundle.type === "plugin" && uglify() - ].filter(Boolean); - - if (bundle.target === "node") { - config.external = EXTERNALS.concat(bundle.external); + try { + await bundler(bundleConfig, output); + } catch (error) { + process.stdout.write(`${FAIL}\n\n`); + handleError(error); } - return config; + process.stdout.write(`${OK}\n`); } -function getRollupOutputOptions(bundle) { - const options = { - dest: `dist/${Bundles.getFileOutput(bundle)}`, - useStrict: typeof bundle.strict === "undefined" ? true : bundle.strict - }; - if (bundle.target === "node") { - options.format = "cjs"; - } else if (bundle.target === "universal") { - options.format = "umd"; - options.moduleName = - bundle.type === "plugin" ? `prettierPlugins.${bundle.name}` : bundle.name; - } - return options; +function handleError(error) { + loggedErrors.add(error); + console.error(error); + throw error; } -function getWebpackConfig(bundle) { - if (bundle.target === "node") { - throw new Error("Unsupported webpack bundle for node"); - } - - const root = path.resolve(__dirname, "..", ".."); - return { - entry: path.resolve(root, bundle.input), - output: { - path: path.resolve(root, "dist"), - filename: Bundles.getFileOutput(bundle), - library: - bundle.type === "plugin" - ? ["prettierPlugins", bundle.name] - : bundle.name, - libraryTarget: "umd" - } - }; -} - -function asyncWebpack(config) { - return new Promise((resolve, reject) => { - webpack(config, err => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); -} - -async function createBundle(bundle) { - const output = Bundles.getFileOutput(bundle); - console.log(`BUILDING ${output}`); - - if (bundle.bundler === "webpack") { - await asyncWebpack(getWebpackConfig(bundle)); - } else { - try { - const result = await rollup(getRollupConfig(bundle)); - await result.write(getRollupOutputOptions(bundle)); - } catch (error) { - console.log(error); - throw error; - } - } -} - -async function createPackageJson() { +async function preparePackage() { const pkg = await util.readJson("package.json"); pkg.bin = "./bin-prettier.js"; pkg.engines.node = ">=4"; @@ -203,18 +59,19 @@ async function createPackageJson() { "node -e \"assert.equal(require('.').version, require('..').version)\"" }; await util.writeJson("dist/package.json", pkg); + + await util.copyFile("./README.md", "./dist/README.md"); } async function run() { await util.asyncRimRaf("dist"); - for (const bundle of Bundles.bundles) { - await createBundle(bundle, "node"); + console.log(chalk.inverse(" Building packages ")); + for (const bundleConfig of bundleConfigs) { + await createBundle(bundleConfig); } - await createPackageJson(); - - await util.copyFile("./README.md", "./dist/README.md"); + await preparePackage(); } run(); diff --git a/scripts/build/bundler.js b/scripts/build/bundler.js new file mode 100644 index 00000000..4edba610 --- /dev/null +++ b/scripts/build/bundler.js @@ -0,0 +1,183 @@ +"use strict"; + +const path = require("path"); +const { rollup } = require("rollup"); +const webpack = require("webpack"); +const resolve = require("rollup-plugin-node-resolve"); +const commonjs = require("rollup-plugin-commonjs"); +const nodeGlobals = require("rollup-plugin-node-globals"); +const json = require("rollup-plugin-json"); +const replace = require("rollup-plugin-replace"); +const uglify = require("rollup-plugin-uglify"); +const babel = require("rollup-plugin-babel"); +const nativeShims = require("./rollup-plugins/native-shims"); +const executable = require("./rollup-plugins/executable"); + +const EXTERNALS = [ + "assert", + "buffer", + "constants", + "crypto", + "events", + "fs", + "module", + "os", + "path", + "stream", + "url", + "util", + "readline", + + // See comment in jest.config.js + "graceful-fs" +]; + +function getBabelConfig(bundle) { + const config = { + babelrc: false, + plugins: [], + compact: bundle.type === "plugin" ? false : "auto" + }; + if (bundle.type === "core") { + config.plugins.push( + require.resolve("./babel-plugins/transform-custom-require") + ); + } + const targets = { node: 4 }; + if (bundle.target === "universal") { + // From https://jamie.build/last-2-versions + targets.browsers = [">0.25%", "not ie 11", "not op_mini all"]; + } + config.presets = [ + [require.resolve("@babel/preset-env"), { targets, modules: false }] + ]; + return config; +} + +function getRollupConfig(bundle) { + const relative = fp => `./${path.basename(fp).replace(/\.js$/, "")}`; + const paths = (bundle.external || []).reduce( + (paths, filepath) => + Object.assign(paths, { [filepath]: relative(filepath) }), + { "graceful-fs": "fs" } + ); + + const config = { + entry: bundle.input, + paths, + + onwarn(warning) { + if ( + // We use `eval("require")` to enable dynamic requires in the + // custom parser API + warning.code === "EVAL" || + (warning.code === "CIRCULAR_DEPENDENCY" && + warning.importer.startsWith("node_modules")) + ) { + return; + } + + // web bundle can't have external requires + if ( + warning.code === "UNRESOLVED_IMPORT" && + bundle.target === "universal" + ) { + throw new Error( + `Unresolved dependency in universal bundle: ${warning.source}` + ); + } + + console.warn(warning); + } + }; + + const replaceStrings = { + "proces.env.NODE_ENV": JSON.stringify("production") + }; + if (bundle.target === "universal") { + // We can't reference `process` in UMD bundles and this is + // an undocumented "feature" + replaceStrings["process.env.PRETTIER_DEBUG"] = "global.PRETTIER_DEBUG"; + } + Object.assign(replaceStrings, bundle.replace); + + const babelConfig = getBabelConfig(bundle); + + config.plugins = [ + replace(replaceStrings), + executable(), + json(), + bundle.target === "universal" && + nativeShims(path.resolve(__dirname, "shims")), + resolve({ + extensions: [".js", ".json"], + preferBuiltins: bundle.target === "node" + }), + commonjs(bundle.commonjs || {}), + bundle.target === "universal" && nodeGlobals(), + babelConfig && babel(babelConfig), + bundle.type === "plugin" && uglify() + ].filter(Boolean); + + if (bundle.target === "node") { + config.external = EXTERNALS.concat(bundle.external); + } + + return config; +} + +function getRollupOutputOptions(bundle) { + const options = { + dest: `dist/${bundle.output}`, + useStrict: typeof bundle.strict === "undefined" ? true : bundle.strict + }; + if (bundle.target === "node") { + options.format = "cjs"; + } else if (bundle.target === "universal") { + options.format = "umd"; + options.moduleName = + bundle.type === "plugin" ? `prettierPlugins.${bundle.name}` : bundle.name; + } + return options; +} + +function getWebpackConfig(bundle) { + if (bundle.target === "node") { + throw new Error("Unsupported webpack bundle for node"); + } + + const root = path.resolve(__dirname, "..", ".."); + return { + entry: path.resolve(root, bundle.input), + output: { + path: path.resolve(root, "dist"), + filename: bundle.output, + library: + bundle.type === "plugin" + ? ["prettierPlugins", bundle.name] + : bundle.name, + libraryTarget: "umd" + } + }; +} + +function runWebpack(config) { + return new Promise((resolve, reject) => { + webpack(config, err => { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); +} + +module.exports = async function createBundle(bundle) { + if (bundle.bundler === "webpack") { + await runWebpack(getWebpackConfig(bundle)); + } else { + const result = await rollup(getRollupConfig(bundle)); + await result.write(getRollupOutputOptions(bundle)); + } +}; diff --git a/scripts/build/bundles.js b/scripts/build/config.js similarity index 96% rename from scripts/build/bundles.js rename to scripts/build/config.js index 48aad8db..d730e53c 100644 --- a/scripts/build/bundles.js +++ b/scripts/build/config.js @@ -75,7 +75,7 @@ const parsers = [ }); /** @type {Bundle[]} */ -const bundles = [ +const coreBundles = [ { input: "index.js", type: "core", @@ -109,10 +109,12 @@ const bundles = [ "module.parent": "(module.parent || module)" } } -].concat(parsers); +]; function getFileOutput(bundle) { return bundle.output || path.basename(bundle.input); } -module.exports = { bundles, getFileOutput }; +module.exports = coreBundles + .concat(parsers) + .map(b => Object.assign(b, { output: getFileOutput(b) }));