vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
88 lines (87 loc) • 4.07 kB
JavaScript
import '../../../assertEnvServer.js';
export { retrievePageAssetsDev };
export { setGetClientEntrySrcDev };
import { styleFileRE } from '../../../../utils/styleFileRE.js';
import { assert } from '../../../../utils/assert.js';
import { getGlobalObject } from '../../../../utils/getGlobalObject.js';
import { parseVirtualFileId } from '../../../../shared-server-node/virtualFileId.js';
const globalObject = getGlobalObject('getPageAssets/retrievePageAssetsDev.ts', {
// We cannot define getClientEntrySrcDev() in this file because it depends on utils/requireResolve.ts which isn't available in production
getClientEntrySrcDev: null,
});
async function retrievePageAssetsDev(viteDevServer, clientDependencies, clientEntries) {
const clientEntriesSrc = clientEntries.map((clientEntry) => globalObject.getClientEntrySrcDev(clientEntry, viteDevServer));
const assetUrls = await getAssetUrls(clientDependencies, viteDevServer);
return { clientEntriesSrc, assetUrls };
}
function setGetClientEntrySrcDev(getClientEntrySrcDev) {
globalObject.getClientEntrySrcDev = getClientEntrySrcDev;
}
async function getAssetUrls(clientDependencies, viteDevServer) {
const assetUrls = new Set();
await Promise.all(clientDependencies.map(async ({ id }) => {
if (id.startsWith('@@vike'))
return; // vike doesn't have any CSS
assert(id);
const virtualFile = parseVirtualFileId(id);
assert(!virtualFile || virtualFile.type !== 'global-entry');
const { moduleGraph } = viteDevServer;
const [_, graphId] = await moduleGraph.resolveUrl(id);
assert(graphId, { id });
const mod = moduleGraph.getModuleById(graphId);
if (!mod) {
/* Not sure when the assertion fails. So let's just remove it for now.
* - https://github.com/vikejs/vike/issues/391
// `moduleGraph` is missing `.page.client.js` files on the very first render
assert(id.includes('.page.client.'), { id })
*/
return;
}
assert(mod, { id });
collectCss(mod, assetUrls, new Set());
}));
return Array.from(assetUrls);
}
// Collect the CSS to be injected to the HTML to avoid FLOUC
// - We only collect the root import: https://github.com/vikejs/vike/issues/400
function collectCss(mod, styleUrls, visitedModules, importer) {
assert(mod);
if (!mod.url)
return;
if (visitedModules.has(mod.url))
return;
visitedModules.add(mod.url);
const virtualFile = parseVirtualFileId(mod.id || mod.url);
if (virtualFile && virtualFile.type === 'global-entry')
return; // virtual:vike:global-entry:server dependency list includes all pages
if (isStyle(mod) && (!importer || !isStyle(importer))) {
if (mod.url.startsWith('/')) {
styleUrls.add(mod.url);
}
else if (mod.url.startsWith('\0')) {
// Virtual modules
// - https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention
// - I believe some Vite plugins don't respect the \0 virtual module convention. What should we do then?
// - https://github.com/vikejs/vike/issues/1327
// - https://github.com/vikejs/vike/commit/3f7b9916dddc84e29e2c20d2b0df7211b6f1acbd
// - https://github.com/vikejs/vike/issues/479#issuecomment-1870043943
styleUrls.add(`/@id/__x00__${mod.url.substring(1)}`);
}
else {
// Is this useful? Maybe for virtual modules that don't respect the \0 virtual module convention?
styleUrls.add(`/@id/${mod.url}`);
}
}
mod.importedModules.forEach((dep) => {
collectCss(dep, styleUrls, visitedModules, mod);
});
}
function isStyle(mod) {
return (
// CSS-in-JS libraries such as [wyw-in-js](https://github.com/vikejs/vike/issues/2039)
mod.type === 'css' ||
// .css, .less, ...
styleFileRE.test(mod.url) ||
// CSS of .vue files
(mod.id && /\?vue&type=style/.test(mod.id)));
}