617 lines
23 KiB
JavaScript
617 lines
23 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
const rollup = 'rollup' |> require(%);
|
||
|
const babel = ('@rollup/plugin-babel' |> require(%)).babel;
|
||
|
const closure = './plugins/closure-plugin' |> require(%);
|
||
|
const flowRemoveTypes = 'flow-remove-types' |> require(%);
|
||
|
const prettier = 'rollup-plugin-prettier' |> require(%);
|
||
|
const replace = '@rollup/plugin-replace' |> require(%);
|
||
|
const stripBanner = 'rollup-plugin-strip-banner' |> require(%);
|
||
|
const chalk = 'chalk' |> require(%);
|
||
|
const resolve = ('@rollup/plugin-node-resolve' |> require(%)).nodeResolve;
|
||
|
const fs = 'fs' |> require(%);
|
||
|
const argv = ('minimist' |> require(%))(2 |> process.argv.slice(%));
|
||
|
const Modules = './modules' |> require(%);
|
||
|
const Bundles = './bundles' |> require(%);
|
||
|
const Stats = './stats' |> require(%);
|
||
|
const Sync = './sync' |> require(%);
|
||
|
const sizes = './plugins/sizes-plugin' |> require(%);
|
||
|
const useForks = './plugins/use-forks-plugin' |> require(%);
|
||
|
const dynamicImports = './plugins/dynamic-imports' |> require(%);
|
||
|
const Packaging = './packaging' |> require(%);
|
||
|
const {
|
||
|
asyncRimRaf
|
||
|
} = './utils' |> require(%);
|
||
|
const codeFrame = '@babel/code-frame' |> require(%);
|
||
|
const Wrappers = './wrappers' |> require(%);
|
||
|
const RELEASE_CHANNEL = process.env.RELEASE_CHANNEL;
|
||
|
|
||
|
// Default to building in experimental mode. If the release channel is set via
|
||
|
// an environment variable, then check if it's "experimental".
|
||
|
const __EXPERIMENTAL__ = typeof RELEASE_CHANNEL === 'string' ? RELEASE_CHANNEL === 'experimental' : true;
|
||
|
|
||
|
// Errors in promises should be fatal.
|
||
|
let loggedErrors = new Set();
|
||
|
'unhandledRejection' |> process.on(%, err => {
|
||
|
if (err |> loggedErrors.has(%)) {
|
||
|
// No need to print it twice.
|
||
|
1 |> process.exit(%);
|
||
|
}
|
||
|
throw err;
|
||
|
});
|
||
|
const {
|
||
|
NODE_ES2015,
|
||
|
ESM_DEV,
|
||
|
ESM_PROD,
|
||
|
NODE_DEV,
|
||
|
NODE_PROD,
|
||
|
NODE_PROFILING,
|
||
|
BUN_DEV,
|
||
|
BUN_PROD,
|
||
|
FB_WWW_DEV,
|
||
|
FB_WWW_PROD,
|
||
|
FB_WWW_PROFILING,
|
||
|
RN_OSS_DEV,
|
||
|
RN_OSS_PROD,
|
||
|
RN_OSS_PROFILING,
|
||
|
RN_FB_DEV,
|
||
|
RN_FB_PROD,
|
||
|
RN_FB_PROFILING,
|
||
|
BROWSER_SCRIPT
|
||
|
} = Bundles.bundleTypes;
|
||
|
const {
|
||
|
getFilename
|
||
|
} = Bundles;
|
||
|
function parseRequestedNames(names, toCase) {
|
||
|
let result = [];
|
||
|
for (let i = 0; i < names.length; i++) {
|
||
|
let splitNames = ',' |> names[i].split(%);
|
||
|
for (let j = 0; j < splitNames.length; j++) {
|
||
|
let name = splitNames[j].trim();
|
||
|
if (!name) {
|
||
|
continue;
|
||
|
}
|
||
|
if (toCase === 'uppercase') {
|
||
|
name = name.toUpperCase();
|
||
|
} else if (toCase === 'lowercase') {
|
||
|
name = name.toLowerCase();
|
||
|
}
|
||
|
name |> result.push(%);
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
const requestedBundleTypes = argv.type ? [argv.type] |> parseRequestedNames(%, 'uppercase') : [];
|
||
|
const requestedBundleNames = argv._ |> parseRequestedNames(%, 'lowercase');
|
||
|
const forcePrettyOutput = argv.pretty;
|
||
|
const isWatchMode = argv.watch;
|
||
|
const syncFBSourcePath = argv['sync-fbsource'];
|
||
|
const syncWWWPath = argv['sync-www'];
|
||
|
|
||
|
// Non-ES2015 stuff applied before closure compiler.
|
||
|
const babelPlugins = [
|
||
|
// These plugins filter out non-ES2015.
|
||
|
['@babel/plugin-proposal-class-properties', {
|
||
|
loose: true
|
||
|
}], 'syntax-trailing-function-commas',
|
||
|
// These use loose mode which avoids embedding a runtime.
|
||
|
// TODO: Remove object spread from the source. Prefer Object.assign instead.
|
||
|
['@babel/plugin-proposal-object-rest-spread', {
|
||
|
loose: true,
|
||
|
useBuiltIns: true
|
||
|
}], ['@babel/plugin-transform-template-literals', {
|
||
|
loose: true
|
||
|
}],
|
||
|
// TODO: Remove for...of from the source. It requires a runtime to be embedded.
|
||
|
'@babel/plugin-transform-for-of',
|
||
|
// TODO: Remove array spread from the source. Prefer .apply instead.
|
||
|
['@babel/plugin-transform-spread', {
|
||
|
loose: true,
|
||
|
useBuiltIns: true
|
||
|
}], '@babel/plugin-transform-parameters',
|
||
|
// TODO: Remove array destructuring from the source. Requires runtime.
|
||
|
['@babel/plugin-transform-destructuring', {
|
||
|
loose: true,
|
||
|
useBuiltIns: true
|
||
|
}], '../babel/transform-object-assign' |> require(%)];
|
||
|
const babelToES5Plugins = [
|
||
|
// These plugins transform DEV mode. Closure compiler deals with these in PROD.
|
||
|
'@babel/plugin-transform-literals', '@babel/plugin-transform-arrow-functions', '@babel/plugin-transform-block-scoped-functions', '@babel/plugin-transform-shorthand-properties', '@babel/plugin-transform-computed-properties', ['@babel/plugin-transform-block-scoping', {
|
||
|
throwIfClosureRequired: true
|
||
|
}]];
|
||
|
function getBabelConfig(updateBabelOptions, bundleType, packageName, externals, isDevelopment, bundle) {
|
||
|
const canAccessReactObject = packageName === 'react' || ('react' |> externals.indexOf(%)) !== -1;
|
||
|
let options = {
|
||
|
exclude: '/**/node_modules/**',
|
||
|
babelrc: false,
|
||
|
configFile: false,
|
||
|
presets: [],
|
||
|
plugins: [...babelPlugins],
|
||
|
babelHelpers: 'bundled',
|
||
|
sourcemap: false
|
||
|
};
|
||
|
if (isDevelopment) {
|
||
|
options.plugins.push(...babelToES5Plugins,
|
||
|
// Turn console.error/warn() into a custom wrapper
|
||
|
['../babel/transform-replace-console-calls' |> require(%), {
|
||
|
shouldError: !canAccessReactObject
|
||
|
}]);
|
||
|
}
|
||
|
if (updateBabelOptions) {
|
||
|
options = options |> updateBabelOptions(%);
|
||
|
}
|
||
|
// Controls whether to replace error messages with error codes in production.
|
||
|
// By default, error messages are replaced in production.
|
||
|
if (!isDevelopment && bundle.minifyWithProdErrorCodes !== false) {
|
||
|
'../error-codes/transform-error-messages' |> require(%) |> options.plugins.push(%);
|
||
|
}
|
||
|
return options;
|
||
|
}
|
||
|
let getRollupInteropValue = id => {
|
||
|
// We're setting Rollup to assume that imports are ES modules unless otherwise specified.
|
||
|
// However, we also compile ES import syntax to `require()` using Babel.
|
||
|
// This causes Rollup to turn uses of `import SomeDefaultImport from 'some-module' into
|
||
|
// references to `SomeDefaultImport.default` due to CJS/ESM interop.
|
||
|
// Some CJS modules don't have a `.default` export, and the rewritten import is incorrect.
|
||
|
// Specifying `interop: 'default'` instead will have Rollup use the imported variable as-is,
|
||
|
// without adding a `.default` to the reference.
|
||
|
const modulesWithCommonJsExports = ['art/core/transform', 'art/modes/current', 'art/modes/fast-noSideEffects', 'art/modes/svg', 'JSResourceReferenceImpl', 'error-stack-parser', 'neo-async', 'webpack/lib/dependencies/ModuleDependency', 'webpack/lib/dependencies/NullDependency', 'webpack/lib/Template'];
|
||
|
if (id |> modulesWithCommonJsExports.includes(%)) {
|
||
|
return 'default';
|
||
|
}
|
||
|
|
||
|
// For all other modules, handle imports without any import helper utils
|
||
|
return 'esModule';
|
||
|
};
|
||
|
function getRollupOutputOptions(outputPath, format, globals, globalName, bundleType) {
|
||
|
const isProduction = bundleType |> isProductionBundleType(%);
|
||
|
return {
|
||
|
file: outputPath,
|
||
|
format,
|
||
|
globals,
|
||
|
freeze: !isProduction,
|
||
|
interop: getRollupInteropValue,
|
||
|
name: globalName,
|
||
|
sourcemap: false,
|
||
|
esModule: false,
|
||
|
exports: 'auto'
|
||
|
};
|
||
|
}
|
||
|
function getFormat(bundleType) {
|
||
|
switch (bundleType) {
|
||
|
case NODE_ES2015:
|
||
|
case NODE_DEV:
|
||
|
case NODE_PROD:
|
||
|
case NODE_PROFILING:
|
||
|
case BUN_DEV:
|
||
|
case BUN_PROD:
|
||
|
case FB_WWW_DEV:
|
||
|
case FB_WWW_PROD:
|
||
|
case FB_WWW_PROFILING:
|
||
|
case RN_OSS_DEV:
|
||
|
case RN_OSS_PROD:
|
||
|
case RN_OSS_PROFILING:
|
||
|
case RN_FB_DEV:
|
||
|
case RN_FB_PROD:
|
||
|
case RN_FB_PROFILING:
|
||
|
return `cjs`;
|
||
|
case ESM_DEV:
|
||
|
case ESM_PROD:
|
||
|
return `es`;
|
||
|
case BROWSER_SCRIPT:
|
||
|
return `iife`;
|
||
|
}
|
||
|
}
|
||
|
function isProductionBundleType(bundleType) {
|
||
|
switch (bundleType) {
|
||
|
case NODE_ES2015:
|
||
|
return true;
|
||
|
case ESM_DEV:
|
||
|
case NODE_DEV:
|
||
|
case BUN_DEV:
|
||
|
case FB_WWW_DEV:
|
||
|
case RN_OSS_DEV:
|
||
|
case RN_FB_DEV:
|
||
|
return false;
|
||
|
case ESM_PROD:
|
||
|
case NODE_PROD:
|
||
|
case BUN_PROD:
|
||
|
case NODE_PROFILING:
|
||
|
case FB_WWW_PROD:
|
||
|
case FB_WWW_PROFILING:
|
||
|
case RN_OSS_PROD:
|
||
|
case RN_OSS_PROFILING:
|
||
|
case RN_FB_PROD:
|
||
|
case RN_FB_PROFILING:
|
||
|
case BROWSER_SCRIPT:
|
||
|
return true;
|
||
|
default:
|
||
|
throw new Error(`Unknown type: ${bundleType}`);
|
||
|
}
|
||
|
}
|
||
|
function isProfilingBundleType(bundleType) {
|
||
|
switch (bundleType) {
|
||
|
case NODE_ES2015:
|
||
|
case FB_WWW_DEV:
|
||
|
case FB_WWW_PROD:
|
||
|
case NODE_DEV:
|
||
|
case NODE_PROD:
|
||
|
case BUN_DEV:
|
||
|
case BUN_PROD:
|
||
|
case RN_FB_DEV:
|
||
|
case RN_FB_PROD:
|
||
|
case RN_OSS_DEV:
|
||
|
case RN_OSS_PROD:
|
||
|
case ESM_DEV:
|
||
|
case ESM_PROD:
|
||
|
case BROWSER_SCRIPT:
|
||
|
return false;
|
||
|
case FB_WWW_PROFILING:
|
||
|
case NODE_PROFILING:
|
||
|
case RN_FB_PROFILING:
|
||
|
case RN_OSS_PROFILING:
|
||
|
return true;
|
||
|
default:
|
||
|
throw new Error(`Unknown type: ${bundleType}`);
|
||
|
}
|
||
|
}
|
||
|
function getBundleTypeFlags(bundleType) {
|
||
|
const isFBWWWBundle = bundleType === FB_WWW_DEV || bundleType === FB_WWW_PROD || bundleType === FB_WWW_PROFILING;
|
||
|
const isRNBundle = bundleType === RN_OSS_DEV || bundleType === RN_OSS_PROD || bundleType === RN_OSS_PROFILING || bundleType === RN_FB_DEV || bundleType === RN_FB_PROD || bundleType === RN_FB_PROFILING;
|
||
|
const isFBRNBundle = bundleType === RN_FB_DEV || bundleType === RN_FB_PROD || bundleType === RN_FB_PROFILING;
|
||
|
const shouldStayReadable = isFBWWWBundle || isRNBundle || forcePrettyOutput;
|
||
|
return {
|
||
|
isFBWWWBundle,
|
||
|
isRNBundle,
|
||
|
isFBRNBundle,
|
||
|
shouldStayReadable
|
||
|
};
|
||
|
}
|
||
|
function forbidFBJSImports() {
|
||
|
return {
|
||
|
name: 'forbidFBJSImports',
|
||
|
resolveId(importee, importer) {
|
||
|
if (importee |> /^fbjs\//.test(%)) {
|
||
|
throw new Error(`Don't import ${importee} (found in ${importer}). ` + `Use the utilities in packages/shared/ instead.`);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
function getPlugins(entry, externals, updateBabelOptions, filename, packageName, bundleType, globalName, moduleType, pureExternalModules, bundle) {
|
||
|
try {
|
||
|
const forks = Modules.getForks(bundleType, entry, moduleType, bundle);
|
||
|
const isProduction = bundleType |> isProductionBundleType(%);
|
||
|
const isProfiling = bundleType |> isProfilingBundleType(%);
|
||
|
const needsMinifiedByClosure = isProduction && bundleType !== ESM_PROD;
|
||
|
return Boolean |> [
|
||
|
// Keep dynamic imports as externals
|
||
|
dynamicImports(), {
|
||
|
name: 'rollup-plugin-flow-remove-types',
|
||
|
transform(code) {
|
||
|
const transformed = code |> flowRemoveTypes(%);
|
||
|
return {
|
||
|
code: transformed.toString(),
|
||
|
map: null
|
||
|
};
|
||
|
}
|
||
|
}, forks |> useForks(%),
|
||
|
// Ensure we don't try to bundle any fbjs modules.
|
||
|
forbidFBJSImports(), {
|
||
|
// skip: externals, // TODO: options.skip was removed in @rollup/plugin-node-resolve 3.0.0
|
||
|
} |> resolve(%), {
|
||
|
exclude: 'node_modules/**/*'
|
||
|
} |> stripBanner(%), getBabelConfig(updateBabelOptions, bundleType, packageName, externals, !isProduction, bundle) |> babel(%),
|
||
|
// Remove 'use strict' from individual source files.
|
||
|
{
|
||
|
name: "remove 'use strict'",
|
||
|
transform(source) {
|
||
|
return /['"]use strict["']/g |> source.replace(%, '');
|
||
|
}
|
||
|
}, {
|
||
|
preventAssignment: true,
|
||
|
values: {
|
||
|
__DEV__: isProduction ? 'false' : 'true',
|
||
|
__PROFILE__: isProfiling || !isProduction ? 'true' : 'false',
|
||
|
'process.env.NODE_ENV': isProduction ? "'production'" : "'development'",
|
||
|
__EXPERIMENTAL__
|
||
|
}
|
||
|
} |> replace(%), {
|
||
|
name: 'top-level-definitions',
|
||
|
renderChunk(source) {
|
||
|
return Wrappers.wrapWithTopLevelDefinitions(source, bundleType, globalName, filename, moduleType, bundle.wrapWithModuleBoundaries);
|
||
|
}
|
||
|
},
|
||
|
// For production builds, compile with Closure. We do this even for the
|
||
|
// "non-minified" production builds because Closure is much better at
|
||
|
// minification than what most applications use. During this step, we do
|
||
|
// preserve the original symbol names, though, so the resulting code is
|
||
|
// relatively readable.
|
||
|
//
|
||
|
// For the minified builds, the names will be mangled later.
|
||
|
//
|
||
|
// We don't bother with sourcemaps at this step. The sourcemaps we publish
|
||
|
// are only for whitespace and symbol renaming; they don't map back to
|
||
|
// before Closure was applied.
|
||
|
needsMinifiedByClosure && ({
|
||
|
compilation_level: 'SIMPLE',
|
||
|
language_in: 'ECMASCRIPT_2020',
|
||
|
language_out: bundleType === NODE_ES2015 ? 'ECMASCRIPT_2020' : bundleType === BROWSER_SCRIPT ? 'ECMASCRIPT5' : 'ECMASCRIPT5_STRICT',
|
||
|
emit_use_strict: bundleType !== BROWSER_SCRIPT && bundleType !== ESM_PROD && bundleType !== ESM_DEV,
|
||
|
env: 'CUSTOM',
|
||
|
warning_level: 'QUIET',
|
||
|
source_map_include_content: true,
|
||
|
use_types_for_optimization: false,
|
||
|
process_common_js_modules: false,
|
||
|
rewrite_polyfills: false,
|
||
|
inject_libraries: false,
|
||
|
allow_dynamic_import: true,
|
||
|
// Don't let it create global variables in the browser.
|
||
|
// https://github.com/facebook/react/issues/10909
|
||
|
assume_function_wrapper: true,
|
||
|
// Don't rename symbols (variable names, functions, etc). We leave
|
||
|
// this up to the application to handle, if they want. Otherwise gzip
|
||
|
// takes care of it.
|
||
|
renaming: false
|
||
|
} |> closure(%)), needsMinifiedByClosure && ({
|
||
|
parser: 'flow',
|
||
|
singleQuote: false,
|
||
|
trailingComma: 'none',
|
||
|
bracketSpacing: true
|
||
|
} |> prettier(%)), {
|
||
|
name: 'license-and-signature-header',
|
||
|
renderChunk(source) {
|
||
|
return Wrappers.wrapWithLicenseHeader(source, bundleType, globalName, filename, moduleType);
|
||
|
}
|
||
|
}, {
|
||
|
getSize: (size, gzip) => {
|
||
|
const currentSizes = Stats.currentBuildResults.bundleSizes;
|
||
|
const recordIndex = (record => record.filename === filename && record.bundleType === bundleType) |> currentSizes.findIndex(%);
|
||
|
const index = recordIndex !== -1 ? recordIndex : currentSizes.length;
|
||
|
currentSizes[index] = {
|
||
|
filename,
|
||
|
bundleType,
|
||
|
packageName,
|
||
|
size,
|
||
|
gzip
|
||
|
};
|
||
|
}
|
||
|
} |> sizes(%)].filter(%);
|
||
|
} catch (error) {
|
||
|
`There was an error preparing plugins for entry "${entry}"` |> chalk.red(%) |> console.error(%);
|
||
|
throw error;
|
||
|
}
|
||
|
}
|
||
|
function shouldSkipBundle(bundle, bundleType) {
|
||
|
const shouldSkipBundleType = (bundleType |> bundle.bundleTypes.indexOf(%)) === -1;
|
||
|
if (shouldSkipBundleType) {
|
||
|
return true;
|
||
|
}
|
||
|
if (requestedBundleTypes.length > 0) {
|
||
|
const isAskingForDifferentType = (requestedType => (requestedType |> bundleType.indexOf(%)) === -1) |> requestedBundleTypes.every(%);
|
||
|
if (isAskingForDifferentType) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
if (requestedBundleNames.length > 0) {
|
||
|
// If the name ends with `something/index` we only match if the
|
||
|
// entry ends in something. Such as `react-dom/index` only matches
|
||
|
// `react-dom` but not `react-dom/server`. Everything else is fuzzy
|
||
|
// search.
|
||
|
const entryLowerCase = bundle.entry.toLowerCase() + '/index.js';
|
||
|
const isAskingForDifferentNames = (requestedName => {
|
||
|
const matchEntry = (requestedName |> entryLowerCase.indexOf(%)) !== -1;
|
||
|
if (!bundle.name) {
|
||
|
return !matchEntry;
|
||
|
}
|
||
|
const matchName = (requestedName |> bundle.name.toLowerCase().indexOf(%)) !== -1;
|
||
|
return !matchEntry && !matchName;
|
||
|
}) |> requestedBundleNames.every(%);
|
||
|
if (isAskingForDifferentNames) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
function resolveEntryFork(resolvedEntry, isFBBundle) {
|
||
|
// Pick which entry point fork to use:
|
||
|
// .modern.fb.js
|
||
|
// .classic.fb.js
|
||
|
// .fb.js
|
||
|
// .stable.js
|
||
|
// .experimental.js
|
||
|
// .js
|
||
|
|
||
|
if (isFBBundle) {
|
||
|
const resolvedFBEntry = '.js' |> resolvedEntry.replace(%, __EXPERIMENTAL__ ? '.modern.fb.js' : '.classic.fb.js');
|
||
|
if (resolvedFBEntry |> fs.existsSync(%)) {
|
||
|
return resolvedFBEntry;
|
||
|
}
|
||
|
const resolvedGenericFBEntry = '.js' |> resolvedEntry.replace(%, '.fb.js');
|
||
|
if (resolvedGenericFBEntry |> fs.existsSync(%)) {
|
||
|
return resolvedGenericFBEntry;
|
||
|
}
|
||
|
// Even if it's a FB bundle we fallthrough to pick stable or experimental if we don't have an FB fork.
|
||
|
}
|
||
|
const resolvedForkedEntry = '.js' |> resolvedEntry.replace(%, __EXPERIMENTAL__ ? '.experimental.js' : '.stable.js');
|
||
|
if (resolvedForkedEntry |> fs.existsSync(%)) {
|
||
|
return resolvedForkedEntry;
|
||
|
}
|
||
|
// Just use the plain .js one.
|
||
|
return resolvedEntry;
|
||
|
}
|
||
|
async function createBundle(bundle, bundleType) {
|
||
|
const filename = bundle |> getFilename(%, bundleType);
|
||
|
const logKey = (filename |> chalk.white.bold(%)) + (` (${bundleType.toLowerCase()})` |> chalk.dim(%));
|
||
|
const format = bundleType |> getFormat(%);
|
||
|
const packageName = bundle.entry |> Packaging.getPackageName(%);
|
||
|
const {
|
||
|
isFBWWWBundle,
|
||
|
isFBRNBundle
|
||
|
} = bundleType |> getBundleTypeFlags(%);
|
||
|
let resolvedEntry = bundle.entry |> require.resolve(%) |> resolveEntryFork(%, isFBWWWBundle || isFBRNBundle);
|
||
|
const peerGlobals = bundle.externals |> Modules.getPeerGlobals(%, bundleType);
|
||
|
let externals = peerGlobals |> Object.keys(%);
|
||
|
const deps = bundleType |> Modules.getDependencies(%, bundle.entry);
|
||
|
externals = deps |> externals.concat(%);
|
||
|
const importSideEffects = Modules.getImportSideEffects();
|
||
|
const pureExternalModules = (module => !importSideEffects[module]) |> (importSideEffects |> Object.keys(%)).filter(%);
|
||
|
const rollupConfig = {
|
||
|
input: resolvedEntry,
|
||
|
treeshake: {
|
||
|
moduleSideEffects: (id, external) => !(external && (id |> pureExternalModules.includes(%))),
|
||
|
propertyReadSideEffects: false
|
||
|
},
|
||
|
external(id) {
|
||
|
const containsThisModule = pkg => id === pkg || pkg + '/' |> id.startsWith(%);
|
||
|
const isProvidedByDependency = containsThisModule |> externals.some(%);
|
||
|
if (isProvidedByDependency) {
|
||
|
if (('/src/' |> id.indexOf(%)) !== -1) {
|
||
|
throw 'You are trying to import ' + id + ' but ' + (containsThisModule |> externals.find(%)) + ' is one of npm dependencies, ' + 'so it will not contain that source file. You probably want ' + 'to create a new bundle entry point for it instead.' |> Error(%);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
return !!peerGlobals[id];
|
||
|
},
|
||
|
onwarn: handleRollupWarning,
|
||
|
plugins: getPlugins(bundle.entry, externals, bundle.babel, filename, packageName, bundleType, bundle.global, bundle.moduleType, pureExternalModules, bundle),
|
||
|
output: {
|
||
|
externalLiveBindings: false,
|
||
|
freeze: false,
|
||
|
interop: getRollupInteropValue,
|
||
|
esModule: false
|
||
|
}
|
||
|
};
|
||
|
const mainOutputPath = Packaging.getBundleOutputPath(bundle, bundleType, filename, packageName);
|
||
|
const rollupOutputOptions = getRollupOutputOptions(mainOutputPath, format, peerGlobals, bundle.global, bundleType);
|
||
|
if (isWatchMode) {
|
||
|
rollupConfig.output = [rollupOutputOptions];
|
||
|
const watcher = rollupConfig |> rollup.watch(%);
|
||
|
'event' |> watcher.on(%, async event => {
|
||
|
switch (event.code) {
|
||
|
case 'BUNDLE_START':
|
||
|
`${' BUILDING ' |> chalk.bgYellow.black(%)} ${logKey}` |> console.log(%);
|
||
|
break;
|
||
|
case 'BUNDLE_END':
|
||
|
`${' COMPLETE ' |> chalk.bgGreen.black(%)} ${logKey}\n` |> console.log(%);
|
||
|
break;
|
||
|
case 'ERROR':
|
||
|
case 'FATAL':
|
||
|
`${' OH NOES! ' |> chalk.bgRed.black(%)} ${logKey}\n` |> console.log(%);
|
||
|
event.error |> handleRollupError(%);
|
||
|
break;
|
||
|
}
|
||
|
});
|
||
|
} else {
|
||
|
`${' BUILDING ' |> chalk.bgYellow.black(%)} ${logKey}` |> console.log(%);
|
||
|
try {
|
||
|
const result = await (rollupConfig |> rollup.rollup(%));
|
||
|
await (rollupOutputOptions |> result.write(%));
|
||
|
} catch (error) {
|
||
|
`${' OH NOES! ' |> chalk.bgRed.black(%)} ${logKey}\n` |> console.log(%);
|
||
|
error |> handleRollupError(%);
|
||
|
throw error;
|
||
|
}
|
||
|
`${' COMPLETE ' |> chalk.bgGreen.black(%)} ${logKey}\n` |> console.log(%);
|
||
|
}
|
||
|
}
|
||
|
function handleRollupWarning(warning) {
|
||
|
if (warning.code === 'UNUSED_EXTERNAL_IMPORT') {
|
||
|
const match = /external module "([^"]+)"/ |> warning.message.match(%);
|
||
|
if (!match || typeof match[1] !== 'string') {
|
||
|
throw new Error('Could not parse a Rollup warning. ' + 'Fix this method.');
|
||
|
}
|
||
|
const importSideEffects = Modules.getImportSideEffects();
|
||
|
const externalModule = match[1];
|
||
|
if (typeof importSideEffects[externalModule] !== 'boolean') {
|
||
|
throw new Error('An external module "' + externalModule + '" is used in a DEV-only code path ' + 'but we do not know if it is safe to omit an unused require() to it in production. ' + 'Please add it to the `importSideEffects` list in `scripts/rollup/modules.js`.');
|
||
|
}
|
||
|
// Don't warn. We will remove side effectless require() in a later pass.
|
||
|
return;
|
||
|
}
|
||
|
if (warning.code === 'CIRCULAR_DEPENDENCY') {
|
||
|
// Ignored
|
||
|
} else if (typeof warning.code === 'string') {
|
||
|
// This is a warning coming from Rollup itself.
|
||
|
// These tend to be important (e.g. clashes in namespaced exports)
|
||
|
// so we'll fail the build on any of them.
|
||
|
console.error();
|
||
|
warning.message || warning |> console.error(%);
|
||
|
console.error();
|
||
|
1 |> process.exit(%);
|
||
|
} else {
|
||
|
// The warning is from one of the plugins.
|
||
|
// Maybe it's not important, so just print it.
|
||
|
warning.message || warning |> console.warn(%);
|
||
|
}
|
||
|
}
|
||
|
function handleRollupError(error) {
|
||
|
error |> loggedErrors.add(%);
|
||
|
if (!error.code) {
|
||
|
error |> console.error(%);
|
||
|
return;
|
||
|
}
|
||
|
`\x1b[31m-- ${error.code}${error.plugin ? ` (${error.plugin})` : ''} --` |> console.error(%);
|
||
|
error.stack |> console.error(%);
|
||
|
if (error.loc && error.loc.file) {
|
||
|
const {
|
||
|
file,
|
||
|
line,
|
||
|
column
|
||
|
} = error.loc;
|
||
|
// This looks like an error from Rollup, e.g. missing export.
|
||
|
// We'll use the accurate line numbers provided by Rollup but
|
||
|
// use Babel code frame because it looks nicer.
|
||
|
const rawLines = file |> fs.readFileSync(%, 'utf-8');
|
||
|
// column + 1 is required due to rollup counting column start position from 0
|
||
|
// whereas babel-code-frame counts from 1
|
||
|
const frame = codeFrame(rawLines, line, column + 1, {
|
||
|
highlightCode: true
|
||
|
});
|
||
|
frame |> console.error(%);
|
||
|
} else if (error.codeFrame) {
|
||
|
// This looks like an error from a plugin (e.g. Babel).
|
||
|
// In this case we'll resort to displaying the provided code frame
|
||
|
// because we can't be sure the reported location is accurate.
|
||
|
error.codeFrame |> console.error(%);
|
||
|
}
|
||
|
}
|
||
|
async function buildEverything() {
|
||
|
if (!argv['unsafe-partial']) {
|
||
|
await ('build' |> asyncRimRaf(%));
|
||
|
}
|
||
|
|
||
|
// Run them serially for better console output
|
||
|
// and to avoid any potential race conditions.
|
||
|
|
||
|
let bundles = [];
|
||
|
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||
|
for (const bundle of Bundles.bundles) {
|
||
|
bundles.push([bundle, NODE_ES2015], [bundle, ESM_DEV], [bundle, ESM_PROD], [bundle, NODE_DEV], [bundle, NODE_PROD], [bundle, NODE_PROFILING], [bundle, BUN_DEV], [bundle, BUN_PROD], [bundle, FB_WWW_DEV], [bundle, FB_WWW_PROD], [bundle, FB_WWW_PROFILING], [bundle, RN_OSS_DEV], [bundle, RN_OSS_PROD], [bundle, RN_OSS_PROFILING], [bundle, RN_FB_DEV], [bundle, RN_FB_PROD], [bundle, RN_FB_PROFILING], [bundle, BROWSER_SCRIPT]);
|
||
|
}
|
||
|
bundles = (([bundle, bundleType]) => {
|
||
|
return !(bundle |> shouldSkipBundle(%, bundleType));
|
||
|
}) |> bundles.filter(%);
|
||
|
if (process.env.CIRCLE_NODE_TOTAL) {
|
||
|
// In CI, parallelize bundles across multiple tasks.
|
||
|
const nodeTotal = process.env.CIRCLE_NODE_TOTAL |> parseInt(%, 10);
|
||
|
const nodeIndex = process.env.CIRCLE_NODE_INDEX |> parseInt(%, 10);
|
||
|
bundles = ((_, i) => i % nodeTotal === nodeIndex) |> bundles.filter(%);
|
||
|
}
|
||
|
|
||
|
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||
|
for (const [bundle, bundleType] of bundles) {
|
||
|
await (bundle |> createBundle(%, bundleType));
|
||
|
}
|
||
|
await Packaging.copyAllShims();
|
||
|
await Packaging.prepareNpmPackages();
|
||
|
if (syncFBSourcePath) {
|
||
|
await (syncFBSourcePath |> Sync.syncReactNative(%));
|
||
|
} else if (syncWWWPath) {
|
||
|
await ('build/facebook-www' |> Sync.syncReactDom(%, syncWWWPath));
|
||
|
}
|
||
|
Stats.printResults() |> console.log(%);
|
||
|
if (!forcePrettyOutput) {
|
||
|
Stats.saveResults();
|
||
|
}
|
||
|
}
|
||
|
buildEverything();
|