Skip to content

Commit

Permalink
Unify the way we fork modules
Browse files Browse the repository at this point in the history
  • Loading branch information
gaearon committed Nov 30, 2017
1 parent d83916e commit 36b31bc
Show file tree
Hide file tree
Showing 11 changed files with 98 additions and 84 deletions.
3 changes: 0 additions & 3 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
<PROJECT_ROOT>/scripts/rollup/shims/facebook-www/.*
<PROJECT_ROOT>/scripts/rollup/shims/react-native/.*

# Note: intentionally *don't* ignore /scripts/rollup/shims/rollup/
# because it is part of the build and isn't external.

<PROJECT_ROOT>/.*/node_modules/y18n/.*
<PROJECT_ROOT>/node_modules/chrome-devtools-frontend/.*
<PROJECT_ROOT>/node_modules/devtools-timeline-model/.*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import invariant from 'fbjs/lib/invariant';

import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';
import typeof * as CSFeatureFlagsType from './ReactNativeCSFeatureFlags';
import typeof * as CSFeatureFlagsType from './ReactFeatureFlags.native-cs';

export const debugRenderPhaseSideEffects = false;
export const enableAsyncSubtreeAPI = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import invariant from 'fbjs/lib/invariant';

import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';
import typeof * as FeatureFlagsShimType from './ReactNativeFeatureFlags';
import typeof * as FeatureFlagsShimType from './ReactFeatureFlags.native';

// Re-export dynamic flags from the fbsource version.
export const {debugRenderPhaseSideEffects} = require('ReactFeatureFlags');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';
import typeof * as FeatureFlagsShimType from './ReactFeatureFlags-www';
import typeof * as FeatureFlagsShimType from './ReactFeatureFlags.www';

// Re-export dynamic flags from the www version.
export const {
Expand Down
File renamed without changes.
12 changes: 5 additions & 7 deletions scripts/rollup/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,10 @@ function getPlugins(
bundleType,
globalName,
moduleType,
modulesToStub,
featureFlags
modulesToStub
) {
const findAndRecordErrorCodes = extractErrorCodes(errorCodeOpts);
const shims = Modules.getShims(bundleType, entry, featureFlags);
const forks = Modules.getForks(bundleType, entry);
const isProduction = isProductionBundleType(bundleType);
const isInGlobalScope = bundleType === UMD_DEV || bundleType === UMD_PROD;
const isFBBundle = bundleType === FB_DEV || bundleType === FB_PROD;
Expand All @@ -236,8 +235,8 @@ function getPlugins(
return source;
},
},
// Shim some modules for www custom behavior and optimizations.
alias(shims),
// Shim any modules that need forking in this environment.
alias(forks),
// Use Node resolution mechanism.
resolvePlugin({
skip: externals,
Expand Down Expand Up @@ -384,8 +383,7 @@ async function createBundle(bundle, bundleType) {
bundleType,
bundle.global,
bundle.moduleType,
bundle.modulesToStub,
bundle.featureFlags
bundle.modulesToStub
),
// We can't use getters in www.
legacy: bundleType === FB_DEV || bundleType === FB_PROD,
Expand Down
2 changes: 0 additions & 2 deletions scripts/rollup/bundles.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ const bundles = [
'deepFreezeAndThrowOnMutationInDev',
'flattenStyle',
],
featureFlags: 'react-native-renderer/src/ReactNativeFeatureFlags',
},

/******* React Native RT *******/
Expand All @@ -156,7 +155,6 @@ const bundles = [
entry: 'react-cs-renderer',
global: 'ReactCSRenderer',
externals: ['CSStatefulComponent'],
featureFlags: 'react-cs-renderer/src/ReactNativeCSFeatureFlags',
},

/******* React Test Renderer *******/
Expand Down
151 changes: 86 additions & 65 deletions scripts/rollup/modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,73 @@ const UMD_PROD = bundleTypes.UMD_PROD;
const FB_DEV = bundleTypes.FB_DEV;
const FB_PROD = bundleTypes.FB_PROD;

// If you need to replace a file with another file for a specific environment,
// add it to this list with the logic for choosing the right replacement.
const forkedModules = Object.freeze({
// Optimization: for UMDs, use object-assign polyfill that is already a part
// of the React package instead of bundling it again.
'object-assign': (bundleType, entry) => {
if (bundleType !== UMD_DEV && bundleType !== UMD_PROD) {
// It's only relevant for UMD bundles since that's where the duplication
// happens. Other bundles just require('object-assign') anyway.
return null;
}
if (getDependencies(bundleType, entry).indexOf('react') === -1) {
// We can only apply the optimizations to bundle that depend on React
// because we read assign() from an object exposed on React internals.
return null;
}
// We can use the fork!
return 'shared/forks/object-assign.umd.js';
},

// We have a few forks for different environments.
'shared/ReactFeatureFlags': (bundleType, entry) => {
switch (entry) {
case 'react-native-renderer':
return 'shared/forks/ReactFeatureFlags.native.js';
case 'react-cs-renderer':
return 'shared/forks/ReactFeatureFlags.native-cs.js';
default:
switch (bundleType) {
case FB_DEV:
case FB_PROD:
return 'shared/forks/ReactFeatureFlags.www.js';
}
}
return null;
},

// This logic is forked on www to blacklist warnings.
'shared/lowPriorityWarning': (bundleType, entry) => {
switch (bundleType) {
case FB_DEV:
case FB_PROD:
return 'shared/forks/lowPriorityWarning.www.js';
default:
return null;
}
},

// In FB bundles, we preserve an inline require to ReactCurrentOwner.
// See the explanation in FB version of ReactCurrentOwner in www:
'react/src/ReactCurrentOwner': (bundleType, entry) => {
switch (bundleType) {
case FB_DEV:
case FB_PROD:
return 'react/src/forks/ReactCurrentOwner.www.js';
default:
return null;
}
},
});

// Bundles exporting globals that other modules rely on.
const knownGlobals = Object.freeze({
react: 'React',
'react-dom': 'ReactDOM',
});

// Redirect some modules to Haste forks in www.
// Assuming their names in www are the same, and also match
// imported names in corresponding ./shims/rollup/*-www.js shims.
const forkedFBModules = Object.freeze([
// At FB, we don't know them statically:
'shared/ReactFeatureFlags',
// This logic is also forked internally.
'shared/lowPriorityWarning',
// In FB bundles, we preserve an inline require to ReactCurrentOwner.
// See the explanation in FB version of ReactCurrentOwner in www:
'react/src/ReactCurrentOwner',
]);

// For any external that is used in a DEV-only condition, explicitly
// specify whether it has side effects during import or not. This lets
// us know whether we can safely omit them when they are unused.
Expand Down Expand Up @@ -62,72 +110,45 @@ function getDependencies(bundleType, entry) {
path.dirname(require.resolve(entry))
) + '/package.json');
// Both deps and peerDeps are assumed as accessible.
let deps = Array.from(
return Array.from(
new Set([
...Object.keys(packageJson.dependencies || {}),
...Object.keys(packageJson.peerDependencies || {}),
])
);
// In www, forked modules are also require-able.
if (bundleType === FB_DEV || bundleType === FB_PROD) {
deps = [...deps, ...forkedFBModules.map(name => path.basename(name))];
}
return deps;
}

function getImportSideEffects() {
return importSideEffects;
}

// Hijacks some modules for optimization and integration reasons.
function getShims(bundleType, entry, featureFlags) {
function getForks(bundleType, entry) {
const shims = {};
switch (bundleType) {
case UMD_DEV:
case UMD_PROD:
if (getDependencies(bundleType, entry).indexOf('react') !== -1) {
// Optimization: rely on object-assign polyfill that is already a part
// of the React package instead of bundling it again.
shims['object-assign'] = path.resolve(
__dirname + '/shims/rollup/assign-umd.js'
);
}
break;
case FB_DEV:
case FB_PROD:
// FB forks a few modules in www that are usually bundled.
// Instead of bundling them, they need to be kept as require()s in the
// final bundles so that they import www modules with the same names.
// Rollup doesn't make it very easy to rewrite and ignore such a require,
// so we resort to using a shim that re-exports the www module, and then
// treating shim's target destinations as external (see getDependencies).
forkedFBModules.forEach(srcPath => {
const fileName = path.parse(srcPath).name;
const shimPath = path.resolve(
__dirname + `/shims/rollup/${fileName}-www.js`
);
shims[srcPath] = shimPath;
// <hack>
// Unfortunately the above doesn't work for relative imports,
// and Rollup isn't smart enough to understand they refer to the same file.
// We should come up with a real fix for this, but for now this will do.
// FIXME: this is gross.
shims['./' + fileName] = shimPath;
shims['../' + fileName] = shimPath;
// We don't have deeper relative requires between source files.
// </hack>
});
break;
}
if (featureFlags) {
shims['shared/ReactFeatureFlags'] = require.resolve(featureFlags);
}
Object.keys(forkedModules).forEach(srcModule => {
const targetModule = forkedModules[srcModule](bundleType, entry);
if (targetModule === null) {
return;
}
const targetPath = require.resolve(targetModule);
shims[srcModule] = targetPath;
// <hack>
// Unfortunately the above doesn't work for relative imports,
// and Rollup isn't smart enough to understand they refer to the same file.
// We should come up with a real fix for this, but for now this will do.
// FIXME: this is gross.
const fileName = path.parse(srcModule).name;
shims['./' + fileName] = targetPath;
shims['../' + fileName] = targetPath;
// We don't have deeper relative requires between source files.
// </hack>
});
return shims;
}

function getImportSideEffects() {
return importSideEffects;
}

module.exports = {
getImportSideEffects,
getPeerGlobals,
getDependencies,
getShims,
getForks,
};
8 changes: 4 additions & 4 deletions scripts/rollup/results.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
"gzip": 3444
},
"react-dom.development.js (UMD_DEV)": {
"size": 568069,
"gzip": 132515
"size": 578564,
"gzip": 134721
},
"react-dom.production.min.js (UMD_PROD)": {
"size": 94498,
Expand All @@ -41,8 +41,8 @@
"gzip": 29787
},
"ReactDOM-dev.js (FB_DEV)": {
"size": 574798,
"gzip": 132028
"size": 585814,
"gzip": 134776
},
"ReactDOM-prod.js (FB_PROD)": {
"size": 272153,
Expand Down

0 comments on commit 36b31bc

Please sign in to comment.