fix(core): do not recreate ReactDOM Root, fix React warning on hot reload (#10103)

This commit is contained in:
Sébastien Lorber 2024-05-03 15:54:49 +02:00 committed by GitHub
parent 4159b25dd1
commit 2d8281fc03
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 57 additions and 45 deletions

View File

@ -387,4 +387,5 @@ interface Window {
prefetch: (url: string) => false | Promise<void[]>;
preload: (url: string) => false | Promise<void[]>;
};
docusaurusRoot?: import('react-dom/client').Root;
}

View File

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import React from 'react';
import React, {startTransition} from 'react';
import ReactDOM, {type ErrorInfo} from 'react-dom/client';
import {BrowserRouter} from 'react-router-dom';
import {HelmetProvider} from 'react-helmet-async';
@ -46,21 +46,24 @@ if (ExecutionEnvironment.canUseDOM) {
};
const renderApp = () => {
if (window.docusaurusRoot) {
window.docusaurusRoot.render(app);
return;
}
if (hydrate) {
React.startTransition(() => {
ReactDOM.hydrateRoot(container, app, {
onRecoverableError,
});
window.docusaurusRoot = ReactDOM.hydrateRoot(container, app, {
onRecoverableError,
});
} else {
const root = ReactDOM.createRoot(container, {onRecoverableError});
React.startTransition(() => {
root.render(app);
});
root.render(app);
window.docusaurusRoot = root;
}
};
preload(window.location.pathname).then(renderApp);
preload(window.location.pathname).then(() => {
startTransition(renderApp);
});
// Webpack Hot Module Replacement API
if (module.hot) {

View File

@ -45,46 +45,55 @@ const getChunkNamesToLoad = (path: string): string[] =>
)
.flatMap(([, routeChunks]) => Object.values(flat(routeChunks)));
const docusaurus = {
prefetch(routePath: string): false | Promise<void[]> {
if (!canPrefetch(routePath)) {
return false;
}
fetched.add(routePath);
type Docusaurus = Window['docusaurus'];
// Find all webpack chunk names needed.
const matches = matchRoutes(routes, routePath);
const prefetch: Docusaurus['prefetch'] = (
routePath: string,
): false | Promise<void[]> => {
if (!canPrefetch(routePath)) {
return false;
}
fetched.add(routePath);
const chunkNamesNeeded = matches.flatMap((match) =>
getChunkNamesToLoad(match.route.path),
);
// Find all webpack chunk names needed.
const matches = matchRoutes(routes, routePath);
// Prefetch all webpack chunk assets file needed.
return Promise.all(
chunkNamesNeeded.map((chunkName) => {
// "__webpack_require__.gca" is injected by ChunkAssetPlugin. Pass it
// the name of the chunk you want to load and it will return its URL.
// eslint-disable-next-line camelcase
const chunkAsset = __webpack_require__.gca(chunkName);
const chunkNamesNeeded = matches.flatMap((match) =>
getChunkNamesToLoad(match.route.path),
);
// In some cases, webpack might decide to optimize further, leading to
// the chunk assets being merged to another chunk. In this case, we can
// safely filter it out and don't need to load it.
if (chunkAsset && !chunkAsset.includes('undefined')) {
return prefetchHelper(chunkAsset);
}
return Promise.resolve();
}),
);
},
// Prefetch all webpack chunk assets file needed.
return Promise.all(
chunkNamesNeeded.map((chunkName) => {
// "__webpack_require__.gca" is injected by ChunkAssetPlugin. Pass it
// the name of the chunk you want to load and it will return its URL.
// eslint-disable-next-line camelcase
const chunkAsset = __webpack_require__.gca(chunkName);
preload(routePath: string): false | Promise<void[]> {
if (!canPreload(routePath)) {
return false;
}
loaded.add(routePath);
return preloadHelper(routePath);
},
// In some cases, webpack might decide to optimize further, leading to
// the chunk assets being merged to another chunk. In this case, we can
// safely filter it out and don't need to load it.
if (chunkAsset && !chunkAsset.includes('undefined')) {
return prefetchHelper(chunkAsset);
}
return Promise.resolve();
}),
);
};
const preload: Docusaurus['preload'] = (
routePath: string,
): false | Promise<void[]> => {
if (!canPreload(routePath)) {
return false;
}
loaded.add(routePath);
return preloadHelper(routePath);
};
const docusaurus: Window['docusaurus'] = {
prefetch,
preload,
};
// This object is directly mounted onto window, better freeze it

View File

@ -67,7 +67,6 @@ datagit
Datagit
Datagit's
dedup
Déja
devto
dingers
Dmitry