mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
In #26446 we started publishing non-minified versions of our production build artifacts, along with source maps, for easier debugging of React when running in production mode. The way it's currently set up is that these builds are generated *before* Closure compiler has run. Which means it's missing many of the optimizations that are in the final build, like dead code elimination. This PR changes the build process to run Closure on the non-minified production builds, too, by moving the sourcemap generation to later in the pipeline. The non-minified builds will still preserve the original symbol names, and we'll use Prettier to add back whitespace. This is the exact same approach we've been using for years to generate production builds for Meta. The idea is that the only difference between the minified and non- minified builds is whitespace and symbol mangling. The semantic structure of the program should be identical. To implement this, I disabled symbol mangling when running Closure compiler. Then, in a later step, the symbols are mangled by Terser. This is when the source maps are generated.
42 lines
1.1 KiB
JavaScript
42 lines
1.1 KiB
JavaScript
'use strict';
|
|
|
|
const ClosureCompiler = require('google-closure-compiler').compiler;
|
|
const {promisify} = require('util');
|
|
const fs = require('fs');
|
|
const tmp = require('tmp');
|
|
const writeFileAsync = promisify(fs.writeFile);
|
|
|
|
function compile(flags) {
|
|
return new Promise((resolve, reject) => {
|
|
const closureCompiler = new ClosureCompiler(flags);
|
|
closureCompiler.run(function (exitCode, stdOut, stdErr) {
|
|
if (!stdErr) {
|
|
resolve(stdOut);
|
|
} else {
|
|
reject(new Error(stdErr));
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
module.exports = function closure(flags = {}) {
|
|
return {
|
|
name: 'scripts/rollup/plugins/closure-plugin',
|
|
async renderChunk(code, chunk, options) {
|
|
const inputFile = tmp.fileSync();
|
|
|
|
// Tell Closure what JS source file to read, and optionally what sourcemap file to write
|
|
const finalFlags = {
|
|
...flags,
|
|
js: inputFile.name,
|
|
};
|
|
|
|
await writeFileAsync(inputFile.name, code, 'utf8');
|
|
const compiledCode = await compile(finalFlags);
|
|
|
|
inputFile.removeCallback();
|
|
return {code: compiledCode};
|
|
},
|
|
};
|
|
};
|