react/scripts/rollup/modules.js
Dan Abramov d9c1dbd617 Use Yarn Workspaces (#11252)
* Enable Yarn workspaces for packages/*

* Move src/isomorphic/* into packages/react/src/*

* Create index.js stubs for all packages in packages/*

This makes the test pass again, but breaks the build because npm/ folders aren't used yet.
I'm not sure if we'll keep this structure--I'll just keep working and fix the build after it settles down.

* Put FB entry point for react-dom into packages/*

* Move src/renderers/testing/* into packages/react-test-renderer/src/*

Note that this is currently broken because Jest ignores node_modules,
and so Yarn linking makes Jest skip React source when transforming.

* Remove src/node_modules

It is now unnecessary. Some tests fail though.

* Add a hacky workaround for Jest/Workspaces issue

Jest sees node_modules and thinks it's third party code.

This is a hacky way to teach Jest to still transform anything in node_modules/react*
if it resolves outside of node_modules (such as to our packages/*) folder.

I'm not very happy with this and we should revisit.

* Add a fake react-native package

* Move src/renderers/art/* into packages/react-art/src/*

* Move src/renderers/noop/* into packages/react-noop-renderer/src/*

* Move src/renderers/dom/* into packages/react-dom/src/*

* Move src/renderers/shared/fiber/* into packages/react-reconciler/src/*

* Move DOM/reconciler tests I previously forgot to move

* Move src/renderers/native-*/* into packages/react-native-*/src/*

* Move shared code into packages/shared

It's not super clear how to organize this properly yet.

* Add back files that somehow got lost

* Fix the build

* Prettier

* Add missing license headers

* Fix an issue that caused mocks to get included into build

* Update other references to src/

* Re-run Prettier

* Fix lint

* Fix weird Flow violation

I didn't change this file but Flow started complaining.
Caleb said this annotation was unnecessarily using $Abstract though so I removed it.

* Update sizes

* Fix stats script

* Fix packaging fixtures

Use file: instead of NODE_PATH since NODE_PATH.
NODE_PATH trick only worked because we had no react/react-dom in root node_modules, but now we do.

file: dependency only works as I expect in Yarn, so I moved the packaging fixtures to use Yarn and committed lockfiles.
Verified that the page shows up.

* Fix art fixture

* Fix reconciler fixture

* Fix SSR fixture

* Rename native packages
2017-10-19 00:22:21 +01:00

337 lines
9.1 KiB
JavaScript

'use strict';
const resolve = require('path').resolve;
const basename = require('path').basename;
const sync = require('glob').sync;
const bundleTypes = require('./bundles').bundleTypes;
const moduleTypes = require('./bundles').moduleTypes;
const extractErrorCodes = require('../error-codes/extract-errors');
const exclude = [
'**/__benchmarks__/**/*.js',
'**/__tests__/**/*.js',
'**/__mocks__/**/*.js',
];
const UMD_DEV = bundleTypes.UMD_DEV;
const UMD_PROD = bundleTypes.UMD_PROD;
const NODE_DEV = bundleTypes.NODE_DEV;
const NODE_PROD = bundleTypes.NODE_PROD;
const FB_DEV = bundleTypes.FB_DEV;
const FB_PROD = bundleTypes.FB_PROD;
const RN_DEV = bundleTypes.RN_DEV;
const RN_PROD = bundleTypes.RN_PROD;
const ISOMORPHIC = moduleTypes.ISOMORPHIC;
const errorCodeOpts = {
errorMapFilePath: 'scripts/error-codes/codes.json',
};
// these are the FBJS modules that are used throughout our bundles
const fbjsModules = [
'fbjs/lib/warning',
'fbjs/lib/invariant',
'fbjs/lib/emptyFunction',
'fbjs/lib/emptyObject',
'fbjs/lib/hyphenateStyleName',
'fbjs/lib/getUnboundedScrollPosition',
'fbjs/lib/camelizeStyleName',
'fbjs/lib/containsNode',
'fbjs/lib/shallowEqual',
'fbjs/lib/getActiveElement',
'fbjs/lib/focusNode',
'fbjs/lib/EventListener',
'fbjs/lib/memoizeStringOnly',
'fbjs/lib/ExecutionEnvironment',
'fbjs/lib/createNodesFromMarkup',
'fbjs/lib/performanceNow',
];
const devOnlyFilesToStubOut = [
"'ReactDebugCurrentFrame'",
"'ReactComponentTreeHook'",
"'ReactPerf'",
"'ReactTestUtils'",
];
const legacyModules = [
'create-react-class',
'create-react-class/factory',
'prop-types',
'prop-types/checkPropTypes',
];
// this function builds up a very niave Haste-like moduleMap
// that works to create up an alias map for modules to link
// up to their actual disk location so Rollup can properly
// bundle them
function createModuleMap(paths, extractErrors, bundleType) {
const moduleMap = {};
paths.forEach(path => {
const files = sync(path, {ignore: exclude});
files.forEach(file => {
if (extractErrors) {
extractErrors(file);
}
const moduleName = basename(file, '.js');
moduleMap[moduleName] = resolve(file);
});
});
// if this is FB, we want to remove ReactCurrentOwner and lowPriorityWarning,
// so we can handle it with a different case
if (bundleType === FB_DEV || bundleType === FB_PROD) {
delete moduleMap.ReactCurrentOwner;
delete moduleMap.lowPriorityWarning;
}
return moduleMap;
}
function getNodeModules(bundleType, moduleType) {
// rather than adding the rollup node resolve plugin,
// we can instead deal with the only node module that is used
// for UMD bundles - object-assign
switch (bundleType) {
case UMD_DEV:
case UMD_PROD:
return {
// Bundle object-assign once in the isomorphic React, and then use
// that from the renderer UMD. Avoids bundling it in both UMDs.
'object-assign': moduleType === ISOMORPHIC
? resolve('./node_modules/object-assign/index.js')
: resolve('./scripts/rollup/shims/rollup/assign.js'),
// include the ART package modules directly by aliasing them from node_modules
'art/modes/current': resolve('./node_modules/art/modes/current.js'),
'art/modes/fast-noSideEffects': resolve(
'./node_modules/art/modes/fast-noSideEffects.js'
),
'art/core/transform': resolve('./node_modules/art/core/transform.js'),
};
case NODE_DEV:
case NODE_PROD:
case FB_DEV:
case FB_PROD:
case RN_DEV:
case RN_PROD:
return {};
}
}
function ignoreFBModules() {
return [
// At FB, we don't know them statically:
'ReactFeatureFlags',
// In FB bundles, we preserve an inline require to ReactCurrentOwner.
// See the explanation in FB version of ReactCurrentOwner in www:
'ReactCurrentOwner',
'lowPriorityWarning',
];
}
function ignoreReactNativeModules() {
return [
// This imports NativeMethodsMixin, causing a circular dependency.
'View',
];
}
function getExternalModules(externals, bundleType, moduleType) {
// external modules tell Rollup that we should not attempt
// to bundle these modules and instead treat them as
// external dependencies to the bundle. so for CJS bundles
// this means having a require("name-of-external-module") at
// the top of the bundle. for UMD bundles this means having
// both a require and a global check for them
let externalModules = externals.slice();
switch (bundleType) {
case UMD_DEV:
case UMD_PROD:
if (moduleType !== ISOMORPHIC) {
externalModules.push('react');
}
break;
case NODE_DEV:
case NODE_PROD:
case RN_DEV:
case RN_PROD:
fbjsModules.forEach(module => externalModules.push(module));
externalModules.push('object-assign');
if (moduleType !== ISOMORPHIC) {
externalModules.push('react');
}
break;
case FB_DEV:
case FB_PROD:
fbjsModules.forEach(module => externalModules.push(module));
externalModules.push('object-assign');
externalModules.push('ReactCurrentOwner');
externalModules.push('lowPriorityWarning');
if (moduleType !== ISOMORPHIC) {
externalModules.push('React');
if (externalModules.indexOf('react-dom') > -1) {
externalModules.push('ReactDOM');
}
}
break;
}
return externalModules;
}
function getInternalModules() {
// we tell Rollup where these files are located internally, otherwise
// it doesn't pick them up and assumes they're external
return {
reactProdInvariant: resolve(
'./packages/shared/src/utils/reactProdInvariant.js'
),
};
}
function getFbjsModuleAliases(bundleType) {
switch (bundleType) {
case UMD_DEV:
case UMD_PROD:
// we want to bundle these modules, so we re-alias them to the actual
// file so Rollup can bundle them up
const fbjsModulesAlias = {};
fbjsModules.forEach(fbjsModule => {
fbjsModulesAlias[fbjsModule] = resolve(`./node_modules/${fbjsModule}`);
});
return fbjsModulesAlias;
case NODE_DEV:
case NODE_PROD:
case FB_DEV:
case FB_PROD:
case RN_DEV:
case RN_PROD:
// for FB we don't want to bundle the above modules, instead keep them
// as external require() calls in the bundle
return {};
}
}
function replaceFbjsModuleAliases(bundleType) {
switch (bundleType) {
case FB_DEV:
case FB_PROD:
// Haste at FB doesn't currently allow case sensitive names,
// and product code already uses "React". In the future,
// we will either allow both variants or migrate to lowercase.
return {
"'react'": "'React'",
"'react-dom'": "'ReactDOM'",
};
default:
return {};
}
}
const devOnlyModuleStub = `'${resolve('./scripts/rollup/shims/rollup/DevOnlyStubShim.js')}'`;
function replaceDevOnlyStubbedModules(bundleType) {
switch (bundleType) {
case UMD_DEV:
case NODE_DEV:
case FB_DEV:
case RN_DEV:
case RN_PROD:
return {};
case FB_PROD:
case UMD_PROD:
case NODE_PROD:
const devOnlyModuleAliases = {};
devOnlyFilesToStubOut.forEach(devOnlyModule => {
devOnlyModuleAliases[devOnlyModule] = devOnlyModuleStub;
});
return devOnlyModuleAliases;
}
}
function replaceLegacyModuleAliases(bundleType) {
switch (bundleType) {
case UMD_DEV:
case UMD_PROD:
const modulesAlias = {};
legacyModules.forEach(legacyModule => {
const modulePath = legacyModule.includes('/')
? legacyModule
: `${legacyModule}/index`;
const resolvedPath = resolve(`./node_modules/${modulePath}`);
modulesAlias[`'${legacyModule}'`] = `'${resolvedPath}'`;
});
return modulesAlias;
case NODE_DEV:
case NODE_PROD:
case FB_DEV:
case FB_PROD:
case RN_DEV:
case RN_PROD:
return {};
}
}
function replaceBundleStubModules(bundleModulesToStub) {
const stubbedModules = {};
if (Array.isArray(bundleModulesToStub)) {
bundleModulesToStub.forEach(module => {
stubbedModules[`'${module}'`] = devOnlyModuleStub;
});
}
return stubbedModules;
}
function getAliases(paths, bundleType, moduleType, extractErrors) {
return Object.assign(
createModuleMap(
paths,
extractErrors && extractErrorCodes(errorCodeOpts),
bundleType
),
getInternalModules(),
getNodeModules(bundleType, moduleType),
getFbjsModuleAliases(bundleType)
);
}
function replaceFeatureFlags(featureFlags) {
if (!featureFlags) {
return {};
}
return {
"'ReactFeatureFlags'": `'${resolve(featureFlags)}'`,
};
}
function getDefaultReplaceModules(
bundleType,
bundleModulesToStub,
featureFlags
) {
return Object.assign(
{},
replaceFbjsModuleAliases(bundleType),
replaceDevOnlyStubbedModules(bundleType),
replaceLegacyModuleAliases(bundleType),
replaceBundleStubModules(bundleModulesToStub),
replaceFeatureFlags(featureFlags)
);
}
function getExcludedHasteGlobs() {
return exclude;
}
module.exports = {
getExcludedHasteGlobs,
getDefaultReplaceModules,
getAliases,
ignoreFBModules,
ignoreReactNativeModules,
getExternalModules,
};