@samitouri / QOS-React / commits / 0f004efce2

Build renderers into their individual npm packages (#7168)

This copies modules into three separate packages instead of putting it all in React. The overlap in shared and between renderers gets duplicated. This allows the isomorphic package to stay minimal. It can also be used as a direct dependency without much risk. This also allow us to ship versions to each renderer independently and we can ship renderers without updating the main react package dependency.

Sebastian Markbåge committed Aug 10, 2016 at 18:17 UTC 0f004efce2dcd0189a663f5724853eab261782e6
17 files changed +237 -42
grunt/config/browserify.js
+17 -10
@@ -16,7 +16,7 @@ var envifyProd = envify({NODE_ENV: process.env.NODE_ENV || 'production'});
16
17 var SECRET_INTERNALS_NAME = 'React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED';
18
19 -var shimSharedModules = globalShim.configure({
19 +var shimSharedModulesFiles = {
20 './ReactCurrentOwner': SECRET_INTERNALS_NAME + '.ReactCurrentOwner',
21 './ReactComponentTreeHook': SECRET_INTERNALS_NAME + '.ReactComponentTreeHook',
22 // The methods we used here are exposed on the main React export.
@@ -26,7 +26,14 @@ var shimSharedModules = globalShim.configure({
26 './ReactElement': 'React',
27 './ReactPropTypes': 'React.PropTypes',
28 './ReactChildren': 'React.Children',
29 -});
29 +};
30 +
31 +// We can access these as absolute or relative. We need to shim both.
32 +for (var key in shimSharedModulesFiles) {
33 + shimSharedModulesFiles[key.replace(/^\.\//, 'react/lib/')] = shimSharedModulesFiles[key];
34 +}
35 +
36 +var shimSharedModules = globalShim.configure(shimSharedModulesFiles);
37
38 var shimDOMModules = aliasify.configure({
39 'aliases': {
@@ -72,7 +79,7 @@ function simpleBannerify(src) {
79 // Our basic config which we'll add to to make our other builds
80 var basic = {
81 entries: [
75 - './build/modules/ReactUMDEntry.js',
82 + './build/node_modules/react/lib/ReactUMDEntry.js',
83 ],
84 outfile: './build/react.js',
85 debug: false,
@@ -85,7 +92,7 @@ var basic = {
92
93 var min = {
94 entries: [
88 - './build/modules/ReactUMDEntry.js',
95 + './build/node_modules/react/lib/ReactUMDEntry.js',
96 ],
97 outfile: './build/react.min.js',
98 debug: false,
@@ -103,7 +110,7 @@ var min = {
110
111 var addons = {
112 entries: [
106 - './build/modules/ReactWithAddonsUMDEntry.js',
113 + './build/node_modules/react/lib/ReactWithAddonsUMDEntry.js',
114 ],
115 outfile: './build/react-with-addons.js',
116 debug: false,
@@ -117,7 +124,7 @@ var addons = {
124
125 var addonsMin = {
126 entries: [
120 - './build/modules/ReactWithAddonsUMDEntry.js',
127 + './build/node_modules/react/lib/ReactWithAddonsUMDEntry.js',
128 ],
129 outfile: './build/react-with-addons.min.js',
130 debug: false,
@@ -135,7 +142,7 @@ var addonsMin = {
142 // The DOM Builds
143 var dom = {
144 entries: [
138 - './build/modules/ReactDOMUMDEntry.js',
145 + './build/node_modules/react-dom/lib/ReactDOMUMDEntry.js',
146 ],
147 outfile: './build/react-dom.js',
148 debug: false,
@@ -149,7 +156,7 @@ var dom = {
156
157 var domMin = {
158 entries: [
152 - './build/modules/ReactDOMUMDEntry.js',
159 + './build/node_modules/react-dom/lib/ReactDOMUMDEntry.js',
160 ],
161 outfile: './build/react-dom.min.js',
162 debug: false,
@@ -167,7 +174,7 @@ var domMin = {
174
175 var domServer = {
176 entries: [
170 - './build/modules/ReactDOMServerUMDEntry.js',
177 + './build/node_modules/react-dom/lib/ReactDOMServerUMDEntry.js',
178 ],
179 outfile: './build/react-dom-server.js',
180 debug: false,
@@ -181,7 +188,7 @@ var domServer = {
188
189 var domServerMin = {
190 entries: [
184 - './build/modules/ReactDOMServerUMDEntry.js',
191 + './build/node_modules/react-dom/lib/ReactDOMServerUMDEntry.js',
192 ],
193 outfile: './build/react-dom-server.min.js',
194 debug: false,
grunt/tasks/npm-react-addons.js
+19 -2
@@ -6,46 +6,55 @@ var path = require('path');
6
7 var addons = {
8 CSSTransitionGroup: {
9 + peerDependency: 'react',
10 module: 'ReactCSSTransitionGroup',
11 name: 'css-transition-group',
12 docs: 'animation',
13 },
14 LinkedStateMixin: {
15 + peerDependency: 'react',
16 module: 'LinkedStateMixin',
17 name: 'linked-state-mixin',
18 docs: 'two-way-binding-helpers',
19 },
20 Perf: {
21 + peerDependency: 'react-dom',
22 module: 'ReactPerf',
23 name: 'perf',
24 docs: 'perf',
25 },
26 PureRenderMixin: {
27 + peerDependency: 'react',
28 module: 'ReactComponentWithPureRenderMixin',
29 name: 'pure-render-mixin',
30 docs: 'pure-render-mixin',
31 },
32 TestUtils: {
33 + peerDependency: 'react-dom',
34 module: 'ReactTestUtils',
35 name: 'test-utils',
36 docs: 'test-utils',
37 },
38 TransitionGroup: {
39 + peerDependency: 'react',
40 module: 'ReactTransitionGroup',
41 name: 'transition-group',
42 docs: 'animation',
43 },
44 createFragment: {
45 + peerDependency: 'react',
46 module: 'ReactFragment',
47 method: 'create',
48 name: 'create-fragment',
49 docs: 'create-fragment',
50 },
51 shallowCompare: {
52 + peerDependency: 'react',
53 module: 'shallowCompare',
54 name: 'shallow-compare',
55 },
56 updates: {
57 + peerDependency: 'react',
58 module: 'update',
59 name: 'update',
60 docs: 'update',
@@ -54,9 +63,11 @@ var addons = {
63
64 function generateSource(info) {
65 var pieces = [
57 - "module.exports = require('react/lib/",
66 + 'module.exports = require(\'',
67 + info.peerDependency,
68 + '/lib/',
69 info.module,
59 - "')",
70 + '\')',
71 ];
72 if (info.method) {
73 pieces.push('.', info.method);
@@ -78,6 +89,12 @@ function buildReleases() {
89 var pkgData = Object.assign({}, pkgTemplate);
90 pkgData.name = pkgName;
91
92 + var version = pkgTemplate.peerDependencies.react;
93 + if (info.peerDependency !== 'react') {
94 + pkgData.peerDependencies = {};
95 + pkgData.peerDependencies[info.peerDependency] = version;
96 + }
97 +
98 grunt.file.mkdir(destDir);
99 var link = info.docs ? info.docs : 'addons';
100 link = `https://facebook.github.io/react/docs/${link}.html`;
grunt/tasks/npm-react-dom.js
+3
@@ -5,6 +5,8 @@ var grunt = require('grunt');
5
6 var src = 'packages/react-dom/';
7 var dest = 'build/packages/react-dom/';
8 +var modSrc = 'build/node_modules/react-dom/lib';
9 +var lib = dest + 'lib/';
10 var dist = dest + 'dist/';
11 var distFiles = [
12 'react-dom.js',
@@ -21,6 +23,7 @@ function buildRelease() {
23 // Copy to build/packages/react-dom
24 var mappings = [].concat(
25 grunt.file.expandMapping('**/*', dest, {cwd: src}),
26 + grunt.file.expandMapping('**/*', lib, {cwd: modSrc}),
27 grunt.file.expandMapping('{LICENSE,PATENTS}', dest)
28 );
29 mappings.forEach(function(mapping) {
grunt/tasks/npm-react-native.js
+3
@@ -5,6 +5,8 @@ var grunt = require('grunt');
5
6 var src = 'packages/react-native-renderer/';
7 var dest = 'build/packages/react-native-renderer/';
8 +var modSrc = 'build/node_modules/react-native/lib';
9 +var lib = dest + 'lib/';
10
11 function buildRelease() {
12 if (grunt.file.exists(dest)) {
@@ -14,6 +16,7 @@ function buildRelease() {
16 // Copy to build/packages/react-native-renderer
17 var mappings = [].concat(
18 grunt.file.expandMapping('**/*', dest, {cwd: src}),
19 + grunt.file.expandMapping('**/*', lib, {cwd: modSrc}),
20 grunt.file.expandMapping('{LICENSE,PATENTS}', dest)
21 );
22 mappings.forEach(function(mapping) {
grunt/tasks/npm-react-test.js
+3
@@ -5,6 +5,8 @@ var grunt = require('grunt');
5
6 var src = 'packages/react-test-renderer/';
7 var dest = 'build/packages/react-test-renderer/';
8 +var modSrc = 'build/node_modules/react-test-renderer/lib';
9 +var lib = dest + 'lib/';
10
11 function buildRelease() {
12 if (grunt.file.exists(dest)) {
@@ -14,6 +16,7 @@ function buildRelease() {
16 // Copy to build/packages/react-native-renderer
17 var mappings = [].concat(
18 grunt.file.expandMapping('**/*', dest, {cwd: src}),
19 + grunt.file.expandMapping('**/*', lib, {cwd: modSrc}),
20 grunt.file.expandMapping('{LICENSE,PATENTS}', dest)
21 );
22 mappings.forEach(function(mapping) {
grunt/tasks/npm-react.js
+1 -1
@@ -5,7 +5,7 @@ var grunt = require('grunt');
5
6 var src = 'packages/react/';
7 var dest = 'build/packages/react/';
8 -var modSrc = 'build/modules/';
8 +var modSrc = 'build/node_modules/react/lib';
9 var lib = dest + 'lib/';
10 var dist = dest + 'dist/';
11 var distFiles = [
gulpfile.js
+167 -17
@@ -13,6 +13,7 @@ var gulp = require('gulp');
13 var babel = require('gulp-babel');
14 var flatten = require('gulp-flatten');
15 var del = require('del');
16 +var merge = require('merge-stream');
17
18 var babelPluginModules = require('fbjs-scripts/babel-6/rewrite-modules');
19 var extractErrors = require('./scripts/error-codes/gulp-extract-errors');
@@ -28,21 +29,113 @@ function getTask(name) {
29 var paths = {
30 react: {
31 src: [
31 - 'src/**/*.js',
32 + 'src/umd/ReactUMDEntry.js',
33 + 'src/umd/ReactWithAddonsUMDEntry.js',
34 + 'src/umd/shims/ReactAddonsDOMDependenciesUMDShim.js',
35 +
36 + 'src/isomorphic/**/*.js',
37 + 'src/addons/**/*.js',
38 +
39 + 'src/ReactVersion.js',
40 + 'src/shared/**/*.js',
41 + '!src/shared/vendor/**/*.js',
42 + '!src/**/__benchmarks__/**/*.js',
43 + '!src/**/__tests__/**/*.js',
44 + '!src/**/__mocks__/**/*.js',
45 + ],
46 + lib: 'build/node_modules/react/lib',
47 + },
48 + reactDOM: {
49 + src: [
50 + 'src/umd/ReactDOMUMDEntry.js',
51 + 'src/umd/ReactDOMServerUMDEntry.js',
52 +
53 + 'src/renderers/dom/**/*.js',
54 + 'src/renderers/shared/**/*.js',
55 + 'src/test/**/*.js', // ReactTestUtils is currently very coupled to DOM.
56 +
57 + 'src/ReactVersion.js',
58 + 'src/shared/**/*.js',
59 + '!src/shared/vendor/**/*.js',
60 + '!src/**/__benchmarks__/**/*.js',
61 + '!src/**/__tests__/**/*.js',
62 + '!src/**/__mocks__/**/*.js',
63 + ],
64 + lib: 'build/node_modules/react-dom/lib',
65 + },
66 + reactNative: {
67 + src: [
68 + 'src/renderers/native/**/*.js',
69 + 'src/renderers/shared/**/*.js',
70 +
71 + 'src/ReactVersion.js',
72 + 'src/shared/**/*.js',
73 + '!src/shared/vendor/**/*.js',
74 '!src/**/__benchmarks__/**/*.js',
75 '!src/**/__tests__/**/*.js',
76 '!src/**/__mocks__/**/*.js',
35 - '!src/renderers/art/**/*.js',
77 + ],
78 + lib: 'build/node_modules/react-native/lib',
79 + },
80 + reactTestRenderer: {
81 + src: [
82 + 'src/renderers/testing/**/*.js',
83 + 'src/renderers/shared/**/*.js',
84 +
85 + 'src/ReactVersion.js',
86 + 'src/shared/**/*.js',
87 '!src/shared/vendor/**/*.js',
88 + '!src/**/__benchmarks__/**/*.js',
89 + '!src/**/__tests__/**/*.js',
90 + '!src/**/__mocks__/**/*.js',
91 ],
38 - lib: 'build/modules',
92 + lib: 'build/node_modules/react-test-renderer/lib',
93 },
94 };
95
42 -var moduleMap = Object.assign(
96 +var moduleMapBase = Object.assign(
97 {'object-assign': 'object-assign'},
44 - require('fbjs/module-map'),
98 + require('fbjs/module-map')
99 +);
100 +
101 +var moduleMapReact = Object.assign(
102 + {
103 + // Addons needs to reach into DOM internals
104 + ReactDOM: 'react-dom/lib/ReactDOM',
105 + ReactInstanceMap: 'react-dom/lib/ReactInstanceMap',
106 + ReactTestUtils: 'react-dom/lib/ReactTestUtils',
107 + ReactPerf: 'react-dom/lib/ReactPerf',
108 + getVendorPrefixedEventName: 'react-dom/lib/getVendorPrefixedEventName',
109 + },
110 + moduleMapBase
111 +);
112 +
113 +var rendererSharedState = {
114 + // Shared state
115 + ReactCurrentOwner: 'react/lib/ReactCurrentOwner',
116 + ReactComponentTreeHook: 'react/lib/ReactComponentTreeHook',
117 +
118 + // TODO: Move to shared since these are actually shared and can be copied.
119 + ReactPropTypeLocations: 'react/lib/ReactPropTypeLocations',
120 + ReactPropTypesSecret: 'react/lib/ReactPropTypesSecret',
121 + checkReactTypeSpec: 'react/lib/checkReactTypeSpec',
122 +
123 + // TODO: Update the source to just use the React module.
124 + React: 'react/lib/React',
125 + ReactElement: 'react/lib/ReactElement',
126 + ReactPropTypes: 'react/lib/ReactPropTypes',
127 + ReactChildren: 'react/lib/ReactChildren',
128 +};
129 +
130 +var moduleMapReactDOM = Object.assign(
131 + {},
132 + rendererSharedState,
133 + moduleMapBase
134 +);
135 +
136 +var moduleMapReactNative = Object.assign(
137 {
138 + // React Native Hooks
139 deepDiffer: 'react-native/lib/deepDiffer',
140 deepFreezeAndThrowOnMutationInDev: 'react-native/lib/deepFreezeAndThrowOnMutationInDev',
141 flattenStyle: 'react-native/lib/flattenStyle',
@@ -52,17 +145,46 @@ var moduleMap = Object.assign(
145 UIManager: 'react-native/lib/UIManager',
146 UIManagerStatTracker: 'react-native/lib/UIManagerStatTracker',
147 View: 'react-native/lib/View',
55 - }
148 + },
149 + rendererSharedState,
150 + moduleMapBase
151 +);
152 +
153 +var moduleMapReactTestRenderer = Object.assign(
154 + {},
155 + rendererSharedState,
156 + moduleMapBase
157 );
158
159 var errorCodeOpts = {
160 errorMapFilePath: 'scripts/error-codes/codes.json',
161 };
162
62 -var babelOpts = {
163 +var babelOptsReact = {
164 + plugins: [
165 + devExpressionWithCodes, // this pass has to run before `rewrite-modules`
166 + [babelPluginModules, {map: moduleMapReact}],
167 + ],
168 +};
169 +
170 +var babelOptsReactDOM = {
171 + plugins: [
172 + devExpressionWithCodes, // this pass has to run before `rewrite-modules`
173 + [babelPluginModules, {map: moduleMapReactDOM}],
174 + ],
175 +};
176 +
177 +var babelOptsReactNative = {
178 + plugins: [
179 + devExpressionWithCodes, // this pass has to run before `rewrite-modules`
180 + [babelPluginModules, {map: moduleMapReactNative}],
181 + ],
182 +};
183 +
184 +var babelOptsReactTestRenderer = {
185 plugins: [
186 devExpressionWithCodes, // this pass has to run before `rewrite-modules`
65 - [babelPluginModules, {map: moduleMap}],
187 + [babelPluginModules, {map: moduleMapReactTestRenderer}],
188 ],
189 };
190
@@ -75,21 +197,49 @@ gulp.task('flow', getTask('flow'));
197 gulp.task('version-check', getTask('version-check'));
198
199 gulp.task('react:clean', function() {
78 - return del([paths.react.lib]);
200 + return del([
201 + paths.react.lib,
202 + paths.reactDOM.lib,
203 + paths.reactNative.lib,
204 + paths.reactTestRenderer.lib,
205 + ]);
206 });
207
208 gulp.task('react:modules', function() {
82 - return gulp
83 - .src(paths.react.src)
84 - .pipe(babel(babelOpts))
85 - .pipe(flatten())
86 - .pipe(gulp.dest(paths.react.lib));
209 + return merge(
210 + gulp
211 + .src(paths.react.src)
212 + .pipe(babel(babelOptsReact))
213 + .pipe(flatten())
214 + .pipe(gulp.dest(paths.react.lib)),
215 +
216 + gulp
217 + .src(paths.reactDOM.src)
218 + .pipe(babel(babelOptsReactDOM))
219 + .pipe(flatten())
220 + .pipe(gulp.dest(paths.reactDOM.lib)),
221 +
222 + gulp
223 + .src(paths.reactNative.src)
224 + .pipe(babel(babelOptsReactNative))
225 + .pipe(flatten())
226 + .pipe(gulp.dest(paths.reactNative.lib)),
227 +
228 + gulp
229 + .src(paths.reactTestRenderer.src)
230 + .pipe(babel(babelOptsReactTestRenderer))
231 + .pipe(flatten())
232 + .pipe(gulp.dest(paths.reactTestRenderer.lib))
233 + );
234 });
235
236 gulp.task('react:extract-errors', function() {
90 - return gulp
91 - .src(paths.react.src)
92 - .pipe(extractErrors(errorCodeOpts));
237 + return merge(
238 + gulp.src(paths.react.src).pipe(extractErrors(errorCodeOpts)),
239 + gulp.src(paths.reactDOM.src).pipe(extractErrors(errorCodeOpts)),
240 + gulp.src(paths.reactNative.src).pipe(extractErrors(errorCodeOpts)),
241 + gulp.src(paths.reactTestRenderer.src).pipe(extractErrors(errorCodeOpts))
242 + );
243 });
244
245 gulp.task('default', ['react:modules']);
package.json
+1
@@ -61,6 +61,7 @@
61 "gzip-js": "~0.3.2",
62 "jest": "^12.1.1",
63 "loose-envify": "^1.1.0",
64 + "merge-stream": "^1.0.0",
65 "object-assign": "^4.1.0",
66 "platform": "^1.1.0",
67 "run-sequence": "^1.1.4",
packages/react-dom/index.js
+1 -1
@@ -1,3 +1,3 @@
1 'use strict';
2
3 -module.exports = require('react/lib/ReactDOM');
3 +module.exports = require('./lib/ReactDOM');
packages/react-dom/package.json
+12 -2
@@ -12,7 +12,11 @@
12 "url": "https://github.com/facebook/react/issues"
13 },
14 "homepage": "https://facebook.github.io/react/",
15 - "dependencies": {},
15 + "dependencies": {
16 + "fbjs": "^0.8.1",
17 + "loose-envify": "^1.1.0",
18 + "object-assign": "^4.1.0"
19 + },
20 "peerDependencies": {
21 "react": "^16.0.0-alpha"
22 },
@@ -21,7 +25,13 @@
25 "PATENTS",
26 "README.md",
27 "dist/",
28 + "lib/",
29 "index.js",
30 "server.js"
26 - ]
31 + ],
32 + "browserify": {
33 + "transform": [
34 + "loose-envify"
35 + ]
36 + }
37 }
packages/react-dom/server.js
+1 -1
@@ -1,3 +1,3 @@
1 'use strict';
2
3 -module.exports = require('react/lib/ReactDOMServer');
3 +module.exports = require('./lib/ReactDOMServer');
packages/react-linked-input/LinkedInput.js
+1 -1
@@ -10,7 +10,7 @@
10 'use strict';
11
12 var React = require('react');
13 -var LinkedValueUtils = require('react/lib/LinkedValueUtils');
13 +var LinkedValueUtils = require('react-dom/lib/LinkedValueUtils');
14
15 class LinkedInput extends React.Component {
16 render() {
packages/react-native-renderer/index.js
+1 -1
@@ -1,3 +1,3 @@
1 'use strict';
2
3 -module.exports = require('react/lib/ReactNative');
3 +module.exports = require('./lib/ReactNative');
packages/react-native-renderer/package.json
+6 -1
@@ -14,12 +14,17 @@
14 },
15 "homepage": "https://facebook.github.io/react-native/",
16 "dependencies": {
17 + "fbjs": "^0.8.1",
18 + "object-assign": "^4.1.0"
19 + },
20 + "peerDependencies": {
21 "react": "^16.0.0-alpha"
22 },
23 "files": [
24 "LICENSE",
25 "PATENTS",
26 "README.md",
23 - "index.js"
27 + "index.js",
28 + "lib/"
29 ]
30 }
packages/react-test-renderer/index.js
+1 -2
@@ -1,4 +1,3 @@
1 -
1 'use strict';
2
4 -module.exports = require('react/lib/ReactTestRenderer');
3 +module.exports = require('./lib/ReactTestRenderer');
src/renderers/shared/stack/event/SyntheticEvent.js renamed
src/renderers/testing/ReactTestRenderer.js
-3
@@ -20,8 +20,6 @@ var ReactTestMount = require('ReactTestMount');
20 var ReactTestReconcileTransaction = require('ReactTestReconcileTransaction');
21 var ReactUpdates = require('ReactUpdates');
22
23 -var renderSubtreeIntoContainer = require('renderSubtreeIntoContainer');
24 -
23 /**
24 * Drill down (through composites and empty components) until we get a native or
25 * native text component.
@@ -141,7 +139,6 @@ var ReactTestRenderer = {
139
140 /* eslint-disable camelcase */
141 unstable_batchedUpdates: ReactUpdates.batchedUpdates,
144 - unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer,
142 /* eslint-enable camelcase */
143 };
144