import semver from 'semver';
/**
* Take a version from the window query string and load a specific
* version of React.
*
* @example
* http://localhost:3000?version=15.4.1
* (Loads React 15.4.1)
*/
function parseQuery(qstr) {
var query = {};
var a = qstr.slice(1).split('&');
for (var i = 0; i < a.length; i++) {
var b = a[i].split('=');
query[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');
}
return query;
}
function loadScript(src) {
let firstScript = document.getElementsByTagName('script')[0];
let scriptNode;
return new Promise((resolve, reject) => {
scriptNode = document.createElement('script');
scriptNode.async = 1;
scriptNode.src = src;
scriptNode.onload = () => resolve();
scriptNode.onerror = () => reject(new Error(`failed to load: ${src}`));
firstScript.parentNode.insertBefore(scriptNode, firstScript);
});
}
function getVersion() {
let query = parseQuery(window.location.search);
return query.version || 'local';
}
export function reactPaths(version = getVersion()) {
let query = parseQuery(window.location.search);
let isProduction = query.production === 'true';
let environment = isProduction ? 'production.min' : 'development';
let reactPath = `react.${environment}.js`;
let reactDOMPath = `react-dom.${environment}.js`;
let reactDOMServerPath = `react-dom-server.browser.${environment}.js`;
let needsCreateElement = true;
let needsReactDOM = true;
if (version !== 'local') {
const {major, minor, prerelease} = semver(version);
if (major === 0) {
needsCreateElement = minor >= 12;
needsReactDOM = minor >= 14;
}
const [preReleaseStage] = prerelease;
// The file structure was updated in 16. This wasn't the case for alphas.
// Load the old module location for anything less than 16 RC
if (major >= 16 && !(minor === 0 && preReleaseStage === 'alpha')) {
reactPath =
'https://unpkg.com/react@' +
version +
'/umd/react.' +
environment +
'.js';
reactDOMPath =
'https://unpkg.com/react-dom@' +
version +
'/umd/react-dom.' +
environment +
'.js';
reactDOMServerPath =
'https://unpkg.com/react-dom@' +
version +
'/umd/react-dom-server.browser' +
environment;
} else if (major > 0 || minor > 11) {
reactPath = 'https://unpkg.com/react@' + version + '/dist/react.js';
reactDOMPath =
'https://unpkg.com/react-dom@' + version + '/dist/react-dom.js';
reactDOMServerPath =
'https://unpkg.com/react-dom@' + version + '/dist/react-dom-server.js';
} else {
reactPath =
'https://cdnjs.cloudflare.com/ajax/libs/react/' + version + '/react.js';
}
}
return {
reactPath,
reactDOMPath,
reactDOMServerPath,
needsCreateElement,
needsReactDOM,
};
}
export default function loadReact() {
const {reactPath, reactDOMPath, needsReactDOM} = reactPaths();
let request = loadScript(reactPath);
if (needsReactDOM) {
request = request.then(() => loadScript(reactDOMPath));
} else {
// Aliasing React to ReactDOM for compatibility.
request = request.then(() => {
window.ReactDOM = window.React;
});
}
return request;
}