Fix browser bundle for AMD (#8374)
* Fix browser bundle for AMD * Final fix for standalone browser build. Much more scientific than the rest so it should stick. * Throw when we can't find code we need to replace.
Paul O’Shannessy committed
Nov 22, 2016 at 17:16 UTC
a3ba48bf724de4c23d7c32f1b381476bcd3bb6fa
1 file changed
+27
-8
grunt/config/browserify.js
+27
-8
@@ -63,7 +63,7 @@ function simpleBannerify(src) {
63
}
64
65
// What is happening here???
66
-// I'm glad you asked. It became really to make our bundle splitting work.
66
+// I'm glad you asked. It became really hard to make our bundle splitting work.
67
// Everything is fine in node and when bundling with those packages, but when
68
// using our pre-packaged files, the splitting didn't work. Specifically due to
69
// the UMD wrappers defining their own require and creating their own encapsulated
@@ -71,19 +71,38 @@ function simpleBannerify(src) {
71
// be smart and looks for top-level requires (even when aliasing to a bundle),
72
// but since we didn't have those, we couldn't require 'react' from 'react-dom'.
73
// But we are already shimming in some modules that look for a global React
74
-// variable. So we write a wrapper around the UMD bundle that browserify creates,
75
-// and define a React variable that will require across Webpack-boundaries or fall
76
-// back to the global, just like it would previously.
74
+// variable. So we replace the UMD wrapper that browserify creates with out own,
75
+// in 2 steps.
76
+// 1. We swap out the browserify UMD with a plain function call. This ensures
77
+// that the internal wrapper doesn't interact with the external state. By the
78
+// time we're in the internal wrapper it doesn't matter what the external wrapper
79
+// detected. Browserify insulates its CommonJS system inside closures so can just
80
+// call that function and return it.
81
+// 2. We put our own UMD wrapper around that fixed internal function, ensuring
82
+// React is in scope. This outer wrapper is essentially the same UMD wrapper
83
+// browserify would create, just handling the scope issue.
84
+// Is this insane? Yes.
85
+// Does it work? Yes.
86
+// Should it go away ASAP? Yes.
87
function wrapperify(src) {
88
+ var toReplace =
89
+ `function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.${this.data.standalone} = f()}}`;
90
+ if (src.indexOf(toReplace) === -1) {
91
+ throw new Error('wrapperify failed to find code to replace');
92
+ }
93
+ src = src.replace(
94
+ toReplace,
95
+ `function(f){return f()}`
96
+ );
97
return `
98
;(function(f) {
99
// CommonJS
100
if (typeof exports === "object" && typeof module !== "undefined") {
82
- f(require('react'));
101
+ module.exports = f(require('react'));
102
103
// RequireJS
104
} else if (typeof define === "function" && define.amd) {
86
- require(['react'], f);
105
+ define(['react'], f);
106
107
// <script>
108
} else {
@@ -100,10 +119,10 @@ function wrapperify(src) {
119
// see https://github.com/facebook/react/issues/3037
120
g = this;
121
}
103
- f(g.React)
122
+ g.${this.data.standalone} = f(g.React);
123
}
124
})(function(React) {
106
- ${src}
125
+ return ${src}
126
});
127
`;
128
}