1. import semver from 'semver';
    
  2. 
    
  3. /**
    
  4.  * Take a version from the window query string and load a specific
    
  5.  * version of React.
    
  6.  *
    
  7.  * @example
    
  8.  * http://localhost:3000?version=15.4.1
    
  9.  * (Loads React 15.4.1)
    
  10.  */
    
  11. 
    
  12. function parseQuery(qstr) {
    
  13.   var query = {};
    
  14.   var a = qstr.slice(1).split('&');
    
  15. 
    
  16.   for (var i = 0; i < a.length; i++) {
    
  17.     var b = a[i].split('=');
    
  18.     query[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');
    
  19.   }
    
  20.   return query;
    
  21. }
    
  22. 
    
  23. function loadScript(src) {
    
  24.   let firstScript = document.getElementsByTagName('script')[0];
    
  25.   let scriptNode;
    
  26. 
    
  27.   return new Promise((resolve, reject) => {
    
  28.     scriptNode = document.createElement('script');
    
  29.     scriptNode.async = 1;
    
  30.     scriptNode.src = src;
    
  31. 
    
  32.     scriptNode.onload = () => resolve();
    
  33.     scriptNode.onerror = () => reject(new Error(`failed to load: ${src}`));
    
  34. 
    
  35.     firstScript.parentNode.insertBefore(scriptNode, firstScript);
    
  36.   });
    
  37. }
    
  38. 
    
  39. function getVersion() {
    
  40.   let query = parseQuery(window.location.search);
    
  41.   return query.version || 'local';
    
  42. }
    
  43. 
    
  44. export function reactPaths(version = getVersion()) {
    
  45.   let query = parseQuery(window.location.search);
    
  46.   let isProduction = query.production === 'true';
    
  47.   let environment = isProduction ? 'production.min' : 'development';
    
  48.   let reactPath = `react.${environment}.js`;
    
  49.   let reactDOMPath = `react-dom.${environment}.js`;
    
  50.   let reactDOMServerPath = `react-dom-server.browser.${environment}.js`;
    
  51.   let needsCreateElement = true;
    
  52.   let needsReactDOM = true;
    
  53. 
    
  54.   if (version !== 'local') {
    
  55.     const {major, minor, prerelease} = semver(version);
    
  56. 
    
  57.     if (major === 0) {
    
  58.       needsCreateElement = minor >= 12;
    
  59.       needsReactDOM = minor >= 14;
    
  60.     }
    
  61. 
    
  62.     const [preReleaseStage] = prerelease;
    
  63.     // The file structure was updated in 16. This wasn't the case for alphas.
    
  64.     // Load the old module location for anything less than 16 RC
    
  65.     if (major >= 16 && !(minor === 0 && preReleaseStage === 'alpha')) {
    
  66.       reactPath =
    
  67.         'https://unpkg.com/react@' +
    
  68.         version +
    
  69.         '/umd/react.' +
    
  70.         environment +
    
  71.         '.js';
    
  72.       reactDOMPath =
    
  73.         'https://unpkg.com/react-dom@' +
    
  74.         version +
    
  75.         '/umd/react-dom.' +
    
  76.         environment +
    
  77.         '.js';
    
  78.       reactDOMServerPath =
    
  79.         'https://unpkg.com/react-dom@' +
    
  80.         version +
    
  81.         '/umd/react-dom-server.browser' +
    
  82.         environment;
    
  83.     } else if (major > 0 || minor > 11) {
    
  84.       reactPath = 'https://unpkg.com/react@' + version + '/dist/react.js';
    
  85.       reactDOMPath =
    
  86.         'https://unpkg.com/react-dom@' + version + '/dist/react-dom.js';
    
  87.       reactDOMServerPath =
    
  88.         'https://unpkg.com/react-dom@' + version + '/dist/react-dom-server.js';
    
  89.     } else {
    
  90.       reactPath =
    
  91.         'https://cdnjs.cloudflare.com/ajax/libs/react/' + version + '/react.js';
    
  92.     }
    
  93.   }
    
  94. 
    
  95.   return {
    
  96.     reactPath,
    
  97.     reactDOMPath,
    
  98.     reactDOMServerPath,
    
  99.     needsCreateElement,
    
  100.     needsReactDOM,
    
  101.   };
    
  102. }
    
  103. 
    
  104. export default function loadReact() {
    
  105.   const {reactPath, reactDOMPath, needsReactDOM} = reactPaths();
    
  106. 
    
  107.   let request = loadScript(reactPath);
    
  108. 
    
  109.   if (needsReactDOM) {
    
  110.     request = request.then(() => loadScript(reactDOMPath));
    
  111.   } else {
    
  112.     // Aliasing React to ReactDOM for compatibility.
    
  113.     request = request.then(() => {
    
  114.       window.ReactDOM = window.React;
    
  115.     });
    
  116.   }
    
  117. 
    
  118.   return request;
    
  119. }