UNPKG

@docusaurus/core

Version:

Easy to Maintain Open Source Documentation Websites

63 lines (62 loc) 2.65 kB
/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import { matchRoutes } from 'react-router-config'; import routesChunkNames from '@generated/routesChunkNames'; import routes from '@generated/routes'; import prefetchHelper from './prefetch'; import preloadHelper from './preload'; import flat from './flat'; const fetched = new Set(); const loaded = new Set(); // If user is on slow or constrained connection. const isSlowConnection = () => navigator.connection?.effectiveType.includes('2g') || navigator.connection?.saveData; const canPrefetch = (routePath) => !isSlowConnection() && !loaded.has(routePath) && !fetched.has(routePath); const canPreload = (routePath) => !isSlowConnection() && !loaded.has(routePath); const getChunkNamesToLoad = (path) => Object.entries(routesChunkNames) .filter( // Remove the last part containing the route hash // input: /blog/2018/12/14/Happy-First-Birthday-Slash-fe9 // output: /blog/2018/12/14/Happy-First-Birthday-Slash ([routeNameWithHash]) => routeNameWithHash.replace(/-[^-]+$/, '') === path) .flatMap(([, routeChunks]) => Object.values(flat(routeChunks))); const prefetch = (routePath) => { if (!canPrefetch(routePath)) { return false; } fetched.add(routePath); // Find all webpack chunk names needed. const matches = matchRoutes(routes, routePath); const chunkNamesNeeded = matches.flatMap((match) => getChunkNamesToLoad(match.route.path)); // 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); // 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 = (routePath) => { if (!canPreload(routePath)) { return false; } loaded.add(routePath); return preloadHelper(routePath); }; const docusaurus = { prefetch, preload, }; // This object is directly mounted onto window, better freeze it export default Object.freeze(docusaurus);