Repository URL to install this package:
|
Version:
0.0.7 ▾
|
/**
* problem: code on each page is too big, is has everything for every page
* solution: code split
*
* problem:
* - the server needs to send the right files for that page
* - right now it is sending every file as a <script>
* - this does not happen without ssr
* - client side part is working (since webpack loads it)
* - sending every file results in code for all pages getting loaded...
* solution:
* - the following...
*
* 0. example page file requirement
* - /home
* -> every page loads the index.<version>.js file
* -> this page needs the `Home.page<version>.js` file
* -> this page (may) need `Vendor~Home-PDP<version>.js` file
*
* 1. go through routes
* - need to find the specific route definition for a given url
*
* 2. the component for that route has the code split file
* - how to extract the meta from the import() ?
* - how to use the variable name if it is uglified
* - any other changes require changing all route definitions (easy, but more KT)
*
* 3. the way other places handle this is with the babel plugin & server reset
* - that way, you will only have `loaded` the files you are using
* - this is slower because we have to load files from disk on each (uncached) page load
*
* 4. the way we currently load is by using the manifest json file
* - this is generated with the webpack-manifest-plugin
* - this contains all of the js files
* - we add them all as scripts
*
* 5. we have no definition of `auth` pages, we should
* - this is needed for amp
* - these pages can be slower since the user is signed in and has loaded many pages already
*
* 6. on some pages, the shared resources are split into a common / shared file
* - example: Home uses Gallery, PDP uses gallery
* - result: `Vendor~Home-PDP.js` (containing the gallery)
*
* 7. since this works on the client side
* - maybe there is a way to get the information webpack uses...
* ...to load these chunks and then extract it here...
* ...but webpack is doing it at runtime based on the render...
* ...we need to do it statically...
* ...or extract it from webpack after such a render...
* ...and it may not even have such code for the server by default...
*/
import { oneRouter } from '@skava/router';
import { isEmpty } from 'exotic';
// import routeList from 'src/bootstrap/routes'
import { routeList } from 'src/bootstrap/routing';
import { matchPath } from 'react-router';
import { logger } from '../../log';
/**
* @todo 1. this will load productlist on product page
* @todo 2. this will load `newhome` on home...
* @todo 2. not sure what will be loading :fallback - maybe client only?
*/
function toUnsafePath(path) {
if (!path) {
return '';
}
else if (path.includes('category/')) {
return 'productlist';
}
else if (path === '/') {
return 'home';
}
else if (path.includes('/')) {
return path.split('/').shift();
}
else if (path.includes('?')) {
return path.split('?').shift();
}
else {
return path;
}
}
/** @todo should only used on ssr... */
export function findAssetsForRoute(clientEntryAssets) {
const found = routeList
.map(route => {
const path = route.path;
// @note - updating react-router made this function throw on undefined
const match = oneRouter.pathname && path && matchPath(oneRouter.pathname, { path });
// console.log('__findRoute__', { match, path, route })
const __UNSAFE_PATH__ = toUnsafePath(path);
return match && __UNSAFE_PATH__.toLowerCase();
})
.filter(Boolean)
.shift();
// const shouldPathMatchBeIgnored = (path: string) => !path.toLowerCase().includes('newhome')
const shouldPathMatchBeAllowed = (path) => true;
const toMatchablePath = (path) => {
const withoutClient = path.includes('/client/') ? path.replace('/client/', '') : path;
return withoutClient.toLowerCase();
};
const doesPathMatchFound = (path) => {
const jsPath = toMatchablePath(path);
const didPathMatch = jsPath.includes(found) ||
jsPath.includes('index') ||
jsPath.includes('workbox') ||
jsPath.includes('worker');
// @todo use pino
const msg = `[server][ssr] doesPathMatchFound?
jsPath: ${jsPath}
found: ${found}
didPathMatch: ${didPathMatch}
`.replace(/ /gm, '');
logger.info(msg);
return didPathMatch;
};
const jsListMatching = clientEntryAssets.jsList
.filter(Boolean)
.filter(doesPathMatchFound)
.filter(shouldPathMatchBeAllowed);
let assetList;
if (isEmpty(jsListMatching)) {
assetList = clientEntryAssets.jsList;
}
else {
assetList = jsListMatching;
}
return assetList;
}
//# sourceMappingURL=findAssetsForRoute.js.map