mirror of
https://github.com/facebook/react.git
synced 2026-02-26 18:58:05 +00:00
* Hydration Fixture: Only load ReactDOMServer if it exists Fixes an issue where the hydration fixture would try to load in ReactDOMServer below version 14. In version 13, string markup methods exist on the React namespace. * DOM Fixtures: Use class component for App.js This was breaking React 0.13.0. * Hydration Fixture: better findDOMNode compatibility This commit fixes an issue where the Hydration DOM fixture was unusable in React 0.13.0 or lower because of newer API usage. It fixes that by avoiding the use of refs to get the textarea reference in the code editor component, using various versions of findDOMNode as required. * Hydration Fixture: Do not show dropdown for single-line errors If an error showed for the hydration fixture, a detail element was used even if no additional lines could display. In that case, this commit changes the component such that it returns a div. * Deeper React version support for hydration fixture This commit adds support for versions 0.4.0 of React and higher for the hydration fixture. The DOM test fixtures themselves do not support down to React 0.4.0, which would be exhaustive. Instead, the Hydration fixture can pick a version to use for its own purposes. By default, this is the version of React used by the fixtures. In the process of doing this, I had to make some updates to the renderer.html document associated with the hydration fixture, and I've added some comments to better document the history of API changes.
120 lines
3.2 KiB
JavaScript
120 lines
3.2 KiB
JavaScript
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.substr(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;
|
|
}
|