From b1007905a75f5c60d52337e3957429592bf74987 Mon Sep 17 00:00:00 2001 From: Josh Story Date: Fri, 12 Apr 2024 15:14:05 -0700 Subject: [PATCH] Updates the dom fixture to load react 19 and later with esm.sh. This fixture looks to be in a state of significant bitrot. I'm not going to bother addressing these issues here but at the very least we can now render React 19 without UMD using this fixture --- fixtures/dom/README.md | 4 +- fixtures/dom/package.json | 2 +- fixtures/dom/src/index.js | 16 ++++-- fixtures/dom/src/react-loader.js | 85 +++++++++++++++++++++++++++----- netlify.toml | 2 +- package.json | 2 +- 6 files changed, 89 insertions(+), 22 deletions(-) diff --git a/fixtures/dom/README.md b/fixtures/dom/README.md index 8aae7b0c22d85..80e92b1626283 100644 --- a/fixtures/dom/README.md +++ b/fixtures/dom/README.md @@ -10,8 +10,8 @@ of the React project. Then: ``` cd fixtures/dom yarn -yarn start +yarn dev ``` -The `start` command runs a script that copies over the local build of react into +The `dev` command runs a script that copies over the local build of react into the public directory. diff --git a/fixtures/dom/package.json b/fixtures/dom/package.json index c5bb0326c3175..5f3333fff3b8b 100644 --- a/fixtures/dom/package.json +++ b/fixtures/dom/package.json @@ -20,7 +20,7 @@ }, "scripts": { "dev": "react-scripts start", - "predev": "cp ../../build/oss-stable/scheduler/umd/scheduler-unstable_mock.development.js ../../build/oss-stable/scheduler/umd/scheduler-unstable_mock.production.min.js ../../build/oss-stable/react/umd/react.development.js ../../build/oss-stable/react-dom/umd/react-dom.development.js ../../build/oss-stable/react/umd/react.production.min.js ../../build/oss-stable/react-dom/umd/react-dom.production.min.js ../../build/oss-stable/react-dom/umd/react-dom-server.browser.development.js ../../build/oss-stable/react-dom/umd/react-dom-server.browser.production.min.js ../../build/oss-stable/react-dom/umd/react-dom-test-utils.development.js ../../build/oss-stable/react-dom/umd/react-dom-test-utils.production.min.js public/ && cp -a ../../build/oss-stable/. node_modules", + "predev": "cp -a ../../build/oss-stable/. node_modules", "build": "react-scripts build && cp build/index.html build/200.html", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" diff --git a/fixtures/dom/src/index.js b/fixtures/dom/src/index.js index 5c76e06d1bca2..d5f37f315fe4a 100644 --- a/fixtures/dom/src/index.js +++ b/fixtures/dom/src/index.js @@ -6,8 +6,16 @@ loadReact() .then(App => { const {React, ReactDOM} = window; - ReactDOM.render( - React.createElement(App.default), - document.getElementById('root') - ); + if (typeof window.ReactDOMClient !== 'undefined') { + // we are in a React that only supports modern roots + + ReactDOM.createRoot(document.getElementById('root')).render( + React.createElement(App.default) + ); + } else { + ReactDOM.render( + React.createElement(App.default), + document.getElementById('root') + ); + } }); diff --git a/fixtures/dom/src/react-loader.js b/fixtures/dom/src/react-loader.js index b2a37c49e5ae2..cbfa96fcce5a9 100644 --- a/fixtures/dom/src/react-loader.js +++ b/fixtures/dom/src/react-loader.js @@ -36,6 +36,33 @@ function loadScript(src) { }); } +function loadModules(SymbolSrcPairs) { + let firstScript = document.getElementsByTagName('script')[0]; + + let imports = ''; + SymbolSrcPairs.map(([symbol, src]) => { + imports += `import ${symbol} from "${src}";\n`; + imports += `window.${symbol} = ${symbol};\n`; + }); + + return new Promise((resolve, reject) => { + const timeout = setTimeout( + () => reject(new Error('Timed out loading react modules over esm')), + 5000 + ); + window.__loaded = () => { + clearTimeout(timeout); + resolve(); + }; + + const moduleScript = document.createElement('script'); + moduleScript.type = 'module'; + moduleScript.textContent = imports + 'window.__loaded();'; + + firstScript.parentNode.insertBefore(moduleScript, firstScript); + }); +} + function getVersion() { let query = parseQuery(window.location.search); return query.version || 'local'; @@ -47,12 +74,15 @@ export function reactPaths(version = getVersion()) { let environment = isProduction ? 'production.min' : 'development'; let reactPath = `react.${environment}.js`; let reactDOMPath = `react-dom.${environment}.js`; + let reactDOMClientPath = `react-dom.${environment}.js`; let reactDOMServerPath = `react-dom-server.browser.${environment}.js`; let needsCreateElement = true; let needsReactDOM = true; + let usingModules = false; if (version !== 'local') { const {major, minor, prerelease} = semver(version); + console.log('semver', semver(version)); if (major === 0) { needsCreateElement = minor >= 12; @@ -62,7 +92,16 @@ export function reactPaths(version = getVersion()) { 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')) { + if (major >= 19) { + usingModules = true; + const devQuery = environment === 'development' ? '?dev' : ''; + reactPath = 'https://esm.sh/react@' + version + '/' + devQuery; + reactDOMPath = 'https://esm.sh/react-dom@' + version + '/' + devQuery; + reactDOMClientPath = + 'https://esm.sh/react-dom@' + version + '/client' + devQuery; + reactDOMServerPath = + 'https://esm.sh/react-dom@' + version + '/server.browser' + devQuery; + } else if (major >= 16 && !(minor === 0 && preReleaseStage === 'alpha')) { reactPath = 'https://unpkg.com/react@' + version + @@ -90,30 +129,50 @@ export function reactPaths(version = getVersion()) { reactPath = 'https://cdnjs.cloudflare.com/ajax/libs/react/' + version + '/react.js'; } + } else { + throw new Error( + 'This fixture no longer works with local versions. Provide a version query parameter that matches a version published to npm to use the fixture.' + ); } return { reactPath, reactDOMPath, + reactDOMClientPath, reactDOMServerPath, needsCreateElement, needsReactDOM, + usingModules, }; } export default function loadReact() { - const {reactPath, reactDOMPath, needsReactDOM} = reactPaths(); - - let request = loadScript(reactPath); - - if (needsReactDOM) { - request = request.then(() => loadScript(reactDOMPath)); + console.log('reactPaths', reactPaths()); + const { + reactPath, + reactDOMPath, + reactDOMClientPath, + needsReactDOM, + usingModules, + } = reactPaths(); + + if (usingModules) { + return loadModules([ + ['React', reactPath], + ['ReactDOM', reactDOMPath], + ['ReactDOMClient', reactDOMClientPath], + ]); } else { - // Aliasing React to ReactDOM for compatibility. - request = request.then(() => { - window.ReactDOM = window.React; - }); - } + let request = loadScript(reactPath, usingModules); - return request; + if (needsReactDOM) { + request = request.then(() => loadScript(reactDOMPath, usingModules)); + } else { + // Aliasing React to ReactDOM for compatibility. + request = request.then(() => { + window.ReactDOM = window.React; + }); + } + return request; + } } diff --git a/netlify.toml b/netlify.toml index 76443cdd50285..9920f41194895 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,7 +1,7 @@ [build] base = "" publish = "fixtures/dom/build" - command = "yarn build --type=UMD_DEV && cd fixtures/dom/ && yarn && yarn predev && yarn build" + command = "yarn build --type=UMD_DEV && cd fixtures/dom/ && yarn && yarn build" [[redirects]] from = "/*" diff --git a/package.json b/package.json index 785bbfe63113b..1c42047b86de8 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,7 @@ "test-www": "node ./scripts/jest/jest-cli.js --release-channel=www-modern", "test-classic": "node ./scripts/jest/jest-cli.js --release-channel=www-classic", "test-build-devtools": "node ./scripts/jest/jest-cli.js --build --project devtools --release-channel=experimental", - "test-dom-fixture": "cd fixtures/dom && yarn && yarn predev && yarn test", + "test-dom-fixture": "cd fixtures/dom && yarn && yarn test", "flow": "node ./scripts/tasks/flow.js", "flow-ci": "node ./scripts/tasks/flow-ci.js", "prettier": "node ./scripts/prettier/index.js write-changed",