Skip to content

Commit 5e2ffcb

Browse files
committed
Refactor header and footer wrapping
It is easier to understand if we just explicitly type them out.
1 parent 6840eab commit 5e2ffcb

File tree

3 files changed

+206
-142
lines changed

3 files changed

+206
-142
lines changed

scripts/rollup/build.js

Lines changed: 8 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const syncReactNative = require('./sync').syncReactNative;
2525
const syncReactNativeRT = require('./sync').syncReactNativeRT;
2626
const syncReactNativeCS = require('./sync').syncReactNativeCS;
2727
const Packaging = require('./packaging');
28-
const Header = require('./header');
28+
const Wrappers = require('./wrappers');
2929

3030
const UMD_DEV = Bundles.bundleTypes.UMD_DEV;
3131
const UMD_PROD = Bundles.bundleTypes.UMD_PROD;
@@ -36,9 +36,6 @@ const FB_PROD = Bundles.bundleTypes.FB_PROD;
3636
const RN_DEV = Bundles.bundleTypes.RN_DEV;
3737
const RN_PROD = Bundles.bundleTypes.RN_PROD;
3838

39-
const RECONCILER = Bundles.moduleTypes.RECONCILER;
40-
41-
const reactVersion = require('../../package.json').version;
4239
const requestedBundleTypes = (argv.type || '')
4340
.split(',')
4441
.map(type => type.toUpperCase());
@@ -63,109 +60,6 @@ const closureOptions = {
6360
processCommonJsModules: false,
6461
};
6562

66-
function getBanner(bundleType, globalName, filename, moduleType) {
67-
if (moduleType === RECONCILER) {
68-
// Standalone reconciler is only used by third-party renderers.
69-
// It is handled separately.
70-
return getReconcilerBanner(bundleType, filename);
71-
}
72-
73-
switch (bundleType) {
74-
// UMDs are not wrapped in conditions.
75-
case UMD_DEV:
76-
case UMD_PROD:
77-
return Header.getHeader(filename, reactVersion);
78-
// CommonJS DEV bundle is guarded to help weak dead code elimination.
79-
case NODE_DEV:
80-
let banner = Header.getHeader(filename, reactVersion);
81-
// Wrap the contents of the if-DEV check with an IIFE.
82-
// Block-level function definitions can cause problems for strict mode.
83-
banner += `'use strict';\n\n\nif (process.env.NODE_ENV !== "production") {\n(function() {\n`;
84-
return banner;
85-
case NODE_PROD:
86-
return Header.getHeader(filename, reactVersion);
87-
// All FB and RN bundles need Haste headers.
88-
// DEV bundle is guarded to help weak dead code elimination.
89-
case FB_DEV:
90-
case FB_PROD:
91-
case RN_DEV:
92-
case RN_PROD:
93-
const isDev = bundleType === FB_DEV || bundleType === RN_DEV;
94-
const hasteFinalName = globalName + (isDev ? '-dev' : '-prod');
95-
// Wrap the contents of the if-DEV check with an IIFE.
96-
// Block-level function definitions can cause problems for strict mode.
97-
return (
98-
Header.getProvidesHeader(hasteFinalName) +
99-
(isDev ? `\n\n'use strict';\n\n\nif (__DEV__) {\n(function() {\n` : '')
100-
);
101-
default:
102-
throw new Error('Unknown type.');
103-
}
104-
}
105-
106-
function getFooter(bundleType, filename, moduleType) {
107-
if (moduleType === RECONCILER) {
108-
// Standalone reconciler is only used by third-party renderers.
109-
// It is handled separately.
110-
return getReconcilerFooter(bundleType);
111-
}
112-
113-
// Only need a footer if getBanner() has an opening brace.
114-
switch (bundleType) {
115-
// Non-UMD DEV bundles need conditions to help weak dead code elimination.
116-
case NODE_DEV:
117-
case FB_DEV:
118-
case RN_DEV:
119-
return '\n})();\n}\n';
120-
default:
121-
return '';
122-
}
123-
}
124-
125-
// TODO: this is extremely gross.
126-
// But it only affects the "experimental" standalone reconciler build.
127-
// The goal is to avoid having any shared state between renderers sharing it on npm.
128-
// Ideally we should just remove shared state in all Fiber modules and then lint against it.
129-
// But for now, we store the exported function in a variable, and then put the rest of the code
130-
// into a closure that makes all module-level state private to each call.
131-
const RECONCILER_WRAPPER_INTRO = `var $$$reconciler;\nmodule.exports = function(config) {\n`;
132-
const RECONCILER_WRAPPER_OUTRO = `return ($$$reconciler || ($$$reconciler = module.exports))(config);\n};\n`;
133-
134-
function getReconcilerBanner(bundleType, filename) {
135-
let banner = `${Header.getHeader(
136-
filename,
137-
reactVersion
138-
)}\n\n'use strict';\n\n\n`;
139-
switch (bundleType) {
140-
case NODE_DEV:
141-
banner += `if (process.env.NODE_ENV !== "production") {\n${
142-
RECONCILER_WRAPPER_INTRO
143-
}`;
144-
break;
145-
case NODE_PROD:
146-
banner += RECONCILER_WRAPPER_INTRO;
147-
break;
148-
default:
149-
throw new Error(
150-
'Standalone reconciler does not support ' + bundleType + ' builds.'
151-
);
152-
}
153-
return banner;
154-
}
155-
156-
function getReconcilerFooter(bundleType) {
157-
switch (bundleType) {
158-
case NODE_DEV:
159-
return `\n${RECONCILER_WRAPPER_OUTRO}\n}`;
160-
case NODE_PROD:
161-
return `\n${RECONCILER_WRAPPER_OUTRO}`;
162-
default:
163-
throw new Error(
164-
'Standalone reconciler does not support ' + bundleType + ' builds.'
165-
);
166-
}
167-
}
168-
16963
function getBabelConfig(updateBabelOptions, bundleType, filename) {
17064
let options = {
17165
exclude: 'node_modules/**',
@@ -393,9 +287,13 @@ function getPlugins(
393287
// License and haste headers, top-level `if` blocks.
394288
{
395289
transformBundle(source) {
396-
const banner = getBanner(bundleType, globalName, filename, moduleType);
397-
const footer = getFooter(bundleType, filename, moduleType);
398-
return banner + '\n' + source + '\n' + footer;
290+
return Wrappers.wrapBundle(
291+
source,
292+
bundleType,
293+
globalName,
294+
filename,
295+
moduleType
296+
);
399297
},
400298
},
401299
// Record bundle size.

scripts/rollup/header.js

Lines changed: 0 additions & 32 deletions
This file was deleted.

scripts/rollup/wrappers.js

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
'use strict';
2+
3+
const Bundles = require('./bundles');
4+
const reactVersion = require('../../package.json').version;
5+
6+
const UMD_DEV = Bundles.bundleTypes.UMD_DEV;
7+
const UMD_PROD = Bundles.bundleTypes.UMD_PROD;
8+
const NODE_DEV = Bundles.bundleTypes.NODE_DEV;
9+
const NODE_PROD = Bundles.bundleTypes.NODE_PROD;
10+
const FB_DEV = Bundles.bundleTypes.FB_DEV;
11+
const FB_PROD = Bundles.bundleTypes.FB_PROD;
12+
const RN_DEV = Bundles.bundleTypes.RN_DEV;
13+
const RN_PROD = Bundles.bundleTypes.RN_PROD;
14+
15+
const RECONCILER = Bundles.moduleTypes.RECONCILER;
16+
17+
const license = ` * Copyright (c) 2013-present, Facebook, Inc.
18+
*
19+
* This source code is licensed under the MIT license found in the
20+
* LICENSE file in the root directory of this source tree.`;
21+
22+
const wrappers = {
23+
/***************** UMD_DEV *****************/
24+
[UMD_DEV](source, globalName, filename, moduleType) {
25+
return `/** @license React v${reactVersion}
26+
* ${filename}
27+
*
28+
${license}
29+
*/
30+
31+
'use strict';
32+
33+
${source}`;
34+
},
35+
36+
/***************** UMD_PROD *****************/
37+
[UMD_PROD](source, globalName, filename, moduleType) {
38+
return `/** @license React v${reactVersion}
39+
* ${filename}
40+
*
41+
${license}
42+
*/
43+
${source}`;
44+
},
45+
46+
/***************** NODE_DEV *****************/
47+
[NODE_DEV](source, globalName, filename, moduleType) {
48+
return `/** @license React v${reactVersion}
49+
* ${filename}
50+
*
51+
${license}
52+
*/
53+
54+
'use strict';
55+
56+
if (process.env.NODE_ENV !== "production") {
57+
(function() {
58+
${source}
59+
})();
60+
}`;
61+
},
62+
63+
/***************** NODE_PROD *****************/
64+
[NODE_PROD](source, globalName, filename, moduleType) {
65+
return `/** @license React v${reactVersion}
66+
* ${filename}
67+
*
68+
${license}
69+
*/
70+
${source}`;
71+
},
72+
73+
/****************** FB_DEV ******************/
74+
[FB_DEV](source, globalName, filename, moduleType) {
75+
return `/**
76+
${license}
77+
*
78+
* @noflow
79+
* @providesModule ${globalName}-dev
80+
* @preventMunge
81+
*/
82+
83+
'use strict';
84+
85+
if (__DEV__) {
86+
(function() {
87+
${source}
88+
})();
89+
}`;
90+
},
91+
92+
/****************** FB_PROD ******************/
93+
[FB_PROD](source, globalName, filename, moduleType) {
94+
return `/**
95+
${license}
96+
*
97+
* @noflow
98+
* @providesModule ${globalName}-prod
99+
* @preventMunge
100+
*/
101+
102+
${source}`;
103+
},
104+
105+
/****************** RN_DEV ******************/
106+
[RN_DEV](source, globalName, filename, moduleType) {
107+
return `/**
108+
${license}
109+
*
110+
* @noflow
111+
* @providesModule ${globalName}-dev
112+
* @preventMunge
113+
*/
114+
115+
'use strict';
116+
117+
if (__DEV__) {
118+
(function() {
119+
${source}
120+
})();
121+
}`;
122+
},
123+
124+
/****************** RN_DEV ******************/
125+
[RN_PROD](source, globalName, filename, moduleType) {
126+
return `/**
127+
${license}
128+
*
129+
* @noflow
130+
* @providesModule ${globalName}-prod
131+
* @preventMunge
132+
*/
133+
134+
${source}`;
135+
},
136+
};
137+
138+
const reconcilerWrappers = {
139+
/***************** NODE_DEV (reconciler only) *****************/
140+
[NODE_DEV](source, globalName, filename, moduleType) {
141+
return `/** @license React v${reactVersion}
142+
* ${filename}
143+
*
144+
${license}
145+
*/
146+
147+
'use strict';
148+
149+
if (process.env.NODE_ENV !== "production") {
150+
// This is a hacky way to ensure third party renderers don't share
151+
// top-level module state inside the reconciler. Ideally we should
152+
// remove this hack by putting all top-level state into the closures
153+
// and then forbidding adding more of it in the reconciler.
154+
var $$$reconciler;
155+
module.exports = function(config) {
156+
${source}
157+
return ($$$reconciler || ($$$reconciler = module.exports))(config);
158+
};
159+
}`;
160+
},
161+
162+
/***************** NODE_PROD (reconciler only) *****************/
163+
[NODE_PROD](source, globalName, filename, moduleType) {
164+
return `/** @license React v${reactVersion}
165+
* ${filename}
166+
*
167+
${license}
168+
*/
169+
module.exports = function(config) {
170+
${source}
171+
return ($$$reconciler || ($$$reconciler = module.exports))(config);
172+
};`;
173+
},
174+
};
175+
176+
function wrapBundle(source, bundleType, globalName, filename, moduleType) {
177+
if (moduleType === RECONCILER) {
178+
// Standalone reconciler is only used by third-party renderers.
179+
// It is handled separately.
180+
const wrapper = reconcilerWrappers[bundleType];
181+
if (typeof wrapper !== 'function') {
182+
throw new Error(
183+
`Unsupported build type for the reconciler package: ${bundleType}.`
184+
);
185+
}
186+
return wrapper(source, globalName, filename, moduleType);
187+
}
188+
// All the other packages.
189+
const wrapper = wrappers[bundleType];
190+
if (typeof wrapper !== 'function') {
191+
throw new Error(`Unsupported build type: ${bundleType}.`);
192+
}
193+
return wrapper(source, globalName, filename, moduleType);
194+
}
195+
196+
module.exports = {
197+
wrapBundle,
198+
};

0 commit comments

Comments
 (0)