@pega/custom-dx-components
Version:
Utility for building custom UI components
244 lines (207 loc) • 7.13 kB
JavaScript
import chalk from 'chalk';
import fs from 'fs-extra';
import webpack from 'webpack';
import FileSizeReporter from 'react-dev-utils/FileSizeReporter.js';
import printBuildError from 'react-dev-utils/printBuildError.js';
import { getUseWebPackPromotion, addDebugLog, emptyDirSync } from '../../../util.js';
import paths from './paths.js';
// Do this as the first thing so that any code reading it knows the right env.
let Env = 'production';
if (process.argv.includes('development')) {
Env = 'development';
}
if (process.argv.includes('source-map')) {
process.env.SOURCE_MAP = true;
}
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = Env;
process.env.NODE_ENV = Env;
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', err => {
console.log(err);
// process.exit(1);
});
const measureFileSizesBeforeBuild = FileSizeReporter.measureFileSizesBeforeBuild;
const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
// These sizes are pretty large. We'll warn for bundles exceeding them.
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
let compilationErrors = null;
// Create the build and print the deployment instructions.
function build(config, previousFileSizes, showStats = true) {
addDebugLog("bundle build", `config: ${JSON.stringify(config)}, \npreviousFileSizes: ${JSON.stringify(previousFileSizes)}, showStats: ${showStats}`, "");
if (showStats) {
console.log(`Creating a ${Env} build...`);
}
const compiler = webpack(config);
return new Promise((resolve, reject) => {
compiler.run((err, stats) => {
if (err != null && typeof (err) == "object") {
if (err.error != undefined) {
//store and print elsewhere
compilationErrors = err.error;
//console.log("err:" + err);
}
}
if (stats != null & typeof (stats) == "object") {
if (stats.errors != undefined) {
if (showStats) {
console.log("stats:" + stats);
}
}
else if (stats.compilation != undefined && stats.compilation.errors != undefined) {
//store and print elsewhere
compilationErrors = stats.compilation.errors;
if (showStats) {
console.log("stats:" + stats);
}
}
}
let messages;
if (err) {
if (!err.message) {
return reject(err);
}
let errMessage = err.message;
// Add additional information for postcss errors
if (Object.prototype.hasOwnProperty.call(err, 'postcssNode')) {
errMessage += `\nCompileError: Begins at CSS selector ${err.postcssNode.selector}`;
}
messages = {
errors: [errMessage],
warnings: []
};
} else {
messages = stats.toJson({ all: false, warnings: true, errors: true });
}
if (messages.errors.length) {
// Only keep the first error. Others are often indicative
// of the same problem, but confuse the reader with noise.
if (messages.errors.length > 1) {
messages.errors.length = 1;
}
return reject(new Error(messages.errors));
}
if (
process.env.CI &&
(typeof process.env.CI !== 'string' || process.env.CI.toLowerCase() !== 'false') &&
messages.warnings.length
) {
console.log(
chalk.yellow(
'\nTreating warnings as errors because process.env.CI = true.\n' +
'Most CI servers set it automatically.\n'
)
);
return reject(new Error(messages.warnings.join('\n\n')));
}
const resolveArgs = {
stats,
previousFileSizes,
warnings: messages.warnings
};
return resolve(resolveArgs);
});
});
}
export default async ({
inputFile,
outputFile,
componentKey,
externals,
globals,
sourceMap,
devBuild,
showStats
}) => {
const usePromoted = await getUseWebPackPromotion();
// used by promote and revert webPack commands, do not change
const configFactory = (
await import(`${usePromoted ? `../../../../../../../webpack.config.js` : `./webpack.config.js`}`)
).default;
// Generate configuration
const config = configFactory(Env, {
inputFile,
outputFile,
componentKey,
externals,
globals,
sourceMap,
devBuild
});
if (devBuild) {
Env = 'development';
}
return new Promise((resolve, reject) => {
measureFileSizesBeforeBuild(paths.appBuild)
.then(previousFileSizes => {
// Remove all content but keep the directory so that
// if you're in it, you don't end up in Trash
emptyDirSync(paths.appBuild);
// Start the webpack build
return build(config, previousFileSizes, showStats);
})
.then(
({ stats, previousFileSizes, warnings }) => {
if (showStats) {
if (warnings.length) {
//console.log(chalk.yellow('Compiled with warnings.\n'), warnings[0].message);
console.log(chalk.yellow('Compiled with warnings.\n'));
for (let warning in warnings) {
console.log(chalk.yellow("Warning.."), warnings[warning].message);
}
} else {
console.log(chalk.green('Compiled successfully.\n'));
}
console.log('File sizes after gzip:\n');
printFileSizesAfterBuild(
stats,
previousFileSizes,
paths.appBuild,
WARN_AFTER_BUNDLE_GZIP_SIZE,
WARN_AFTER_CHUNK_GZIP_SIZE
);
}
else {
}
resolve('done emitting');
},
err => {
reject();
const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true';
if (tscCompileOnError) {
console.log(
chalk.yellow(
'Compiled with the following type errors (you may want to check these before deploying your app):\n'
)
);
printBuildError(err);
}
else if (compilationErrors != null) {
if (compilationErrors.length == undefined) {
console.log(chalk.red("Error..."), compilationErrors.message);
}
else {
for (let error in compilationErrors) {
console.log(chalk.red("Error..."), compilationErrors[error].message);
}
}
// process.exit(1);
}
else {
console.log(chalk.red('Failed to compile.\n'));
printBuildError(JSON.stringify(err));
}
}
)
.catch(err => {
reject();
if (err && err.message) {
console.log(err.message);
}
// process.exit(1);
});
});
};