From 24ffd57dfa8248e0668203ee72d9a16c9627d64d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Tue, 22 Nov 2016 17:16:45 -0800 Subject: [PATCH] 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. (cherry picked from commit a3ba48bf724de4c23d7c32f1b381476bcd3bb6fa) --- grunt/config/browserify.js | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/grunt/config/browserify.js b/grunt/config/browserify.js index 282c003d61..e626091486 100644 --- a/grunt/config/browserify.js +++ b/grunt/config/browserify.js @@ -63,7 +63,7 @@ function simpleBannerify(src) { } // What is happening here??? -// I'm glad you asked. It became really to make our bundle splitting work. +// I'm glad you asked. It became really hard to make our bundle splitting work. // Everything is fine in node and when bundling with those packages, but when // using our pre-packaged files, the splitting didn't work. Specifically due to // the UMD wrappers defining their own require and creating their own encapsulated @@ -71,19 +71,38 @@ function simpleBannerify(src) { // be smart and looks for top-level requires (even when aliasing to a bundle), // but since we didn't have those, we couldn't require 'react' from 'react-dom'. // But we are already shimming in some modules that look for a global React -// variable. So we write a wrapper around the UMD bundle that browserify creates, -// and define a React variable that will require across Webpack-boundaries or fall -// back to the global, just like it would previously. +// variable. So we replace the UMD wrapper that browserify creates with out own, +// in 2 steps. +// 1. We swap out the browserify UMD with a plain function call. This ensures +// that the internal wrapper doesn't interact with the external state. By the +// time we're in the internal wrapper it doesn't matter what the external wrapper +// detected. Browserify insulates its CommonJS system inside closures so can just +// call that function and return it. +// 2. We put our own UMD wrapper around that fixed internal function, ensuring +// React is in scope. This outer wrapper is essentially the same UMD wrapper +// browserify would create, just handling the scope issue. +// Is this insane? Yes. +// Does it work? Yes. +// Should it go away ASAP? Yes. function wrapperify(src) { + var toReplace = + `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()}}`; + if (src.indexOf(toReplace) === -1) { + throw new Error('wrapperify failed to find code to replace'); + } + src = src.replace( + toReplace, + `function(f){return f()}` + ); return ` ;(function(f) { // CommonJS if (typeof exports === "object" && typeof module !== "undefined") { - f(require('react')); + module.exports = f(require('react')); // RequireJS } else if (typeof define === "function" && define.amd) { - require(['react'], f); + define(['react'], f); //