astro
Version:
Astro is a modern site builder with web best practices, performance, and DX front-of-mind.
78 lines (77 loc) • 3.21 kB
JavaScript
import { DEFAULT_COMPONENTS } from "../core/routing/default.js";
import { routeIsRedirect } from "../core/routing/helpers.js";
import { VIRTUAL_PAGE_MODULE_ID } from "./const.js";
import { getVirtualModulePageName } from "./util.js";
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js";
export const VIRTUAL_PAGES_MODULE_ID = "virtual:astro:pages";
const VIRTUAL_PAGES_RESOLVED_MODULE_ID = "\0" + VIRTUAL_PAGES_MODULE_ID;
/**
* Filters routes for a specific build environment.
*
* Redirect target routes do not need special handling here: they already
* appear in the routes list with their own `prerender` flag and are
* included when it matches `isPrerender`. At SSR runtime, redirect
* responses are generated from route metadata alone (no component is
* loaded), so the target's component is never needed in the SSR page map.
*/
export function getRoutesForEnvironment(routes, isPrerender) {
const result = new Set();
for (const route of routes) {
if (route.prerender === isPrerender) {
result.add(route);
}
}
return result;
}
export function pluginPages({ routesList }) {
return {
name: "@astro/plugin-pages",
enforce: "post",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender;
},
resolveId: {
filter: { id: new RegExp(`^${VIRTUAL_PAGES_MODULE_ID}$`) },
handler() {
return VIRTUAL_PAGES_RESOLVED_MODULE_ID;
}
},
load: {
filter: { id: new RegExp(`^${VIRTUAL_PAGES_RESOLVED_MODULE_ID}$`) },
async handler() {
const imports = [];
const pageMap = [];
let i = 0;
// Filter routes based on the build environment to reduce memory usage.
// Each environment only builds the pages it needs:
// - SSR environment: builds only on-demand rendered pages (prerender: false)
// - Prerender environment: builds only static pages (prerender: true)
// - Other environments (e.g. client): get all routes
const envName = this.environment.name;
const isSSR = envName === ASTRO_VITE_ENVIRONMENT_NAMES.ssr;
const isPrerender = envName === ASTRO_VITE_ENVIRONMENT_NAMES.prerender;
const routes = isSSR || isPrerender ? getRoutesForEnvironment(routesList.routes, isPrerender) : new Set(routesList.routes);
for (const route of routes) {
if (routeIsRedirect(route)) {
continue;
}
// Skip default components (404, server islands, etc.)
if (DEFAULT_COMPONENTS.some((component) => route.component === component)) {
continue;
}
const virtualModuleName = getVirtualModulePageName(VIRTUAL_PAGE_MODULE_ID, route.component);
const module = await this.resolve(virtualModuleName);
if (module) {
const variable = `_page${i}`;
// use the non-resolved ID to resolve correctly the virtual module
imports.push(`const ${variable} = () => import("${virtualModuleName}");`);
pageMap.push(`[${JSON.stringify(route.component)}, ${variable}]`);
i++;
}
}
const pageMapCode = `const pageMap = new Map([\n ${pageMap.join(",\n ")}\n]);\n\nexport { pageMap };`;
return { code: [...imports, pageMapCode].join("\n") };
}
}
};
}