astro
Version:
Astro is a modern site builder with web best practices, performance, and DX front-of-mind.
79 lines (78 loc) • 3.52 kB
JavaScript
import { removeQueryString } from "../../path.js";
import { getTopLevelPageModuleInfos } from "../graph.js";
import { getPageDataByViteID, trackClientOnlyPageDatas, trackHydratedComponentPageDatas, trackScriptPageDatas } from "../internal.js";
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
export function pluginAnalyzer(internals) {
return {
name: "@astro/rolldown-plugin-astro-analyzer",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender;
},
async generateBundle() {
const ids = this.getModuleIds();
for (const id of ids) {
const info = this.getModuleInfo(id);
if (!info?.meta?.astro) continue;
const astro = info.meta.astro;
if (astro.hydratedComponents.length) {
const hydratedComponents = [];
for (const c of astro.hydratedComponents) {
const rid = c.resolvedPath ? decodeURI(c.resolvedPath) : c.specifier;
if (internals.discoveredHydratedComponents.has(rid)) {
const exportNames = internals.discoveredHydratedComponents.get(rid);
exportNames?.push(c.exportName);
} else {
internals.discoveredHydratedComponents.set(rid, [c.exportName]);
}
hydratedComponents.push(rid);
}
// Track which pages use each hydrated component
for (const pageInfo of getTopLevelPageModuleInfos(id, this)) {
const newPageData = getPageDataByViteID(internals, pageInfo.id);
if (!newPageData) continue;
trackHydratedComponentPageDatas(internals, newPageData, hydratedComponents);
}
}
if (astro.clientOnlyComponents.length) {
const clientOnlys = [];
for (const c of astro.clientOnlyComponents) {
const cid = c.resolvedPath ? decodeURI(c.resolvedPath) : c.specifier;
if (internals.discoveredClientOnlyComponents.has(cid)) {
const exportNames = internals.discoveredClientOnlyComponents.get(cid);
exportNames?.push(c.exportName);
} else {
internals.discoveredClientOnlyComponents.set(cid, [c.exportName]);
}
clientOnlys.push(cid);
const resolvedId = await this.resolve(c.specifier, id);
if (resolvedId) {
clientOnlys.push(resolvedId.id);
}
}
for (const pageInfo of getTopLevelPageModuleInfos(id, this)) {
const newPageData = getPageDataByViteID(internals, pageInfo.id);
if (!newPageData) continue;
trackClientOnlyPageDatas(internals, newPageData, clientOnlys);
}
}
// When directly rendering scripts, we don't need to group them together when bundling,
// each script module is its own entrypoint, so we directly assign each script modules to
// `discoveredScripts` here, which will eventually be passed as inputs of the client build.
if (astro.scripts.length) {
const filename = removeQueryString(id.replace("/@fs", ""));
const scriptIds = astro.scripts.map((_, i) => `${filename}?astro&type=script&index=${i}&lang.ts`);
// Assign as entrypoints for the client bundle
for (const scriptId of scriptIds) {
internals.discoveredScripts.add(scriptId);
}
// The script may import CSS, so we also have to track the pages that use this script
for (const pageInfo of getTopLevelPageModuleInfos(id, this)) {
const newPageData = getPageDataByViteID(internals, pageInfo.id);
if (!newPageData) continue;
trackScriptPageDatas(internals, newPageData, scriptIds);
}
}
}
}
};
}