Add first business article and article layout

This commit is contained in:
2026-05-21 12:14:46 -05:00
parent 200e14e2e9
commit 4735704c6f
9617 changed files with 988627 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
import type { Rollup } from 'vite';
export declare function addRollupInput(inputOptions: Rollup.InputOptions, newInputs: string[]): Rollup.InputOptions;

37
node_modules/astro/dist/core/build/add-rollup-input.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
function fromEntries(entries) {
const obj = {};
for (const [k, v] of entries) {
obj[k] = v;
}
return obj;
}
function addRollupInput(inputOptions, newInputs) {
if (!inputOptions.input) {
return { ...inputOptions, input: newInputs };
}
if (typeof inputOptions.input === "string") {
return {
...inputOptions,
input: [inputOptions.input, ...newInputs]
};
}
if (Array.isArray(inputOptions.input)) {
return {
...inputOptions,
input: [...inputOptions.input, ...newInputs]
};
}
if (typeof inputOptions.input === "object") {
return {
...inputOptions,
input: {
...inputOptions.input,
...fromEntries(newInputs.map((i) => [i.split("/").slice(-1)[0].split(".")[0], i]))
}
};
}
throw new Error(`Unknown rollup input type. Supported inputs are string, array and object.`);
}
export {
addRollupInput
};

20
node_modules/astro/dist/core/build/app.d.ts generated vendored Normal file
View File

@@ -0,0 +1,20 @@
import { BaseApp, type RenderErrorOptions } from '../app/entrypoints/index.js';
import type { SSRManifest } from '../app/types.js';
import type { BuildInternals } from './internal.js';
import { BuildPipeline } from './pipeline.js';
import type { StaticBuildOptions } from './types.js';
import type { CreateRenderContext, RenderContext } from '../render-context.js';
import type { LogRequestPayload } from '../app/base.js';
import type { PoolStatsReport } from '../../runtime/server/render/queue/pool.js';
export declare class BuildApp extends BaseApp<BuildPipeline> {
createPipeline(_streaming: boolean, manifest: SSRManifest, ..._args: any[]): BuildPipeline;
createRenderContext(payload: CreateRenderContext): Promise<RenderContext>;
isDev(): boolean;
setInternals(internals: BuildInternals): void;
setOptions(options: StaticBuildOptions): void;
getOptions(): StaticBuildOptions;
getSettings(): import("../../types/astro.js").AstroSettings;
renderError(request: Request, options: RenderErrorOptions): Promise<Response>;
getQueueStats(): PoolStatsReport | undefined;
logRequest(_options: LogRequestPayload): void;
}

54
node_modules/astro/dist/core/build/app.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
import { BaseApp } from "../app/entrypoints/index.js";
import { BuildPipeline } from "./pipeline.js";
class BuildApp extends BaseApp {
createPipeline(_streaming, manifest, ..._args) {
return BuildPipeline.create({
manifest
});
}
async createRenderContext(payload) {
return await super.createRenderContext({
...payload
});
}
isDev() {
return true;
}
setInternals(internals) {
this.pipeline.setInternals(internals);
}
setOptions(options) {
this.pipeline.setOptions(options);
this.logger.setDestination(options.logger.options.destination);
this.resetAdapterLogger();
}
getOptions() {
return this.pipeline.getOptions();
}
getSettings() {
return this.pipeline.getSettings();
}
async renderError(request, options) {
if (options.status === 500) {
if (options.response) {
return options.response;
}
throw options.error;
} else {
return super.renderError(request, {
...options,
prerenderedErrorPageFetch: void 0
});
}
}
getQueueStats() {
if (this.pipeline.nodePool) {
return this.pipeline.nodePool.getStats();
}
}
logRequest(_options) {
}
}
export {
BuildApp
};

11
node_modules/astro/dist/core/build/common.d.ts generated vendored Normal file
View File

@@ -0,0 +1,11 @@
import type { AstroSettings } from '../../types/astro.js';
import type { AstroConfig } from '../../types/public/config.js';
import type { RouteData } from '../../types/public/internal.js';
export declare function getOutFolder(astroSettings: AstroSettings, pathname: string, routeData: RouteData): URL;
export declare function getOutFile(buildFormat: NonNullable<AstroConfig['build']>['format'], outFolder: URL, pathname: string, routeData: RouteData): URL;
/**
* Ensures the `outDir` is within `process.cwd()`. If not it will fall back to `<cwd>/.astro`.
* This is used for static `ssrBuild` so the output can access node_modules when we import
* the output files. A hardcoded fallback dir is fine as it would be cleaned up after build.
*/
export declare function getOutDirWithinCwd(outDir: URL): URL;

87
node_modules/astro/dist/core/build/common.js generated vendored Normal file
View File

@@ -0,0 +1,87 @@
import npath from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
import { appendForwardSlash } from "../../core/path.js";
const STATUS_CODE_PAGES = /* @__PURE__ */ new Set(["/404", "/500"]);
const FALLBACK_OUT_DIR_NAME = "./.astro/";
function getOutRoot(astroSettings) {
const preserveStructure = astroSettings.adapter?.adapterFeatures?.preserveBuildClientDir;
if (astroSettings.buildOutput === "static" && !preserveStructure) {
return new URL("./", astroSettings.config.outDir);
} else {
return new URL("./", astroSettings.config.build.client);
}
}
function getOutFolder(astroSettings, pathname, routeData) {
const outRoot = getOutRoot(astroSettings);
const routeType = routeData.type;
switch (routeType) {
case "endpoint":
return new URL("." + appendForwardSlash(npath.dirname(pathname)), outRoot);
case "fallback":
case "page":
case "redirect":
switch (astroSettings.config.build.format) {
case "directory": {
if (STATUS_CODE_PAGES.has(pathname)) {
return new URL("." + appendForwardSlash(npath.dirname(pathname)), outRoot);
}
return new URL("." + appendForwardSlash(pathname), outRoot);
}
case "file": {
const d = pathname === "" ? pathname : npath.dirname(pathname);
return new URL("." + appendForwardSlash(d), outRoot);
}
case "preserve": {
let dir;
if (pathname === "" || routeData.isIndex) {
dir = pathname;
} else {
dir = npath.dirname(pathname);
}
return new URL("." + appendForwardSlash(dir), outRoot);
}
}
}
}
function getOutFile(buildFormat, outFolder, pathname, routeData) {
const routeType = routeData.type;
switch (routeType) {
case "endpoint":
return new URL(npath.basename(pathname), outFolder);
case "page":
case "fallback":
case "redirect":
switch (buildFormat) {
case "directory": {
if (STATUS_CODE_PAGES.has(pathname)) {
const baseName = npath.basename(pathname);
return new URL("./" + (baseName || "index") + ".html", outFolder);
}
return new URL("./index.html", outFolder);
}
case "file": {
const baseName = npath.basename(pathname);
return new URL("./" + (baseName || "index") + ".html", outFolder);
}
case "preserve": {
let baseName = npath.basename(pathname);
if (!baseName || routeData.isIndex) {
baseName = "index";
}
return new URL(`./${baseName}.html`, outFolder);
}
}
}
}
function getOutDirWithinCwd(outDir) {
if (fileURLToPath(outDir).startsWith(process.cwd())) {
return outDir;
} else {
return new URL(FALLBACK_OUT_DIR_NAME, pathToFileURL(process.cwd() + npath.sep));
}
}
export {
getOutDirWithinCwd,
getOutFile,
getOutFolder
};

1
node_modules/astro/dist/core/build/consts.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export declare const CHUNKS_PATH = "chunks/";

4
node_modules/astro/dist/core/build/consts.js generated vendored Normal file
View File

@@ -0,0 +1,4 @@
const CHUNKS_PATH = "chunks/";
export {
CHUNKS_PATH
};

View File

@@ -0,0 +1,22 @@
import type { AstroPrerenderer } from '../../types/public/integrations.js';
import type { BuildInternals } from './internal.js';
import type { StaticBuildOptions } from './types.js';
import type { BuildApp } from './app.js';
interface DefaultPrerendererOptions {
internals: BuildInternals;
options: StaticBuildOptions;
prerenderOutputDir: URL;
}
/**
* Default prerenderer with access to the BuildApp for assets generation.
*/
export interface DefaultPrerenderer extends AstroPrerenderer {
/** The BuildApp instance, available after setup() is called */
app?: BuildApp;
}
/**
* Creates the default prerenderer that uses Node to import the bundle and render pages.
* This is used when no custom prerenderer is set by an adapter.
*/
export declare function createDefaultPrerenderer({ internals, options, prerenderOutputDir, }: DefaultPrerendererOptions): DefaultPrerenderer;
export {};

View File

@@ -0,0 +1,37 @@
import { StaticPaths } from "../../runtime/prerender/static-paths.js";
function createDefaultPrerenderer({
internals,
options,
prerenderOutputDir
}) {
const prerenderer = {
name: "astro:default",
async setup() {
const prerenderEntryFileName = internals.prerenderEntryFileName;
if (!prerenderEntryFileName) {
throw new Error(
`Prerender entry filename not found in build internals. This is likely a bug in Astro.`
);
}
const prerenderEntryUrl = new URL(prerenderEntryFileName, prerenderOutputDir);
const prerenderEntry = await import(prerenderEntryUrl.toString());
const app = prerenderEntry.app;
app.setInternals(internals);
app.setOptions(options);
prerenderer.app = app;
},
async getStaticPaths() {
const staticPaths = new StaticPaths(prerenderer.app);
return staticPaths.getAll();
},
async render(request, { routeData }) {
return prerenderer.app.render(request, { routeData });
},
async teardown() {
}
};
return prerenderer;
}
export {
createDefaultPrerenderer
};

50
node_modules/astro/dist/core/build/generate.d.ts generated vendored Normal file
View File

@@ -0,0 +1,50 @@
import type { AstroLogger } from '../logger/core.js';
import type { AstroPrerenderer, RouteToHeaders } from '../../types/public/index.js';
import type { RouteData } from '../../types/public/internal.js';
import { type BuildInternals } from './internal.js';
import type { StaticBuildOptions } from './types.js';
export declare function generatePages(options: StaticBuildOptions, internals: BuildInternals, prerenderOutputDir: URL): Promise<void>;
/**
* The result of rendering a single path, ready to be written to the filesystem.
* `null` means no file should be written (empty body, redirect skipped, or a file with the
* same output path already exists in `publicDir`).
*/
export interface RenderPathResult {
body: string | Uint8Array;
outFile: URL;
outFolder: URL;
}
interface RenderToPathPayload {
prerenderer: AstroPrerenderer;
pathname: string;
route: RouteData;
options: StaticBuildOptions;
routeToHeaders?: RouteToHeaders;
logger: AstroLogger;
}
/**
* Renders a single prerendered path to an in-memory result.
*
* This function is intentionally free of filesystem writes — it only calls
* `prerenderer.render()` and computes output paths. The caller is responsible
* for persisting the returned `body` to disk (or any other destination).
*
* Returning `null` signals that no output file should be created for this path:
* - the response body was empty
* - the redirect was suppressed by `config.build.redirects`
* - a file with the same output path already exists in `publicDir` (public files
* take priority over generated pages, so the generated page is skipped)
*
* @param params
* @param params.prerenderer - The prerenderer used to obtain a `Response` for the path.
* @param params.pathname - The URL pathname being rendered (e.g. `/about`).
* @param params.route - Route data for the page being rendered.
* @param params.options - Build options; `options.fsMod` is used to check whether a
* file already exists in `publicDir` at the output path.
* @param [params.routeToHeaders=new Map()] - Mutable map populated with response headers when
* the adapter requests static-header tracking. Callers that do
* not need to inspect the headers after the call can omit this.
* @param params.logger - Logger instance.
*/
export declare function renderPath({ prerenderer, pathname, route, options, routeToHeaders, logger, }: RenderToPathPayload): Promise<RenderPathResult | null>;
export {};

393
node_modules/astro/dist/core/build/generate.js generated vendored Normal file
View File

@@ -0,0 +1,393 @@
import nodeFs from "node:fs";
import os from "node:os";
import PLimit from "p-limit";
import PQueue from "p-queue";
import colors from "piccolore";
import {
generateImagesForPath,
getStaticImageList,
prepareAssetsGenerationEnv
} from "../../assets/build/generate.js";
import {
appendForwardSlash,
collapseDuplicateTrailingSlashes,
hasFileExtension,
joinPaths,
removeLeadingForwardSlash,
removeTrailingForwardSlash,
trimSlashes
} from "../../core/path.js";
import { runHookBuildGenerated, toIntegrationResolvedRoute } from "../../integrations/hooks.js";
import { AstroError, AstroErrorData } from "../errors/index.js";
import { getRedirectLocationOrThrow } from "../redirects/index.js";
import { createRequest } from "../request.js";
import { redirectTemplate } from "../routing/3xx.js";
import { routeIsRedirect } from "../routing/helpers.js";
import { matchRoute } from "../routing/match.js";
import { getOutputFilename } from "../util.js";
import { getOutFile, getOutFolder } from "./common.js";
import { createDefaultPrerenderer } from "./default-prerenderer.js";
import { hasPrerenderedPages } from "./internal.js";
import { getTimeStat, shouldAppendForwardSlash } from "./util.js";
async function generatePages(options, internals, prerenderOutputDir) {
const generatePagesTimer = performance.now();
const ssr = options.settings.buildOutput === "server";
const logger = options.logger;
const hasPagesToGenerate = hasPrerenderedPages(internals);
if (ssr && !hasPagesToGenerate) {
delete globalThis?.astroAsset?.addStaticImage;
}
if (!hasPagesToGenerate) {
return;
}
let prerenderer;
const settingsPrerenderer = options.settings.prerenderer;
if (!settingsPrerenderer) {
prerenderer = createDefaultPrerenderer({
internals,
options,
prerenderOutputDir
});
} else if (typeof settingsPrerenderer === "function") {
const defaultPrerenderer = createDefaultPrerenderer({
internals,
options,
prerenderOutputDir
});
prerenderer = settingsPrerenderer(defaultPrerenderer);
} else {
prerenderer = settingsPrerenderer;
}
await prerenderer.setup?.();
const verb = ssr ? "prerendering" : "generating";
logger.info("SKIP_FORMAT", `
${colors.bgGreen(colors.black(` ${verb} static routes `))}`);
const routeToHeaders = /* @__PURE__ */ new Map();
let staticImageList = getStaticImageList();
try {
const pathsWithRoutes = await prerenderer.getStaticPaths();
const hasI18nDomains = ssr && options.settings.config.i18n?.domains && Object.keys(options.settings.config.i18n.domains).length > 0;
const { config } = options.settings;
const builtPaths = /* @__PURE__ */ new Set();
const filteredPaths = pathsWithRoutes.filter(({ pathname, route }) => {
if (hasI18nDomains && route.prerender) {
throw new AstroError({
...AstroErrorData.NoPrerenderedRoutesWithDomains,
message: AstroErrorData.NoPrerenderedRoutesWithDomains.message(route.component)
});
}
const normalized = removeTrailingForwardSlash(pathname);
if (!builtPaths.has(normalized)) {
builtPaths.add(normalized);
return true;
}
const matchedRoute = matchRoute(decodeURI(pathname), options.routesList);
if (!matchedRoute) {
return false;
}
if (matchedRoute === route) {
return true;
}
if (config.prerenderConflictBehavior === "error") {
throw new AstroError({
...AstroErrorData.PrerenderRouteConflict,
message: AstroErrorData.PrerenderRouteConflict.message(
matchedRoute.route,
route.route,
normalized
),
hint: AstroErrorData.PrerenderRouteConflict.hint(matchedRoute.route, route.route)
});
} else if (config.prerenderConflictBehavior === "warn") {
const msg = AstroErrorData.PrerenderRouteConflict.message(
matchedRoute.route,
route.route,
normalized
);
logger.warn("build", msg);
}
return false;
});
if (config.build.concurrency > 1) {
const limit = PLimit(config.build.concurrency);
const BATCH_SIZE = 1e5;
for (let i = 0; i < filteredPaths.length; i += BATCH_SIZE) {
const batch = filteredPaths.slice(i, i + BATCH_SIZE);
const promises = [];
for (const { pathname, route } of batch) {
promises.push(
limit(
() => generatePathWithPrerenderer(
prerenderer,
pathname,
route,
options,
routeToHeaders,
logger
)
)
);
}
await Promise.all(promises);
}
} else {
for (const { pathname, route } of filteredPaths) {
await generatePathWithPrerenderer(
prerenderer,
pathname,
route,
options,
routeToHeaders,
logger
);
}
}
for (const { route: generatedRoute } of filteredPaths) {
if (generatedRoute.distURL && generatedRoute.distURL.length > 0) {
for (const pageData of Object.values(options.allPages)) {
if (pageData.route.route === generatedRoute.route && pageData.route.component === generatedRoute.component) {
pageData.route.distURL = generatedRoute.distURL;
break;
}
}
}
}
staticImageList = getStaticImageList();
if (prerenderer.collectStaticImages) {
const adapterImages = await prerenderer.collectStaticImages();
for (const [path, entry] of adapterImages) {
staticImageList.set(path, entry);
}
}
} finally {
await prerenderer.teardown?.();
}
logger.info(
null,
colors.green(`\u2713 Completed in ${getTimeStat(generatePagesTimer, performance.now())}.
`)
);
if (options.settings.logLevel === "debug" && options.settings.config.experimental?.queuedRendering && prerenderer.app) {
try {
const stats = prerenderer.app.getQueueStats();
if (stats && (stats.acquireFromPool > 0 || stats.acquireNew > 0)) {
logger.info(
null,
colors.dim(
`[Queue Pool] ${stats.acquireFromPool.toLocaleString()} reused / ${stats.acquireNew.toLocaleString()} new nodes | Hit rate: ${stats.hitRate.toFixed(1)}% | Pool: ${stats.poolSize}/${stats.maxSize}`
)
);
}
} catch {
}
}
if (staticImageList.size) {
logger.info("SKIP_FORMAT", `${colors.bgGreen(colors.black(` generating optimized images `))}`);
const totalCount = Array.from(staticImageList.values()).map((x) => x.transforms.size).reduce((a, b) => a + b, 0);
const cpuCount = os.cpus().length;
const assetsCreationPipeline = await prepareAssetsGenerationEnv(options, totalCount);
const queue = new PQueue({ concurrency: Math.max(cpuCount, 1) });
const assetsTimer = performance.now();
for (const [originalPath, transforms] of staticImageList) {
queue.add(() => generateImagesForPath(originalPath, transforms, assetsCreationPipeline)).catch((e) => {
throw e;
});
}
await queue.onIdle();
const assetsTimeEnd = performance.now();
logger.info(null, colors.green(`\u2713 Completed in ${getTimeStat(assetsTimer, assetsTimeEnd)}.
`));
delete globalThis?.astroAsset?.addStaticImage;
}
await runHookBuildGenerated({
settings: options.settings,
logger,
routeToHeaders
});
}
const THRESHOLD_SLOW_RENDER_TIME_MS = 500;
async function renderPath({
prerenderer,
pathname,
route,
options,
routeToHeaders = /* @__PURE__ */ new Map(),
logger
}) {
const { config } = options.settings;
if (route.type === "fallback" && route.pathname !== "/") {
if (options.routesList.routes.some((routeData) => {
if (routeData.pattern.test(pathname)) {
if (routeData.params && routeData.params.length !== 0) {
if (routeData.distURL && !routeData.distURL.find(
(url2) => url2.href.replace(config.outDir.toString(), "").replace(/(?:\/index\.html|\.html)$/, "") === trimSlashes(pathname)
)) {
return false;
}
}
return true;
} else {
return false;
}
})) {
return null;
}
}
const url = getUrlForPath(
pathname,
config.base,
options.origin,
config.build.format,
config.trailingSlash,
route.type
);
const request = createRequest({
url,
headers: new Headers(),
logger,
isPrerendered: true,
routePattern: route.component
});
let response;
try {
response = await prerenderer.render(request, { routeData: route });
} catch (err) {
logger.error("build", `Caught error rendering ${pathname}: ${err}`);
if (err && !AstroError.is(err) && !err.id && typeof err === "object") {
err.id = route.component;
}
throw err;
}
let body;
const responseHeaders = response.headers;
if (response.status >= 300 && response.status < 400) {
if (routeIsRedirect(route) && !config.build.redirects) {
return null;
}
const locationSite = getRedirectLocationOrThrow(responseHeaders);
const siteURL = config.site;
const location = siteURL ? new URL(locationSite, siteURL) : locationSite;
const fromPath = new URL(request.url).pathname;
body = redirectTemplate({
status: response.status,
absoluteLocation: location,
relativeLocation: locationSite,
from: fromPath
});
if (config.compressHTML === true) {
body = body.replaceAll("\n", "");
}
if (route.type !== "redirect") {
route.redirect = location.toString();
}
} else {
if (!response.body) {
return null;
}
body = Buffer.from(await response.arrayBuffer());
}
const encodedPath = encodeURI(pathname);
const outFolder = getOutFolder(options.settings, encodedPath, route);
const outFile = getOutFile(config.build.format, outFolder, encodedPath, route);
if (route.distURL) {
route.distURL.push(outFile);
} else {
route.distURL = [outFile];
}
const integrationRoute = toIntegrationResolvedRoute(route, config.trailingSlash);
if (options.settings.adapter?.adapterFeatures?.staticHeaders) {
routeToHeaders.set(pathname, { headers: responseHeaders, route: integrationRoute });
}
if (checkPublicConflict(outFile, route, options.settings, logger)) return null;
return { body, outFile, outFolder };
}
async function generatePathWithPrerenderer(prerenderer, pathname, route, options, routeToHeaders, logger) {
const timeStart = performance.now();
const { config } = options.settings;
const filePath = getOutputFilename(config.build.format, pathname, route);
logger.info(null, ` ${colors.blue("\u251C\u2500")} ${colors.dim(filePath)}`, false);
if (route.type === "page") {
addPageName(pathname, options);
}
const result = await renderPath({
prerenderer,
pathname,
route,
options,
routeToHeaders,
logger
});
if (!result) {
logRenderTime(logger, timeStart, true);
return;
}
await nodeFs.promises.mkdir(result.outFolder, { recursive: true });
await nodeFs.promises.writeFile(result.outFile, result.body);
logRenderTime(logger, timeStart, false);
}
function logRenderTime(logger, timeStart, notCreated) {
const timeEnd = performance.now();
const isSlow = timeEnd - timeStart > THRESHOLD_SLOW_RENDER_TIME_MS;
const timeIncrease = (isSlow ? colors.red : colors.dim)(`(+${getTimeStat(timeStart, timeEnd)})`);
const notCreatedMsg = notCreated ? colors.yellow("(file not created, response body was empty)") : "";
logger.info("SKIP_FORMAT", ` ${timeIncrease} ${notCreatedMsg}`);
}
function addPageName(pathname, opts) {
const trailingSlash = opts.settings.config.trailingSlash;
const buildFormat = opts.settings.config.build.format;
const pageName = shouldAppendForwardSlash(trailingSlash, buildFormat) ? pathname.replace(/\/?$/, "/").replace(/^\//, "") : pathname.replace(/^\//, "");
opts.pageNames.push(pageName);
}
function getUrlForPath(pathname, base, origin, format, trailingSlash, routeType) {
let ending;
switch (format) {
case "directory":
case "preserve": {
ending = trailingSlash === "never" ? "" : "/";
break;
}
case "file":
default: {
ending = ".html";
break;
}
}
let buildPathname;
if (pathname === "/" || pathname === "") {
if (format === "file") {
buildPathname = joinPaths(base, "index.html");
} else {
buildPathname = collapseDuplicateTrailingSlashes(base + ending, trailingSlash !== "never");
}
} else if (routeType === "endpoint") {
const buildPathRelative = removeLeadingForwardSlash(pathname);
let endpointPathname = joinPaths(base, buildPathRelative);
if (trailingSlash === "always" && !hasFileExtension(pathname)) {
endpointPathname = appendForwardSlash(endpointPathname);
} else if (trailingSlash === "never") {
endpointPathname = removeTrailingForwardSlash(endpointPathname);
}
buildPathname = endpointPathname;
} else {
const buildPathRelative = removeTrailingForwardSlash(removeLeadingForwardSlash(pathname)) + ending;
buildPathname = joinPaths(base, buildPathRelative);
}
return new URL(buildPathname, origin);
}
function checkPublicConflict(outFile, route, settings, logger) {
const outRoot = settings.buildOutput === "static" && !settings.adapter?.adapterFeatures?.preserveBuildClientDir ? settings.config.outDir : settings.config.build.client;
const relativePath = outFile.href.slice(outRoot.href.length);
const publicFileUrl = new URL(relativePath, settings.config.publicDir);
if (nodeFs.existsSync(publicFileUrl)) {
logger.warn(
"build",
`Skipping ${route.component} because a file with the same name exists in the public folder: ${relativePath}`
);
return true;
}
return false;
}
export {
generatePages,
renderPath
};

17
node_modules/astro/dist/core/build/graph.d.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
import type { GetModuleInfo, ModuleInfo } from 'rollup';
interface ExtendedModuleInfo {
info: ModuleInfo;
depth: number;
order: number;
}
export declare function getParentExtendedModuleInfos(id: string, ctx: {
getModuleInfo: GetModuleInfo;
}, until?: (importer: string) => boolean, depth?: number, order?: number, childId?: string, seen?: Set<string>, accumulated?: ExtendedModuleInfo[]): ExtendedModuleInfo[];
export declare function getParentModuleInfos(id: string, ctx: {
getModuleInfo: GetModuleInfo;
}, until?: (importer: string) => boolean, seen?: Set<string>, accumulated?: ModuleInfo[]): ModuleInfo[];
export declare function moduleIsTopLevelPage(info: ModuleInfo): boolean;
export declare function getTopLevelPageModuleInfos(id: string, ctx: {
getModuleInfo: GetModuleInfo;
}): ModuleInfo[];
export {};

54
node_modules/astro/dist/core/build/graph.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
import { VIRTUAL_PAGE_RESOLVED_MODULE_ID } from "../../vite-plugin-pages/const.js";
function getParentExtendedModuleInfos(id, ctx, until, depth = 0, order = 0, childId = "", seen = /* @__PURE__ */ new Set(), accumulated = []) {
seen.add(id);
const info = ctx.getModuleInfo(id);
if (info) {
if (childId) {
const idx = info.importedIds.indexOf(childId);
if (idx === -1) {
order += info.importedIds.length;
order += info.dynamicallyImportedIds.indexOf(childId);
} else {
order += idx;
}
}
accumulated.push({ info, depth, order });
}
if (info && !until?.(id)) {
const importers = info.importers.concat(info.dynamicImporters);
for (const imp of importers) {
if (!seen.has(imp)) {
getParentExtendedModuleInfos(imp, ctx, until, depth + 1, order, id, seen, accumulated);
}
}
}
return accumulated;
}
function getParentModuleInfos(id, ctx, until, seen = /* @__PURE__ */ new Set(), accumulated = []) {
seen.add(id);
const info = ctx.getModuleInfo(id);
if (info) {
accumulated.push(info);
}
if (info && !until?.(id)) {
const importers = info.importers.concat(info.dynamicImporters);
for (const imp of importers) {
if (!seen.has(imp)) {
getParentModuleInfos(imp, ctx, until, seen, accumulated);
}
}
}
return accumulated;
}
function moduleIsTopLevelPage(info) {
return info.importers[0]?.includes(VIRTUAL_PAGE_RESOLVED_MODULE_ID) || info.dynamicImporters[0]?.includes(VIRTUAL_PAGE_RESOLVED_MODULE_ID);
}
function getTopLevelPageModuleInfos(id, ctx) {
return getParentModuleInfos(id, ctx).filter(moduleIsTopLevelPage);
}
export {
getParentExtendedModuleInfos,
getParentModuleInfos,
getTopLevelPageModuleInfos,
moduleIsTopLevelPage
};

66
node_modules/astro/dist/core/build/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,66 @@
import type { AstroSettings, RoutesList } from '../../types/astro.js';
import type { AstroInlineConfig, RuntimeMode } from '../../types/public/config.js';
import type { AstroLogger } from '../logger/core.js';
interface BuildOptions {
/**
* Output a development-based build similar to code transformed in `astro dev`. This
* can be useful to test build-only issues with additional debugging information included.
*
* @default false
*/
devOutput?: boolean;
/**
* Teardown the compiler WASM instance after build. This can improve performance when
* building once, but may cause a performance hit if building multiple times in a row.
*
* When building multiple projects in the same execution (e.g. during tests), disabling
* this option can greatly improve performance at the cost of some extra memory usage.
*
* @default true
*/
teardownCompiler?: boolean;
}
/**
* Builds your site for deployment. By default, this will generate static files and place them in a dist/ directory.
* If SSR is enabled, this will generate the necessary server files to serve your site.
*
* @experimental The JavaScript API is experimental
*/
export default function build(inlineConfig: AstroInlineConfig, options?: BuildOptions): Promise<void>;
interface AstroBuilderOptions extends BuildOptions {
logger: AstroLogger;
mode: string;
runtimeMode: RuntimeMode;
/**
* Provide a pre-built routes list to skip filesystem route scanning.
* Useful for testing builds with in-memory virtual modules.
*/
routesList?: RoutesList;
/**
* Whether to run `syncInternal` during setup. Defaults to true.
* Set to false for in-memory builds that don't need type generation.
*/
sync?: boolean;
}
export declare class AstroBuilder {
private settings;
private logger;
private mode;
private runtimeMode;
private origin;
private routesList;
private timer;
private teardownCompiler;
private sync;
constructor(settings: AstroSettings, options: AstroBuilderOptions);
/** Setup Vite and run any async setup logic that couldn't run inside of the constructor. */
private setup;
/** Run the build logic. build() is marked private because usage should go through ".run()" */
private build;
/** Build the given Astro project. */
run(): Promise<void>;
private validateConfig;
/** Stats */
private printStats;
}
export {};

237
node_modules/astro/dist/core/build/index.js generated vendored Normal file
View File

@@ -0,0 +1,237 @@
import fs from "node:fs";
import { performance } from "node:perf_hooks";
import { fileURLToPath } from "node:url";
import colors from "piccolore";
import { telemetry } from "../../events/index.js";
import { eventCliSession } from "../../events/session.js";
import {
runHookBuildDone,
runHookBuildStart,
runHookConfigDone,
runHookConfigSetup
} from "../../integrations/hooks.js";
import { resolveConfig } from "../config/config.js";
import { loadOrCreateNodeLogger } from "../logger/load.js";
import { createSettings } from "../config/settings.js";
import { createVite } from "../create-vite.js";
import { createKey, getEnvironmentKey, hasEnvironmentKey } from "../encryption.js";
import { AstroError, AstroErrorData } from "../errors/index.js";
import { levels, timerMessage } from "../logger/core.js";
import { createRoutesList } from "../routing/create-manifest.js";
import { getPrerenderDefault } from "../../prerender/utils.js";
import { clearContentLayerCache } from "../sync/index.js";
import { ensureProcessNodeEnv } from "../util.js";
import { collectPagesData } from "./page-data.js";
import { viteBuild } from "./static-build.js";
import { getTimeStat } from "./util.js";
import { warnIfCspWithShiki } from "../messages/runtime.js";
async function build(inlineConfig, options = {}) {
ensureProcessNodeEnv(options.devOutput ? "development" : "production");
const { userConfig, astroConfig } = await resolveConfig(inlineConfig, "build");
const logger = await loadOrCreateNodeLogger(astroConfig, inlineConfig ?? {});
telemetry.record(eventCliSession("build", userConfig));
warnIfCspWithShiki(astroConfig, logger);
const settings = await createSettings(
astroConfig,
inlineConfig.logLevel,
fileURLToPath(astroConfig.root)
);
if (inlineConfig.force) {
await clearContentLayerCache({ settings, logger, fs, isDev: false });
}
const builder = new AstroBuilder(settings, {
...options,
logger,
mode: inlineConfig.mode ?? "production",
runtimeMode: options.devOutput ? "development" : "production"
});
await builder.run();
}
class AstroBuilder {
settings;
logger;
mode;
runtimeMode;
origin;
routesList;
timer;
teardownCompiler;
sync;
constructor(settings, options) {
this.mode = options.mode;
this.runtimeMode = options.runtimeMode;
this.settings = settings;
this.logger = options.logger;
this.teardownCompiler = options.teardownCompiler ?? true;
this.sync = options.sync ?? true;
this.origin = settings.config.site ? new URL(settings.config.site).origin : `http://localhost:${settings.config.server.port}`;
this.routesList = options.routesList ?? { routes: [] };
this.timer = {};
}
/** Setup Vite and run any async setup logic that couldn't run inside of the constructor. */
async setup() {
this.logger.debug("build", "Initial setup...");
const { logger } = this;
this.timer.init = performance.now();
this.settings = await runHookConfigSetup({
settings: this.settings,
command: "build",
logger
});
this.settings.buildOutput = getPrerenderDefault(this.settings.config) ? "static" : "server";
if (this.routesList.routes.length === 0) {
this.routesList = await createRoutesList({ settings: this.settings }, this.logger);
}
await runHookConfigDone({ settings: this.settings, logger, command: "build" });
if (!this.settings.config.adapter && this.settings.buildOutput === "server") {
throw new AstroError(AstroErrorData.NoAdapterInstalled);
}
const viteConfig = await createVite(
{
server: {
hmr: false,
middlewareMode: true
}
},
{
routesList: this.routesList,
settings: this.settings,
logger: this.logger,
mode: this.mode,
command: "build",
sync: false
}
);
if (this.sync) {
const { syncInternal } = await import("../sync/index.js");
await syncInternal({
mode: this.mode,
settings: this.settings,
logger,
fs,
command: "build"
});
}
return { viteConfig };
}
/** Run the build logic. build() is marked private because usage should go through ".run()" */
async build({ viteConfig }) {
await runHookBuildStart({ settings: this.settings, logger: this.logger });
this.validateConfig();
this.logger.info("build", `output: ${colors.blue('"' + this.settings.config.output + '"')}`);
this.logger.info("build", `mode: ${colors.blue('"' + this.settings.buildOutput + '"')}`);
this.logger.info(
"build",
`directory: ${colors.blue(fileURLToPath(this.settings.config.outDir))}`
);
if (this.settings.adapter) {
this.logger.info("build", `adapter: ${colors.green(this.settings.adapter.name)}`);
}
this.logger.info("build", "Collecting build info...");
this.timer.loadStart = performance.now();
const { assets, allPages } = collectPagesData({
settings: this.settings,
logger: this.logger,
manifest: this.routesList
});
this.logger.debug("build", timerMessage("All pages loaded", this.timer.loadStart));
const pageNames = [];
this.timer.buildStart = performance.now();
this.logger.info(
"build",
colors.green(`\u2713 Completed in ${getTimeStat(this.timer.init, performance.now())}.`)
);
const hasKey = hasEnvironmentKey();
const keyPromise = hasKey ? getEnvironmentKey() : createKey();
const opts = {
allPages,
settings: this.settings,
logger: this.logger,
routesList: this.routesList,
runtimeMode: this.runtimeMode,
origin: this.origin,
pageNames,
teardownCompiler: this.teardownCompiler,
viteConfig,
key: keyPromise
};
await viteBuild(opts);
this.timer.assetsStart = performance.now();
Object.keys(assets).map((k) => {
if (!assets[k]) return;
const filePath = new URL(`file://${k}`);
fs.mkdirSync(new URL("./", filePath), { recursive: true });
fs.writeFileSync(filePath, assets[k], "utf8");
delete assets[k];
});
this.logger.debug("build", timerMessage("Additional assets copied", this.timer.assetsStart));
if (this.settings.fontsHttpServer) {
await new Promise((resolve, reject) => {
this.settings.fontsHttpServer.close((err) => {
if (err) reject(err);
else resolve();
});
}).catch((err) => {
this.logger.debug("assets", "Failed to close fonts HTTP server:", err);
});
this.settings.fontsHttpServer = null;
}
await runHookBuildDone({
settings: this.settings,
pages: pageNames,
routes: Object.values(allPages).flat().map((pageData) => pageData.route),
logger: this.logger
});
if (this.logger.level && levels[this.logger.level()] <= levels["info"]) {
await this.printStats({
logger: this.logger,
timeStart: this.timer.init,
pageCount: pageNames.length,
buildMode: this.settings.buildOutput
// buildOutput is always set at this point
});
}
}
/** Build the given Astro project. */
async run() {
this.settings.timer.start("Total build");
const setupData = await this.setup();
try {
await this.build(setupData);
} catch (_err) {
throw _err;
} finally {
this.settings.timer.end("Total build");
this.settings.timer.writeStats();
}
}
validateConfig() {
const { config } = this.settings;
if (config.outDir.toString() === config.root.toString()) {
throw new Error(
`the outDir cannot be the root folder. Please build to a folder such as dist.`
);
}
}
/** Stats */
async printStats({
logger,
timeStart,
pageCount,
buildMode
}) {
const total = getTimeStat(timeStart, performance.now());
let messages = [];
if (buildMode === "static") {
messages = [`${pageCount} page(s) built in`, colors.bold(total)];
} else {
messages = ["Server built in", colors.bold(total)];
}
logger.info("build", messages.join(" "));
logger.info("build", `${colors.bold("Complete!")}`);
}
}
export {
AstroBuilder,
build as default
};

125
node_modules/astro/dist/core/build/internal.d.ts generated vendored Normal file
View File

@@ -0,0 +1,125 @@
import type { SSRResult } from '../../types/public/internal.js';
import type { AstroEnvironmentNames } from '../constants.js';
import type { PageBuildData, StylesheetAsset, ViteID } from './types.js';
export interface BuildInternals {
/**
* Each CSS module is named with a chunk id derived from the Astro pages they
* are used in by default. It's easy to crawl this relation in the SSR build as
* the Astro pages are the entrypoint, but not for the client build as hydratable
* components are the entrypoint instead. This map is used as a cache from the SSR
* build so the client can pick up the same information and use the same chunk ids.
*/
cssModuleToChunkIdMap: Map<string, string>;
/**
* If script is inlined, its id and inlined code is mapped here. The resolved id is
* an URL like "/_astro/something.js" but will no longer exist as the content is now
* inlined in this map.
*/
inlinedScripts: Map<string, string>;
entrySpecifierToBundleMap: Map<string, string>;
/**
* A map for page-specific information.
*/
pagesByKeys: Map<string, PageBuildData>;
/**
* A map for page-specific information by Vite ID (a path-like string)
*/
pagesByViteID: Map<ViteID, PageBuildData>;
/**
* A map for page-specific information by a client:only component
*/
pagesByClientOnly: Map<string, Set<PageBuildData>>;
/**
* A map for page-specific information by a script in an Astro file
*/
pagesByScriptId: Map<string, Set<PageBuildData>>;
/**
* A map for page-specific information by a hydrated component
*/
pagesByHydratedComponent: Map<string, Set<PageBuildData>>;
/**
* A map of hydrated components to export names that are discovered during the SSR build.
* These will be used as the top-level entrypoints for the client build.
*
* @example
* '/project/Component1.jsx' => ['default']
* '/project/Component2.jsx' => ['Counter', 'Timer']
* '/project/Component3.jsx' => ['*']
*/
discoveredHydratedComponents: Map<string, string[]>;
/**
* A list of client:only components to export names that are discovered during the SSR build.
* These will be used as the top-level entrypoints for the client build.
*
* @example
* '/project/Component1.jsx' => ['default']
* '/project/Component2.jsx' => ['Counter', 'Timer']
* '/project/Component3.jsx' => ['*']
*/
discoveredClientOnlyComponents: Map<string, string[]>;
/**
* A list of scripts that are discovered during the SSR build.
* These will be used as the top-level entrypoints for the client build.
*/
discoveredScripts: Set<string>;
/**
* Map of propagated module ids (usually something like `/Users/...blog.mdx?astroPropagatedAssets`)
* to a set of stylesheets that it uses.
*/
propagatedStylesMap: Map<string, Set<StylesheetAsset>>;
staticFiles: Set<string>;
clientChunksAndAssets: Set<string>;
clientInput: Set<string>;
manifestFileName?: string;
prerenderEntryFileName?: string;
componentMetadata: SSRResult['componentMetadata'];
middlewareEntryPoint: URL | undefined;
loggerEntryPoint: URL | undefined;
astroActionsEntryPoint: URL | undefined;
/**
* Assets that need to be moved from SSR/prerender directories to the client directory.
* Populated during generateBundle by vitePluginSSRAssets.
* Map of environment name -> Set of asset filenames.
*/
ssrAssetsPerEnvironment: Map<AstroEnvironmentNames, Set<string>>;
/**
* Chunks extracted during build that need post-build injection (manifest, content).
* Populated by top-level buildApp, consumed by post plugin.
*/
extractedChunks?: Array<{
fileName: string;
code: string;
moduleIds: string[];
prerender: boolean;
}>;
}
/**
* Creates internal maps used to coordinate the CSS and HTML plugins.
* @returns {BuildInternals}
*/
export declare function createBuildInternals(): BuildInternals;
/**
* Gets or creates the set of SSR assets for a given environment.
* Handles type casting from Vite's string environment name to AstroEnvironmentNames.
*/
export declare function getOrCreateSSRAssets(internals: BuildInternals, envName: string): Set<string>;
/**
* Gets the set of SSR assets for a given environment, or an empty set if none exist.
*/
export declare function getSSRAssets(internals: BuildInternals, envName: string): Set<string>;
export declare function trackPageData(internals: BuildInternals, _component: string, pageData: PageBuildData, componentModuleId: string, componentURL: URL): void;
/**
* Tracks client-only components to the pages they are associated with.
*/
export declare function trackClientOnlyPageDatas(internals: BuildInternals, pageData: PageBuildData, clientOnlys: string[]): void;
/**
* Tracks scripts to the pages they are associated with.
*/
export declare function trackScriptPageDatas(internals: BuildInternals, pageData: PageBuildData, scriptIds: string[]): void;
/**
* Tracks hydrated components to the pages they are associated with.
*/
export declare function trackHydratedComponentPageDatas(internals: BuildInternals, pageData: PageBuildData, hydratedComponents: string[]): void;
export declare function getPageDatasByClientOnlyID(internals: BuildInternals, viteid: ViteID): Generator<PageBuildData, void, unknown>;
export declare function getPageDataByViteID(internals: BuildInternals, viteid: ViteID): PageBuildData | undefined;
export declare function hasPrerenderedPages(internals: BuildInternals): boolean;

124
node_modules/astro/dist/core/build/internal.js generated vendored Normal file
View File

@@ -0,0 +1,124 @@
import { prependForwardSlash, removeFileExtension } from "../path.js";
import { viteID } from "../util.js";
function createBuildInternals() {
return {
clientInput: /* @__PURE__ */ new Set(),
cssModuleToChunkIdMap: /* @__PURE__ */ new Map(),
inlinedScripts: /* @__PURE__ */ new Map(),
entrySpecifierToBundleMap: /* @__PURE__ */ new Map(),
pagesByKeys: /* @__PURE__ */ new Map(),
pagesByViteID: /* @__PURE__ */ new Map(),
pagesByClientOnly: /* @__PURE__ */ new Map(),
pagesByScriptId: /* @__PURE__ */ new Map(),
pagesByHydratedComponent: /* @__PURE__ */ new Map(),
propagatedStylesMap: /* @__PURE__ */ new Map(),
discoveredHydratedComponents: /* @__PURE__ */ new Map(),
discoveredClientOnlyComponents: /* @__PURE__ */ new Map(),
discoveredScripts: /* @__PURE__ */ new Set(),
staticFiles: /* @__PURE__ */ new Set(),
componentMetadata: /* @__PURE__ */ new Map(),
astroActionsEntryPoint: void 0,
middlewareEntryPoint: void 0,
loggerEntryPoint: void 0,
clientChunksAndAssets: /* @__PURE__ */ new Set(),
ssrAssetsPerEnvironment: /* @__PURE__ */ new Map()
};
}
function getOrCreateSSRAssets(internals, envName) {
const key = envName;
let assets = internals.ssrAssetsPerEnvironment.get(key);
if (!assets) {
assets = /* @__PURE__ */ new Set();
internals.ssrAssetsPerEnvironment.set(key, assets);
}
return assets;
}
function getSSRAssets(internals, envName) {
return internals.ssrAssetsPerEnvironment.get(envName) ?? /* @__PURE__ */ new Set();
}
function trackPageData(internals, _component, pageData, componentModuleId, componentURL) {
pageData.moduleSpecifier = componentModuleId;
internals.pagesByKeys.set(pageData.key, pageData);
internals.pagesByViteID.set(viteID(componentURL), pageData);
}
function trackClientOnlyPageDatas(internals, pageData, clientOnlys) {
for (const clientOnlyComponent of clientOnlys) {
let pageDataSet;
if (internals.pagesByClientOnly.has(clientOnlyComponent)) {
pageDataSet = internals.pagesByClientOnly.get(clientOnlyComponent);
} else {
pageDataSet = /* @__PURE__ */ new Set();
internals.pagesByClientOnly.set(clientOnlyComponent, pageDataSet);
}
pageDataSet.add(pageData);
}
}
function trackScriptPageDatas(internals, pageData, scriptIds) {
for (const scriptId of scriptIds) {
let pageDataSet;
if (internals.pagesByScriptId.has(scriptId)) {
pageDataSet = internals.pagesByScriptId.get(scriptId);
} else {
pageDataSet = /* @__PURE__ */ new Set();
internals.pagesByScriptId.set(scriptId, pageDataSet);
}
pageDataSet.add(pageData);
}
}
function trackHydratedComponentPageDatas(internals, pageData, hydratedComponents) {
for (const hydratedComponent of hydratedComponents) {
let pageDataSet;
if (internals.pagesByHydratedComponent.has(hydratedComponent)) {
pageDataSet = internals.pagesByHydratedComponent.get(hydratedComponent);
} else {
pageDataSet = /* @__PURE__ */ new Set();
internals.pagesByHydratedComponent.set(hydratedComponent, pageDataSet);
}
pageDataSet.add(pageData);
}
}
function* getPageDatasByClientOnlyID(internals, viteid) {
const pagesByClientOnly = internals.pagesByClientOnly;
if (pagesByClientOnly.size) {
let pageBuildDatas = pagesByClientOnly.get(viteid);
if (!pageBuildDatas) {
let pathname = `/@fs${prependForwardSlash(viteid)}`;
pageBuildDatas = pagesByClientOnly.get(pathname);
}
if (!pageBuildDatas) {
let pathname = `/@fs${prependForwardSlash(removeFileExtension(viteid))}`;
pageBuildDatas = pagesByClientOnly.get(pathname);
}
if (pageBuildDatas) {
for (const pageData of pageBuildDatas) {
yield pageData;
}
}
}
}
function getPageDataByViteID(internals, viteid) {
if (internals.pagesByViteID.has(viteid)) {
return internals.pagesByViteID.get(viteid);
}
return void 0;
}
function hasPrerenderedPages(internals) {
for (const pageData of internals.pagesByKeys.values()) {
if (pageData.route.prerender) {
return true;
}
}
return false;
}
export {
createBuildInternals,
getOrCreateSSRAssets,
getPageDataByViteID,
getPageDatasByClientOnlyID,
getSSRAssets,
hasPrerenderedPages,
trackClientOnlyPageDatas,
trackHydratedComponentPageDatas,
trackPageData,
trackScriptPageDatas
};

14
node_modules/astro/dist/core/build/page-data.d.ts generated vendored Normal file
View File

@@ -0,0 +1,14 @@
import type { AstroSettings, RoutesList } from '../../types/astro.js';
import type { AstroLogger } from '../logger/core.js';
import type { AllPagesData } from './types.js';
interface CollectPagesDataOptions {
settings: AstroSettings;
logger: AstroLogger;
manifest: RoutesList;
}
interface CollectPagesDataResult {
assets: Record<string, string>;
allPages: AllPagesData;
}
export declare function collectPagesData(opts: CollectPagesDataOptions): CollectPagesDataResult;
export {};

45
node_modules/astro/dist/core/build/page-data.js generated vendored Normal file
View File

@@ -0,0 +1,45 @@
import colors from "piccolore";
import { debug } from "../logger/core.js";
import { DEFAULT_COMPONENTS } from "../routing/default.js";
import { makePageDataKey } from "./plugins/util.js";
function collectPagesData(opts) {
const { settings, manifest } = opts;
const assets = {};
const allPages = {};
for (const route of manifest.routes) {
if (DEFAULT_COMPONENTS.some((component) => route.component === component)) {
continue;
}
const key = makePageDataKey(route.route, route.component);
if (route.pathname) {
allPages[key] = {
key,
component: route.component,
route,
moduleSpecifier: "",
styles: []
};
if (settings.buildOutput === "static") {
const html = `${route.pathname}`.replace(/\/?$/, "/index.html");
debug(
"build",
`\u251C\u2500\u2500 ${colors.bold(colors.green("\u2714"))} ${route.component} \u2192 ${colors.yellow(html)}`
);
} else {
debug("build", `\u251C\u2500\u2500 ${colors.bold(colors.green("\u2714"))} ${route.component}`);
}
continue;
}
allPages[key] = {
key,
component: route.component,
route,
moduleSpecifier: "",
styles: []
};
}
return { assets, allPages };
}
export {
collectPagesData
};

38
node_modules/astro/dist/core/build/pipeline.d.ts generated vendored Normal file
View File

@@ -0,0 +1,38 @@
import type { ComponentInstance } from '../../types/astro.js';
import type { RewritePayload } from '../../types/public/common.js';
import type { RouteData, SSRResult } from '../../types/public/internal.js';
import type { SSRManifest } from '../app/types.js';
import type { TryRewriteResult } from '../base-pipeline.js';
import { Pipeline } from '../base-pipeline.js';
import { type DefaultRouteParams } from '../routing/default.js';
import type { BuildInternals } from './internal.js';
import type { SinglePageBuiltModule, StaticBuildOptions } from './types.js';
/**
* The build pipeline is responsible to gather the files emitted by the SSR build and generate the pages by executing these files.
*/
export declare class BuildPipeline extends Pipeline {
#private;
internals: BuildInternals | undefined;
options: StaticBuildOptions | undefined;
readonly manifest: SSRManifest;
readonly defaultRoutes: Array<DefaultRouteParams>;
getName(): string;
getSettings(): import("../../types/astro.js").AstroSettings;
getOptions(): StaticBuildOptions;
getInternals(): BuildInternals;
private constructor();
getRoutes(): RouteData[];
static create({ manifest }: Pick<BuildPipeline, 'manifest'>): BuildPipeline;
setInternals(internals: BuildInternals): void;
setOptions(options: StaticBuildOptions): void;
headElements(routeData: RouteData): Pick<SSRResult, 'scripts' | 'styles' | 'links'>;
componentMetadata(): void;
/**
* It collects the routes to generate during the build.
* It returns a map of page information and their relative entry point as a string.
*/
retrieveRoutesToGenerate(): Set<RouteData>;
getComponentByRoute(routeData: RouteData): Promise<ComponentInstance>;
getModuleForRoute(route: RouteData): Promise<SinglePageBuiltModule>;
tryRewrite(payload: RewritePayload, request: Request): Promise<TryRewriteResult>;
}

211
node_modules/astro/dist/core/build/pipeline.js generated vendored Normal file
View File

@@ -0,0 +1,211 @@
import { VIRTUAL_PAGE_RESOLVED_MODULE_ID } from "../../vite-plugin-pages/const.js";
import { getVirtualModulePageName } from "../../vite-plugin-pages/util.js";
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from "../../vite-plugin-scripts/index.js";
import { createConsoleLogger } from "../app/entrypoints/index.js";
import { RedirectSinglePageBuiltModule } from "../redirects/component.js";
import { Pipeline } from "../base-pipeline.js";
import { createAssetLink, createStylesheetElementSet } from "../render/ssr-element.js";
import { createDefaultRoutes } from "../routing/default.js";
import { getFallbackRoute, routeIsFallback, routeIsRedirect } from "../routing/helpers.js";
import { findRouteToRewrite } from "../routing/rewrite.js";
import { cssOrder, mergeInlineCss, getPageData } from "./runtime.js";
import { newNodePool } from "../../runtime/server/render/queue/pool.js";
import { HTMLStringCache } from "../../runtime/server/html-string-cache.js";
import { queueRenderingEnabled } from "../app/manifest.js";
class BuildPipeline extends Pipeline {
internals;
options;
manifest;
defaultRoutes;
getName() {
return "BuildPipeline";
}
/**
* This cache is needed to map a single `RouteData` to its file path.
* @private
*/
#routesByFilePath = /* @__PURE__ */ new WeakMap();
getSettings() {
if (!this.options) {
throw new Error("No options defined");
}
return this.options.settings;
}
getOptions() {
if (!this.options) {
throw new Error("No options defined");
}
return this.options;
}
getInternals() {
if (!this.internals) {
throw new Error("No internals defined");
}
return this.internals;
}
constructor(manifest, defaultRoutes = createDefaultRoutes(manifest)) {
const resolveCache = /* @__PURE__ */ new Map();
async function resolve(specifier) {
if (resolveCache.has(specifier)) {
return resolveCache.get(specifier);
}
const hashedFilePath = manifest.entryModules[specifier];
if (typeof hashedFilePath !== "string" || hashedFilePath === "") {
if (specifier === BEFORE_HYDRATION_SCRIPT_ID) {
resolveCache.set(specifier, "");
return "";
}
throw new Error(`Cannot find the built path for ${specifier}`);
}
const assetLink = createAssetLink(hashedFilePath, manifest.base, manifest.assetsPrefix);
resolveCache.set(specifier, assetLink);
return assetLink;
}
const logger = createConsoleLogger({ level: manifest.logLevel });
super(logger, manifest, "production", manifest.renderers, resolve, manifest.serverLike);
this.manifest = manifest;
this.defaultRoutes = defaultRoutes;
if (queueRenderingEnabled(this.manifest.experimentalQueuedRendering)) {
this.nodePool = newNodePool(this.manifest.experimentalQueuedRendering);
if (this.manifest.experimentalQueuedRendering.contentCache) {
this.htmlStringCache = new HTMLStringCache(1e3);
}
}
}
getRoutes() {
return this.getOptions().routesList.routes;
}
static create({ manifest }) {
return new BuildPipeline(manifest);
}
setInternals(internals) {
this.internals = internals;
}
setOptions(options) {
this.options = options;
}
headElements(routeData) {
const {
manifest: { assetsPrefix, base }
} = this;
const settings = this.getSettings();
const internals = this.getInternals();
const links = /* @__PURE__ */ new Set();
const pageBuildData = getPageData(internals, routeData.route, routeData.component);
const scripts = /* @__PURE__ */ new Set();
const sortedCssAssets = pageBuildData?.styles.sort(cssOrder).map(({ sheet }) => sheet).reduce(mergeInlineCss, []);
const styles = createStylesheetElementSet(sortedCssAssets ?? [], base, assetsPrefix);
if (settings.scripts.some((script) => script.stage === "page")) {
const hashedFilePath = internals.entrySpecifierToBundleMap.get(PAGE_SCRIPT_ID);
if (typeof hashedFilePath !== "string") {
throw new Error(`Cannot find the built path for ${PAGE_SCRIPT_ID}`);
}
const src = createAssetLink(hashedFilePath, base, assetsPrefix);
scripts.add({
props: { type: "module", src },
children: ""
});
}
for (const script of settings.scripts) {
if (script.stage === "head-inline") {
scripts.add({
props: {},
children: script.content
});
}
}
return { scripts, styles, links };
}
componentMetadata() {
}
/**
* It collects the routes to generate during the build.
* It returns a map of page information and their relative entry point as a string.
*/
retrieveRoutesToGenerate() {
const pages = /* @__PURE__ */ new Set();
const defaultRouteComponents = new Set(this.defaultRoutes.map((route) => route.component));
for (const { routeData } of this.manifest.routes) {
if (routeIsRedirect(routeData)) {
pages.add(routeData);
continue;
}
if (routeIsFallback(routeData) && i18nHasFallback(this.manifest)) {
pages.add(routeData);
continue;
}
if (defaultRouteComponents.has(routeData.component)) {
continue;
}
pages.add(routeData);
const moduleSpecifier = getVirtualModulePageName(
VIRTUAL_PAGE_RESOLVED_MODULE_ID,
routeData.component
);
const filePath = this.internals?.entrySpecifierToBundleMap.get(moduleSpecifier);
if (filePath) {
this.#routesByFilePath.set(routeData, filePath);
}
}
return pages;
}
async getComponentByRoute(routeData) {
const module = await this.getModuleForRoute(routeData);
return module.page();
}
async getModuleForRoute(route) {
for (const defaultRoute of this.defaultRoutes) {
if (route.component === defaultRoute.component) {
return {
page: () => Promise.resolve(defaultRoute.instance)
};
}
}
let routeToProcess = route;
if (routeIsRedirect(route)) {
if (route.redirectRoute) {
routeToProcess = route.redirectRoute;
} else {
return RedirectSinglePageBuiltModule;
}
} else if (routeIsFallback(route)) {
routeToProcess = getFallbackRoute(route, this.manifest.routes);
}
if (this.manifest.pageMap) {
const importComponentInstance = this.manifest.pageMap.get(routeToProcess.component);
if (!importComponentInstance) {
throw new Error(
`Unexpectedly unable to find a component instance for route ${route.route}`
);
}
return await importComponentInstance();
} else if (this.manifest.pageModule) {
return this.manifest.pageModule;
}
throw new Error(
"Astro couldn't find the correct page to render, probably because it wasn't correctly mapped for SSR usage. This is an internal error, please file an issue."
);
}
async tryRewrite(payload, request) {
const { routeData, pathname, newUrl } = findRouteToRewrite({
payload,
request,
routes: this.manifest.routes.map((routeInfo) => routeInfo.routeData),
trailingSlash: this.manifest.trailingSlash,
buildFormat: this.manifest.buildFormat,
base: this.manifest.base,
outDir: this.manifest.serverLike ? this.manifest.buildClientDir : this.manifest.outDir
});
const componentInstance = await this.getComponentByRoute(routeData);
return { routeData, componentInstance, newUrl, pathname };
}
}
function i18nHasFallback(manifest) {
if (manifest.i18n && manifest.i18n.fallback) {
return Object.keys(manifest.i18n.fallback).length > 0;
}
return false;
}
export {
BuildPipeline
};

View File

@@ -0,0 +1,4 @@
import type { Plugin as VitePlugin } from 'vite';
import type { BuildInternals } from '../internal.js';
import type { StaticBuildOptions } from '../types.js';
export declare function getAllBuildPlugins(internals: BuildInternals, options: StaticBuildOptions): Array<VitePlugin | VitePlugin[] | undefined>;

33
node_modules/astro/dist/core/build/plugins/index.js generated vendored Normal file
View File

@@ -0,0 +1,33 @@
import { vitePluginActionsBuild } from "../../../actions/vite-plugin-actions.js";
import { astroHeadBuildPlugin } from "../../../vite-plugin-head/index.js";
import { pluginAnalyzer } from "./plugin-analyzer.js";
import { pluginComponentEntry } from "./plugin-component-entry.js";
import { pluginCSS } from "./plugin-css.js";
import { pluginInternals } from "./plugin-internals.js";
import { pluginMiddleware } from "./plugin-middleware.js";
import { pluginPrerender } from "./plugin-prerender.js";
import { pluginScripts } from "./plugin-scripts.js";
import { pluginSSR } from "./plugin-ssr.js";
import { pluginChunkImports } from "./plugin-chunk-imports.js";
import { pluginNoop } from "./plugin-noop.js";
import { vitePluginSSRAssets } from "../vite-plugin-ssr-assets.js";
function getAllBuildPlugins(internals, options) {
return [
pluginComponentEntry(internals),
pluginAnalyzer(internals),
pluginInternals(options, internals),
pluginMiddleware(options, internals),
vitePluginActionsBuild(options, internals),
...pluginCSS(options, internals),
astroHeadBuildPlugin(internals),
pluginPrerender(options, internals),
pluginScripts(internals),
...pluginSSR(options, internals),
pluginNoop(),
vitePluginSSRAssets(internals),
pluginChunkImports(options)
].filter(Boolean);
}
export {
getAllBuildPlugins
};

View File

@@ -0,0 +1,3 @@
import type { Plugin as VitePlugin } from 'vite';
import type { BuildInternals } from '../internal.js';
export declare function pluginAnalyzer(internals: BuildInternals): VitePlugin;

View File

@@ -0,0 +1,80 @@
import { getTopLevelPageModuleInfos } from "../graph.js";
import {
getPageDataByViteID,
trackClientOnlyPageDatas,
trackHydratedComponentPageDatas,
trackScriptPageDatas
} from "../internal.js";
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
function pluginAnalyzer(internals) {
return {
name: "@astro/rollup-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);
}
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);
}
}
if (astro.scripts.length) {
const scriptIds = astro.scripts.map(
(_, i) => `${id.replace("/@fs", "")}?astro&type=script&index=${i}&lang.ts`
);
for (const scriptId of scriptIds) {
internals.discoveredScripts.add(scriptId);
}
for (const pageInfo of getTopLevelPageModuleInfos(id, this)) {
const newPageData = getPageDataByViteID(internals, pageInfo.id);
if (!newPageData) continue;
trackScriptPageDatas(internals, newPageData, scriptIds);
}
}
}
}
};
}
export {
pluginAnalyzer
};

View File

@@ -0,0 +1,10 @@
import type { Plugin as VitePlugin } from 'vite';
import type { StaticBuildOptions } from '../types.js';
/**
* Appends assetQueryParams (e.g., ?dpl=<VERCEL_DEPLOYMENT_ID>) to relative
* JS import paths inside client chunks. Without this, inter-chunk imports
* bypass the HTML rendering pipeline and miss skew protection query params.
*
* Uses es-module-lexer to reliably parse both static and dynamic imports.
*/
export declare function pluginChunkImports(options: StaticBuildOptions): VitePlugin | undefined;

View File

@@ -0,0 +1,39 @@
import { init, parse } from "es-module-lexer";
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
function pluginChunkImports(options) {
const assetQueryParams = options.settings.adapter?.client?.assetQueryParams;
if (!assetQueryParams || assetQueryParams.toString() === "") {
return void 0;
}
const queryString = assetQueryParams.toString();
return {
name: "@astro/plugin-chunk-imports",
enforce: "post",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client;
},
async renderChunk(code, _chunk) {
if (!code.includes("./")) {
return null;
}
await init;
const [imports] = parse(code);
const relativeImports = imports.filter(
(imp) => imp.n && /^\.\.?\//.test(imp.n) && /\.(?:js|mjs)$/.test(imp.n)
);
if (relativeImports.length === 0) {
return null;
}
let rewritten = code;
for (let i = relativeImports.length - 1; i >= 0; i--) {
const imp = relativeImports[i];
const insertAt = imp.d > -1 ? imp.e - 1 : imp.e;
rewritten = rewritten.slice(0, insertAt) + "?" + queryString + rewritten.slice(insertAt);
}
return { code: rewritten, map: null };
}
};
}
export {
pluginChunkImports
};

View File

@@ -0,0 +1,9 @@
import type { Plugin as VitePlugin } from 'vite';
import type { BuildInternals } from '../internal.js';
/**
* When adding hydrated or client:only components as Rollup inputs, sometimes we're not using all
* of the export names, e.g. `import { Counter } from './ManyComponents.jsx'`. This plugin proxies
* entries to re-export only the names that the user is using.
*/
export declare function pluginComponentEntry(internals: BuildInternals): VitePlugin;
export declare function normalizeEntryId(id: string): string;

View File

@@ -0,0 +1,71 @@
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
const astroEntryPrefix = "\0astro-entry:";
function pluginComponentEntry(internals) {
const componentToExportNames = /* @__PURE__ */ new Map();
mergeComponentExportNames(internals.discoveredHydratedComponents);
mergeComponentExportNames(internals.discoveredClientOnlyComponents);
for (const [componentId, exportNames] of componentToExportNames) {
if (exportNames.some((name) => name.includes(".") || name === "*")) {
componentToExportNames.delete(componentId);
} else {
componentToExportNames.set(componentId, Array.from(new Set(exportNames)));
}
}
function mergeComponentExportNames(components) {
for (const [componentId, exportNames] of components) {
if (componentToExportNames.has(componentId)) {
componentToExportNames.get(componentId)?.push(...exportNames);
} else {
componentToExportNames.set(componentId, exportNames);
}
}
}
return {
name: "@astro/plugin-component-entry",
enforce: "pre",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client;
},
config(config) {
const rollupInput = config.build?.rollupOptions?.input;
if (Array.isArray(rollupInput)) {
config.build.rollupOptions.input = rollupInput.map((id) => {
if (componentToExportNames.has(id)) {
return astroEntryPrefix + id;
} else {
return id;
}
});
}
},
resolveId: {
filter: {
id: new RegExp(`^${astroEntryPrefix}`)
},
handler(id) {
return id;
}
},
load: {
filter: {
id: new RegExp(`^${astroEntryPrefix}`)
},
async handler(id) {
const componentId = id.slice(astroEntryPrefix.length);
const exportNames = componentToExportNames.get(componentId);
if (exportNames) {
return {
code: `export { ${exportNames.join(", ")} } from ${JSON.stringify(componentId)}`
};
}
}
}
};
}
function normalizeEntryId(id) {
return id.startsWith(astroEntryPrefix) ? id.slice(astroEntryPrefix.length) : id;
}
export {
normalizeEntryId,
pluginComponentEntry
};

View File

@@ -0,0 +1,5 @@
import type { Plugin as VitePlugin } from 'vite';
import type { BuildInternals } from '../internal.js';
import type { StaticBuildOptions } from '../types.js';
/***** ASTRO PLUGIN *****/
export declare function pluginCSS(options: StaticBuildOptions, internals: BuildInternals): VitePlugin[];

View File

@@ -0,0 +1,341 @@
import { isCSSRequest } from "vite";
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
import { isPropagatedAssetBoundary } from "../../head-propagation/boundary.js";
import { VIRTUAL_PAGE_RESOLVED_MODULE_ID } from "../../../vite-plugin-pages/const.js";
import {
getParentExtendedModuleInfos,
getParentModuleInfos,
moduleIsTopLevelPage
} from "../graph.js";
import { getPageDataByViteID, getPageDatasByClientOnlyID } from "../internal.js";
import { normalizeEntryId } from "./plugin-component-entry.js";
import { shouldInlineAsset } from "./util.js";
function pluginCSS(options, internals) {
return rollupPluginAstroBuildCSS({
buildOptions: options,
internals
});
}
function isBuildCssBoundary(id, ctx) {
if (isPropagatedAssetBoundary(id)) return true;
const info = ctx.getModuleInfo(id);
if (!info || !moduleIsTopLevelPage(info)) return false;
const allImporters = info.importers.concat(info.dynamicImporters);
const hasNonVirtualPageImporter = allImporters.some(
(importer) => !importer.includes(VIRTUAL_PAGE_RESOLVED_MODULE_ID)
);
return !hasNonVirtualPageImporter;
}
function rollupPluginAstroBuildCSS(options) {
const { internals, buildOptions } = options;
const { settings } = buildOptions;
let resolvedConfig;
const pagesToCss = {};
const moduleIdToPropagatedCss = {};
const cssBuildPlugin = {
name: "astro:rollup-plugin-build-css",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender;
},
async generateBundle(_outputOptions, bundle) {
if (this.environment?.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || this.environment?.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender) {
for (const [, chunk] of Object.entries(bundle)) {
if (chunk.type !== "chunk") continue;
for (const moduleId of Object.keys(chunk.modules || {})) {
if (isCSSRequest(moduleId)) {
internals.cssModuleToChunkIdMap.set(moduleId, chunk.fileName);
}
}
}
}
const renderedComponentExports = /* @__PURE__ */ new Map();
const componentToPages = /* @__PURE__ */ new Map();
if (this.environment?.name === ASTRO_VITE_ENVIRONMENT_NAMES.client) {
for (const [, item] of Object.entries(bundle)) {
if (item.type !== "chunk") continue;
for (const [moduleId, moduleRenderedInfo] of Object.entries(item.modules)) {
if (moduleRenderedInfo.renderedExports.length > 0) {
renderedComponentExports.set(moduleId, moduleRenderedInfo.renderedExports);
if (item.facadeModuleId) {
let pages = componentToPages.get(moduleId);
if (!pages) {
pages = /* @__PURE__ */ new Set();
componentToPages.set(moduleId, pages);
}
pages.add(item.facadeModuleId);
}
}
}
if ("viteMetadata" in item === false) continue;
const meta = item.viteMetadata;
const allModules = Object.keys(item.modules || {});
const cssModules = allModules.filter((m) => isCSSRequest(m));
if (cssModules.length > 0) {
const allCssInSSR = cssModules.every(
(moduleId) => internals.cssModuleToChunkIdMap.has(moduleId)
);
if (allCssInSSR && shouldDeleteCSSChunk(allModules, internals)) {
for (const cssId of meta.importedCss) {
delete bundle[cssId];
}
}
}
}
}
for (const [, chunk] of Object.entries(bundle)) {
if (chunk.type !== "chunk") continue;
if ("viteMetadata" in chunk === false) continue;
const meta = chunk.viteMetadata;
if (meta.importedCss.size < 1) continue;
if (this.environment?.name === ASTRO_VITE_ENVIRONMENT_NAMES.client) {
for (const id of Object.keys(chunk.modules)) {
for (const pageData of getParentClientOnlys(id, this, internals)) {
for (const importedCssImport of meta.importedCss) {
const cssToInfoRecord = pagesToCss[pageData.moduleSpecifier] ??= {};
cssToInfoRecord[importedCssImport] = { depth: -1, order: -1 };
}
}
}
for (const id of Object.keys(chunk.modules)) {
const moduleInfo = this.getModuleInfo(id);
const cssScopeTo = moduleInfo?.meta?.vite?.cssScopeTo;
if (cssScopeTo) {
const [scopedToModule, scopedToExport] = cssScopeTo;
const renderedExports = renderedComponentExports.get(scopedToModule);
if (renderedExports?.includes(scopedToExport)) {
const parentModuleInfos = getParentExtendedModuleInfos(
scopedToModule,
this,
(moduleId) => isBuildCssBoundary(moduleId, this)
);
for (const { info: pageInfo, depth, order } of parentModuleInfos) {
if (moduleIsTopLevelPage(pageInfo)) {
const pageData = getPageDataByViteID(internals, pageInfo.id);
if (pageData) {
appendCSSToPage(
pageData,
meta,
pagesToCss,
depth,
order,
this.environment?.name
);
}
}
const pageDatas = internals.pagesByScriptId.get(pageInfo.id);
if (pageDatas) {
for (const pageData of pageDatas) {
appendCSSToPage(
pageData,
meta,
pagesToCss,
-1,
order,
this.environment?.name
);
}
}
}
let addedToAnyPage = false;
for (const importedCssImport of meta.importedCss) {
for (const pageData of internals.pagesByKeys.values()) {
const cssToInfoRecord = pagesToCss[pageData.moduleSpecifier];
if (cssToInfoRecord && importedCssImport in cssToInfoRecord) {
addedToAnyPage = true;
break;
}
}
}
if (!addedToAnyPage) {
for (const { info: parentInfo } of parentModuleInfos) {
const normalizedParent = normalizeEntryId(parentInfo.id);
const pages = internals.pagesByHydratedComponent.get(normalizedParent);
if (pages) {
for (const pageData of pages) {
appendCSSToPage(pageData, meta, pagesToCss, -1, -1, this.environment?.name);
}
}
}
}
}
}
}
}
for (const id of Object.keys(chunk.modules)) {
if (!isCSSRequest(id)) continue;
const parentModuleInfos = getParentExtendedModuleInfos(
id,
this,
(importer) => isBuildCssBoundary(importer, this)
);
for (const { info: pageInfo, depth, order } of parentModuleInfos) {
if (isPropagatedAssetBoundary(pageInfo.id)) {
const propagatedCss = moduleIdToPropagatedCss[pageInfo.id] ??= /* @__PURE__ */ new Set();
for (const css of meta.importedCss) {
propagatedCss.add(css);
}
} else if (moduleIsTopLevelPage(pageInfo)) {
const pageViteID = pageInfo.id;
const pageData = getPageDataByViteID(internals, pageViteID);
if (pageData) {
appendCSSToPage(pageData, meta, pagesToCss, depth, order, this.environment?.name);
}
} else if (this.environment?.name === ASTRO_VITE_ENVIRONMENT_NAMES.client) {
const pageDatas = internals.pagesByScriptId.get(pageInfo.id);
if (pageDatas) {
for (const pageData of pageDatas) {
appendCSSToPage(pageData, meta, pagesToCss, -1, order, this.environment?.name);
}
}
}
}
}
}
}
};
const singleCssPlugin = {
name: "astro:rollup-plugin-single-css",
enforce: "post",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender;
},
configResolved(config) {
resolvedConfig = config;
},
generateBundle(_, bundle) {
if (resolvedConfig.build.cssCodeSplit) return;
const cssChunk = Object.values(bundle).find(
(chunk) => chunk.type === "asset" && chunk.name === "style.css"
);
if (cssChunk === void 0) return;
for (const pageData of internals.pagesByKeys.values()) {
const cssToInfoMap = pagesToCss[pageData.moduleSpecifier] ??= {};
cssToInfoMap[cssChunk.fileName] = { depth: -1, order: -1 };
}
}
};
let assetsInlineLimit;
const inlineStylesheetsPlugin = {
name: "astro:rollup-plugin-inline-stylesheets",
enforce: "post",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender;
},
configResolved(config) {
assetsInlineLimit = config.build.assetsInlineLimit;
},
async generateBundle(_outputOptions, bundle) {
const inlineConfig = settings.config.build.inlineStylesheets;
Object.entries(bundle).forEach(([id, stylesheet]) => {
if (stylesheet.type !== "asset" || stylesheet.name?.endsWith(".css") !== true || typeof stylesheet.source !== "string")
return;
if (stylesheet.source.length === 0) {
delete bundle[id];
return;
}
const toBeInlined = inlineConfig === "always" ? true : inlineConfig === "never" ? false : shouldInlineAsset(stylesheet.source, stylesheet.fileName, assetsInlineLimit);
const sheet = toBeInlined ? { type: "inline", content: stylesheet.source } : { type: "external", src: stylesheet.fileName };
let sheetAddedToPage = false;
internals.pagesByKeys.forEach((pageData) => {
const orderingInfo = pagesToCss[pageData.moduleSpecifier]?.[stylesheet.fileName];
if (orderingInfo !== void 0) {
const alreadyAdded = pageData.styles.some((s) => {
if (s.sheet.type === "external" && sheet.type === "external") {
return s.sheet.src === sheet.src;
}
if (s.sheet.type === "inline" && sheet.type === "inline") {
return s.sheet.content === sheet.content;
}
return false;
});
if (!alreadyAdded) {
pageData.styles.push({ ...orderingInfo, sheet });
}
sheetAddedToPage = true;
}
});
for (const moduleId in moduleIdToPropagatedCss) {
if (!moduleIdToPropagatedCss[moduleId].has(stylesheet.fileName)) continue;
let propagatedStyles = internals.propagatedStylesMap.get(moduleId);
if (!propagatedStyles) {
propagatedStyles = /* @__PURE__ */ new Set();
internals.propagatedStylesMap.set(moduleId, propagatedStyles);
}
propagatedStyles.add(sheet);
sheetAddedToPage = true;
}
const wasInlined = toBeInlined && sheetAddedToPage;
const wasAddedToChunk = Object.values(bundle).some(
(chunk) => chunk.type === "chunk" && chunk.viteMetadata?.importedAssets?.has(id)
);
const isOrphaned = !sheetAddedToPage && !wasAddedToChunk;
if (wasInlined || isOrphaned) {
delete bundle[id];
for (const chunk of Object.values(bundle)) {
if (chunk.type === "chunk") {
chunk.viteMetadata?.importedCss?.delete(id);
}
}
}
});
}
};
return [cssBuildPlugin, singleCssPlugin, inlineStylesheetsPlugin];
}
function shouldDeleteCSSChunk(allModules, internals) {
const componentPaths = /* @__PURE__ */ new Set();
for (const componentPath of internals.discoveredClientOnlyComponents.keys()) {
if (allModules.some((m) => m.includes(componentPath))) {
componentPaths.add(componentPath);
}
}
for (const componentPath of internals.discoveredHydratedComponents.keys()) {
if (allModules.some((m) => m.includes(componentPath))) {
componentPaths.add(componentPath);
}
}
if (componentPaths.size === 0) return false;
for (const componentPath of componentPaths) {
const pagesUsingClientOnly = internals.pagesByClientOnly.get(componentPath);
if (pagesUsingClientOnly) {
for (const pageData of internals.pagesByKeys.values()) {
if (!pagesUsingClientOnly.has(pageData)) {
return false;
}
}
}
}
return true;
}
function* getParentClientOnlys(id, ctx, internals) {
for (const info of getParentModuleInfos(id, ctx)) {
yield* getPageDatasByClientOnlyID(internals, info.id);
}
}
function appendCSSToPage(pageData, meta, pagesToCss, depth, order, environmentName) {
if (environmentName === ASTRO_VITE_ENVIRONMENT_NAMES.ssr && pageData.route.prerender) {
return;
}
if (environmentName === ASTRO_VITE_ENVIRONMENT_NAMES.prerender && !pageData.route.prerender) {
return;
}
for (const importedCssImport of meta.importedCss) {
const cssInfo = pagesToCss[pageData.moduleSpecifier]?.[importedCssImport];
if (cssInfo !== void 0) {
if (depth < cssInfo.depth) {
cssInfo.depth = depth;
}
if (cssInfo.order === -1) {
cssInfo.order = order;
} else if (order < cssInfo.order && order > -1) {
cssInfo.order = order;
}
} else {
const cssToInfoRecord = pagesToCss[pageData.moduleSpecifier] ??= {};
cssToInfoRecord[importedCssImport] = { depth, order };
}
}
}
export {
pluginCSS
};

View File

@@ -0,0 +1,4 @@
import type { Plugin as VitePlugin } from 'vite';
import type { BuildInternals } from '../internal.js';
import type { StaticBuildOptions } from '../types.js';
export declare function pluginInternals(options: StaticBuildOptions, internals: BuildInternals): VitePlugin;

View File

@@ -0,0 +1,75 @@
import { normalizeEntryId } from "./plugin-component-entry.js";
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
function getRollupInputAsSet(rollupInput) {
if (Array.isArray(rollupInput)) {
return new Set(rollupInput);
} else if (typeof rollupInput === "string") {
return /* @__PURE__ */ new Set([rollupInput]);
} else if (rollupInput && typeof rollupInput === "object") {
return new Set(Object.values(rollupInput));
} else {
return /* @__PURE__ */ new Set();
}
}
function pluginInternals(options, internals) {
return {
name: "@astro/plugin-build-internals",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender;
},
configEnvironment(environmentName) {
if (environmentName === ASTRO_VITE_ENVIRONMENT_NAMES.prerender) {
return {
build: {
rollupOptions: {
// These packages as they're not bundle-friendly. Users with strict package installations
// need to manually install these themselves if they use the related features.
external: [
"sharp"
// For sharp image service
]
}
},
resolve: {
// Always bundle Astro runtime when building for SSR
noExternal: ["astro"]
}
};
}
},
async generateBundle(_options, bundle) {
const input = getRollupInputAsSet(this.environment?.config.build.rollupOptions.input);
const promises = [];
const mapping = /* @__PURE__ */ new Map();
const allInput = /* @__PURE__ */ new Set([...input, ...internals.clientInput]);
for (const specifier of allInput) {
promises.push(
this.resolve(specifier).then((result) => {
if (result) {
if (mapping.has(result.id)) {
mapping.get(result.id).add(specifier);
} else {
mapping.set(result.id, /* @__PURE__ */ new Set([specifier]));
}
}
})
);
}
await Promise.all(promises);
for (const [_, chunk] of Object.entries(bundle)) {
if (chunk.fileName.startsWith(options.settings.config.build.assets)) {
internals.clientChunksAndAssets.add(chunk.fileName);
}
if (chunk.type === "chunk" && chunk.facadeModuleId) {
const specifiers = mapping.get(chunk.facadeModuleId) || /* @__PURE__ */ new Set([chunk.facadeModuleId]);
for (const specifier of specifiers) {
internals.entrySpecifierToBundleMap.set(normalizeEntryId(specifier), chunk.fileName);
}
}
}
}
};
}
export {
pluginInternals
};

View File

@@ -0,0 +1,32 @@
import type { ExtractedChunk } from '../static-build.js';
import type { BuildInternals } from '../internal.js';
import type { StaticBuildOptions } from '../types.js';
/**
* Unified manifest system architecture:
*
* The serialized manifest (virtual:astro:manifest) is now the single source of truth
* for both dev and production builds:
*
* - In dev: The serialized manifest is used directly (pre-computed manifest data)
* - In prod: Two-stage process:
* 1. serialized.ts emits a placeholder (MANIFEST_REPLACE token) during bundling
* 2. plugin-manifest injects the real build-specific data at the end
*
* This flow eliminates dual virtual modules and simplifies the architecture:
* - pluginManifestBuild: Registers SERIALIZED_MANIFEST_ID as Vite input
* - pluginManifestBuild.generateBundle: Tracks the serialized manifest chunk filename
* - manifestBuildPostHook: Finds the chunk, computes final manifest data, and replaces the token
*
* The placeholder mechanism allows serialized.ts to emit during vite build without knowing
* the final build-specific data (routes, assets, CSP hashes, etc) that's only available
* after bundling completes.
*/
export declare const MANIFEST_REPLACE = "@@ASTRO_MANIFEST_REPLACE@@";
/**
* Post-build hook that injects the computed manifest into bundled chunks.
* Finds the serialized manifest chunk and replaces the placeholder token with real data.
*/
export declare function manifestBuildPostHook(options: StaticBuildOptions, internals: BuildInternals, { chunks, mutate, }: {
chunks: ExtractedChunk[];
mutate: (fileName: string, code: string, prerender: boolean) => void;
}): Promise<void>;

View File

@@ -0,0 +1,291 @@
import { fileURLToPath } from "node:url";
import { glob } from "tinyglobby";
import { getAssetsPrefix } from "../../../assets/utils/getAssetsPrefix.js";
import { normalizeTheLocale } from "../../../i18n/index.js";
import { resolveMiddlewareMode } from "../../../integrations/adapter-utils.js";
import { runHookBuildSsr } from "../../../integrations/hooks.js";
import { SERIALIZED_MANIFEST_RESOLVED_ID } from "../../../manifest/serialized.js";
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from "../../../vite-plugin-scripts/index.js";
import { toFallbackType } from "../../app/common.js";
import { serializeRouteData, toRoutingStrategy } from "../../app/entrypoints/index.js";
import {
getAlgorithm,
getDirectives,
getScriptHashes,
getScriptResources,
getStrictDynamic,
getStyleHashes,
getStyleResources,
shouldTrackCspHashes,
trackScriptHashes,
trackStyleHashes
} from "../../csp/common.js";
import { encodeKey } from "../../encryption.js";
import { fileExtension, joinPaths, prependForwardSlash } from "../../path.js";
import { DEFAULT_COMPONENTS } from "../../routing/default.js";
import { getOutFile, getOutFolder } from "../common.js";
import { cssOrder, mergeInlineCss } from "../runtime.js";
import { makePageDataKey } from "./util.js";
import { cacheConfigToManifest } from "../../cache/utils.js";
import { sessionConfigToManifest } from "../../session/utils.js";
const MANIFEST_REPLACE = "@@ASTRO_MANIFEST_REPLACE@@";
const replaceExp = new RegExp(`['"]${MANIFEST_REPLACE}['"]`, "g");
async function manifestBuildPostHook(options, internals, {
chunks,
mutate
}) {
const manifest = await createManifest(options, internals);
const ssrManifestChunk = chunks.find(
(c) => !c.prerender && c.moduleIds.includes(SERIALIZED_MANIFEST_RESOLVED_ID)
);
if (ssrManifestChunk) {
const middlewareMode = resolveMiddlewareMode(options.settings.adapter?.adapterFeatures);
const shouldPassMiddlewareEntryPoint = middlewareMode === "edge";
await runHookBuildSsr({
config: options.settings.config,
manifest,
logger: options.logger,
middlewareEntryPoint: shouldPassMiddlewareEntryPoint ? internals.middlewareEntryPoint : void 0
});
const ssrManifest = stripPrerenderedRouteStyles(manifest);
const code = injectManifest(ssrManifest, ssrManifestChunk.code);
mutate(ssrManifestChunk.fileName, code, false);
}
const prerenderManifestChunk = chunks.find(
(c) => c.prerender && c.moduleIds.includes(SERIALIZED_MANIFEST_RESOLVED_ID)
);
if (prerenderManifestChunk) {
const code = injectManifest(manifest, prerenderManifestChunk.code);
mutate(prerenderManifestChunk.fileName, code, true);
}
}
async function createManifest(buildOpts, internals) {
const clientStatics = new Set(
await glob("**/*", {
cwd: fileURLToPath(buildOpts.settings.config.build.client)
})
);
for (const file of clientStatics) {
internals.staticFiles.add(file);
}
for (const [, ssrAssets] of internals.ssrAssetsPerEnvironment) {
for (const asset of ssrAssets) {
internals.staticFiles.add(asset);
}
}
const staticFiles = internals.staticFiles;
const encodedKey = await encodeKey(await buildOpts.key);
const manifest = await buildManifest(buildOpts, internals, Array.from(staticFiles), encodedKey);
return manifest;
}
function injectManifest(manifest, code) {
return code.replace(replaceExp, () => {
return JSON.stringify(manifest);
});
}
function stripPrerenderedRouteStyles(manifest) {
let stripped = false;
const routes = manifest.routes.map((route) => {
if (!route.routeData.prerender || route.styles.length === 0) return route;
stripped = true;
return { ...route, styles: [] };
});
return stripped ? { ...manifest, routes } : manifest;
}
async function buildManifest(opts, internals, staticFiles, encodedKey) {
const { settings } = opts;
const routes = [];
const domainLookupTable = {};
const rawEntryModules = Object.fromEntries(internals.entrySpecifierToBundleMap.entries());
const assetQueryParams = settings.adapter?.client?.assetQueryParams;
const assetQueryString = assetQueryParams ? assetQueryParams.toString() : void 0;
const appendAssetQuery = (pth) => assetQueryString ? `${pth}?${assetQueryString}` : pth;
const entryModules = Object.fromEntries(
Object.entries(rawEntryModules).map(([key, value]) => [
key,
value ? appendAssetQuery(value) : value
])
);
if (settings.scripts.some((script) => script.stage === "page")) {
staticFiles.push(rawEntryModules[PAGE_SCRIPT_ID]);
}
const prefixAssetPath = (pth) => {
let result = "";
if (settings.config.build.assetsPrefix) {
const pf = getAssetsPrefix(fileExtension(pth), settings.config.build.assetsPrefix);
result = joinPaths(pf, pth);
} else {
result = prependForwardSlash(joinPaths(settings.config.base, pth));
}
if (assetQueryString) {
result += "?" + assetQueryString;
}
return result;
};
for (const route of opts.routesList.routes) {
if (!DEFAULT_COMPONENTS.find((component) => route.component === component)) {
continue;
}
routes.push({
file: "",
links: [],
scripts: [],
styles: [],
routeData: serializeRouteData(route, settings.config.trailingSlash)
});
}
for (const route of opts.routesList.routes) {
const pageData = internals.pagesByKeys.get(makePageDataKey(route.route, route.component));
if (!pageData) continue;
const scripts = [];
if (settings.scripts.some((script) => script.stage === "page")) {
const src = rawEntryModules[PAGE_SCRIPT_ID];
scripts.push({
type: "external",
value: appendAssetQuery(src)
});
}
const links = [];
const styles = pageData.styles.sort(cssOrder).map(({ sheet }) => sheet).map((s) => s.type === "external" ? { ...s, src: appendAssetQuery(s.src) } : s).reduce(mergeInlineCss, []);
routes.push({
file: "",
links,
scripts: [
...scripts,
...settings.scripts.filter((script) => script.stage === "head-inline").map(({ stage, content }) => ({ stage, children: content }))
],
styles,
routeData: serializeRouteData(route, settings.config.trailingSlash)
});
if (route.prerender && route.pathname) {
const outFolder = getOutFolder(opts.settings, route.pathname, route);
const outFile = getOutFile(
opts.settings.config.build.format,
outFolder,
route.pathname,
route
);
const file = outFile.toString().replace(opts.settings.config.build.client.toString(), "");
staticFiles.push(file);
}
}
const i18n = settings.config.i18n;
if (i18n && i18n.domains) {
for (const [locale, domainValue] of Object.entries(i18n.domains)) {
domainLookupTable[domainValue] = normalizeTheLocale(locale);
}
}
if (!(BEFORE_HYDRATION_SCRIPT_ID in entryModules)) {
entryModules[BEFORE_HYDRATION_SCRIPT_ID] = "";
}
let i18nManifest = void 0;
if (settings.config.i18n) {
i18nManifest = {
fallback: settings.config.i18n.fallback,
fallbackType: toFallbackType(settings.config.i18n.routing),
strategy: toRoutingStrategy(settings.config.i18n.routing, settings.config.i18n.domains),
locales: settings.config.i18n.locales,
defaultLocale: settings.config.i18n.defaultLocale,
domainLookupTable,
domains: settings.config.i18n.domains
};
}
let csp = void 0;
if (shouldTrackCspHashes(settings.config.security.csp)) {
const algorithm = getAlgorithm(settings.config.security.csp);
const scriptHashes = [
...getScriptHashes(settings.config.security.csp),
...await trackScriptHashes(internals, settings, algorithm)
];
const styleHashes = [
...getStyleHashes(settings.config.security.csp),
...settings.injectedCsp.styleHashes,
...await trackStyleHashes(internals, settings, algorithm)
];
csp = {
cspDestination: settings.adapter?.adapterFeatures?.staticHeaders ? "adapter" : void 0,
scriptHashes,
scriptResources: getScriptResources(settings.config.security.csp),
styleHashes,
styleResources: getStyleResources(settings.config.security.csp),
algorithm,
directives: getDirectives(settings),
isStrictDynamic: getStrictDynamic(settings.config.security.csp)
};
}
let internalFetchHeaders = void 0;
if (settings.adapter?.client?.internalFetchHeaders) {
const headers = typeof settings.adapter.client.internalFetchHeaders === "function" ? settings.adapter.client.internalFetchHeaders() : settings.adapter.client.internalFetchHeaders;
if (Object.keys(headers).length > 0) {
internalFetchHeaders = headers;
}
}
const middlewareMode = resolveMiddlewareMode(opts.settings.adapter?.adapterFeatures);
let experimentalLogger = void 0;
if (settings.config.experimental.logger) {
experimentalLogger = settings.config.experimental.logger;
}
return {
rootDir: opts.settings.config.root.toString(),
cacheDir: opts.settings.config.cacheDir.toString(),
outDir: opts.settings.config.outDir.toString(),
srcDir: opts.settings.config.srcDir.toString(),
publicDir: opts.settings.config.publicDir.toString(),
buildClientDir: opts.settings.config.build.client.toString(),
buildServerDir: opts.settings.config.build.server.toString(),
adapterName: opts.settings.adapter?.name ?? "",
assetsDir: opts.settings.config.build.assets,
routes,
serverLike: opts.settings.buildOutput === "server",
middlewareMode,
site: settings.config.site,
base: settings.config.base,
userAssetsBase: settings.config?.vite?.base,
trailingSlash: settings.config.trailingSlash,
compressHTML: settings.config.compressHTML,
assetsPrefix: settings.config.build.assetsPrefix,
experimentalQueuedRendering: {
enabled: settings.config.experimental.queuedRendering?.enabled ?? false,
poolSize: 0,
contentCache: false
},
componentMetadata: Array.from(internals.componentMetadata),
renderers: [],
clientDirectives: Array.from(settings.clientDirectives),
entryModules,
inlinedScripts: Array.from(internals.inlinedScripts),
assets: staticFiles.map(prefixAssetPath),
i18n: i18nManifest,
buildFormat: settings.config.build.format,
checkOrigin: (settings.config.security?.checkOrigin && settings.buildOutput === "server") ?? false,
actionBodySizeLimit: settings.config.security?.actionBodySizeLimit && settings.buildOutput === "server" ? settings.config.security.actionBodySizeLimit : 1024 * 1024,
serverIslandBodySizeLimit: settings.config.security?.serverIslandBodySizeLimit && settings.buildOutput === "server" ? settings.config.security.serverIslandBodySizeLimit : 1024 * 1024,
allowedDomains: settings.config.security?.allowedDomains,
key: encodedKey,
sessionConfig: sessionConfigToManifest(settings.config.session),
cacheConfig: cacheConfigToManifest(
settings.config.experimental?.cache,
settings.config.experimental?.routeRules
),
csp,
image: {
objectFit: settings.config.image.objectFit,
objectPosition: settings.config.image.objectPosition,
layout: settings.config.image.layout
},
devToolbar: {
enabled: false,
latestAstroVersion: void 0,
debugInfoOutput: "",
placement: void 0
},
internalFetchHeaders,
logLevel: settings.logLevel,
shouldInjectCspMetaTags: shouldTrackCspHashes(settings.config.security.csp),
experimentalLogger
};
}
export {
MANIFEST_REPLACE,
manifestBuildPostHook
};

View File

@@ -0,0 +1,4 @@
import type { Plugin as VitePlugin } from 'vite';
import type { BuildInternals } from '../internal.js';
import type { StaticBuildOptions } from '../types.js';
export declare function pluginMiddleware(opts: StaticBuildOptions, internals: BuildInternals): VitePlugin;

View File

@@ -0,0 +1,14 @@
import { vitePluginMiddlewareBuild } from "../../middleware/vite-plugin.js";
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
function pluginMiddleware(opts, internals) {
const plugin = vitePluginMiddlewareBuild(opts, internals);
return {
...plugin,
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr;
}
};
}
export {
pluginMiddleware
};

View File

@@ -0,0 +1,3 @@
import type * as vite from 'vite';
export declare const NOOP_MODULE_ID = "virtual:astro:noop";
export declare function pluginNoop(): vite.Plugin;

View File

@@ -0,0 +1,35 @@
const NOOP_MODULE_ID = "virtual:astro:noop";
const RESOLVED_NOOP_MODULE_ID = "\0" + NOOP_MODULE_ID;
function pluginNoop() {
return {
name: "plugin-noop",
resolveId: {
filter: {
id: new RegExp(`^${NOOP_MODULE_ID}$`)
},
handler() {
return RESOLVED_NOOP_MODULE_ID;
}
},
load: {
filter: {
id: new RegExp(`^${RESOLVED_NOOP_MODULE_ID}$`)
},
handler() {
return "export const noop = {};";
}
},
generateBundle(_options, bundle) {
for (const [name, chunk] of Object.entries(bundle)) {
if (chunk.type === "asset") continue;
if (chunk.facadeModuleId === RESOLVED_NOOP_MODULE_ID) {
delete bundle[name];
}
}
}
};
}
export {
NOOP_MODULE_ID,
pluginNoop
};

View File

@@ -0,0 +1,4 @@
import type { Plugin as VitePlugin } from 'vite';
import type { BuildInternals } from '../internal.js';
import type { StaticBuildOptions } from '../types.js';
export declare function pluginPrerender(_opts: StaticBuildOptions, internals: BuildInternals): VitePlugin;

View File

@@ -0,0 +1,22 @@
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
function pluginPrerender(_opts, internals) {
return {
name: "astro:rollup-plugin-prerender",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr;
},
generateBundle() {
const moduleIds = this.getModuleIds();
for (const id of moduleIds) {
const pageInfo = internals.pagesByViteID.get(id);
if (!pageInfo) continue;
const moduleInfo = this.getModuleInfo(id);
if (!moduleInfo) continue;
pageInfo.route.prerender = Boolean(moduleInfo?.meta?.astro?.pageOptions?.prerender);
}
}
};
}
export {
pluginPrerender
};

View File

@@ -0,0 +1,6 @@
import type { Plugin as VitePlugin } from 'vite';
import type { BuildInternals } from '../internal.js';
/**
* Inline scripts from Astro files directly into the HTML.
*/
export declare function pluginScripts(internals: BuildInternals): VitePlugin;

View File

@@ -0,0 +1,34 @@
import { shouldInlineAsset } from "./util.js";
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
function pluginScripts(internals) {
let assetInlineLimit;
return {
name: "@astro/plugin-scripts",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client;
},
configResolved(config) {
assetInlineLimit = config.build.assetsInlineLimit;
},
async generateBundle(_options, bundle) {
const outputs = Object.values(bundle);
const importedIds = /* @__PURE__ */ new Set();
for (const output of outputs) {
if (output.type === "chunk") {
for (const id of output.imports) {
importedIds.add(id);
}
}
}
for (const output of outputs) {
if (output.type === "chunk" && output.facadeModuleId && internals.discoveredScripts.has(output.facadeModuleId) && !importedIds.has(output.fileName) && output.imports.length === 0 && output.dynamicImports.length === 0 && shouldInlineAsset(output.code, output.fileName, assetInlineLimit)) {
internals.inlinedScripts.set(output.facadeModuleId, output.code.trim());
delete bundle[output.fileName];
}
}
}
};
}
export {
pluginScripts
};

View File

@@ -0,0 +1,12 @@
import type { Plugin as VitePlugin } from 'vite';
import type { AstroAdapter } from '../../../types/public/index.js';
import type { BuildInternals } from '../internal.js';
import type { StaticBuildOptions } from '../types.js';
type LegacyAdapter = Extract<AstroAdapter, {
entrypointResolution?: 'explicit';
}>;
export declare function isLegacyAdapter(adapter: AstroAdapter): adapter is LegacyAdapter;
export declare const LEGACY_SSR_ENTRY_VIRTUAL_MODULE = "virtual:astro:legacy-ssr-entry";
export declare const RESOLVED_LEGACY_SSR_ENTRY_VIRTUAL_MODULE: string;
export declare function pluginSSR(options: StaticBuildOptions, internals: BuildInternals): VitePlugin[];
export {};

View File

@@ -0,0 +1,132 @@
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
function isLegacyAdapter(adapter) {
return adapter.entrypointResolution === void 0 || adapter.entrypointResolution === "explicit";
}
const LEGACY_SSR_ENTRY_VIRTUAL_MODULE = "virtual:astro:legacy-ssr-entry";
const RESOLVED_LEGACY_SSR_ENTRY_VIRTUAL_MODULE = "\0" + LEGACY_SSR_ENTRY_VIRTUAL_MODULE;
const ADAPTER_VIRTUAL_MODULE_ID = "virtual:astro:adapter-entrypoint";
const RESOLVED_ADAPTER_VIRTUAL_MODULE_ID = "\0" + ADAPTER_VIRTUAL_MODULE_ID;
const ADAPTER_CONFIG_VIRTUAL_MODULE_ID = "virtual:astro:adapter-config";
const RESOLVED_ADAPTER_CONFIG_VIRTUAL_MODULE_ID = "\0" + ADAPTER_CONFIG_VIRTUAL_MODULE_ID;
function vitePluginAdapter(adapter) {
return {
name: "@astrojs/vite-plugin-astro-adapter",
enforce: "post",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr;
},
resolveId: {
filter: {
id: new RegExp(`^${ADAPTER_VIRTUAL_MODULE_ID}$`)
},
handler() {
return RESOLVED_ADAPTER_VIRTUAL_MODULE_ID;
}
},
load: {
filter: {
id: new RegExp(`^${RESOLVED_ADAPTER_VIRTUAL_MODULE_ID}$`)
},
async handler() {
const adapterEntrypointStr = JSON.stringify(adapter.serverEntrypoint);
return {
code: `export * from ${adapterEntrypointStr};
import * as _serverEntrypoint from ${adapterEntrypointStr};
export default _serverEntrypoint.default;`
};
}
}
};
}
function vitePluginAdapterConfig(adapter) {
return {
name: "@astrojs/vite-plugin-astro-adapter-config",
enforce: "post",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr;
},
resolveId: {
filter: {
id: new RegExp(`^${ADAPTER_CONFIG_VIRTUAL_MODULE_ID}$`)
},
handler() {
return RESOLVED_ADAPTER_CONFIG_VIRTUAL_MODULE_ID;
}
},
load: {
filter: {
id: new RegExp(`^${RESOLVED_ADAPTER_CONFIG_VIRTUAL_MODULE_ID}$`)
},
handler() {
return {
code: `export const args = ${adapter.args ? JSON.stringify(adapter.args, null, 2) : "undefined"};`
};
}
}
};
}
function vitePluginSSR(internals, adapter) {
return {
name: "@astrojs/vite-plugin-astro-ssr-server",
enforce: "post",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr;
},
resolveId: {
filter: {
id: new RegExp(`^${LEGACY_SSR_ENTRY_VIRTUAL_MODULE}$`)
},
handler() {
return RESOLVED_LEGACY_SSR_ENTRY_VIRTUAL_MODULE;
}
},
load: {
filter: {
id: new RegExp(`^${RESOLVED_LEGACY_SSR_ENTRY_VIRTUAL_MODULE}$`)
},
handler() {
const exports = [];
if (adapter.exports) {
exports.push(
...adapter.exports?.map((name) => {
if (name === "default") {
return `export default _exports.default;`;
} else {
return `export const ${name} = _exports['${name}'];`;
}
}) ?? []
);
}
return {
code: `import _exports from 'astro/entrypoints/legacy';
${exports.join("\n")}`
};
}
},
async generateBundle(_opts, bundle) {
for (const [, chunk] of Object.entries(bundle)) {
if (chunk.type === "asset") {
internals.staticFiles.add(chunk.fileName);
}
}
}
};
}
function pluginSSR(options, internals) {
const adapter = options.settings.adapter;
const ssr = options.settings.buildOutput === "server";
const plugins = [];
if (adapter && isLegacyAdapter(adapter)) {
plugins.push(vitePluginAdapter(adapter), vitePluginAdapterConfig(adapter));
if (ssr) {
plugins.unshift(vitePluginSSR(internals, adapter));
}
}
return plugins;
}
export {
LEGACY_SSR_ENTRY_VIRTUAL_MODULE,
RESOLVED_LEGACY_SSR_ENTRY_VIRTUAL_MODULE,
isLegacyAdapter,
pluginSSR
};

9
node_modules/astro/dist/core/build/plugins/util.d.ts generated vendored Normal file
View File

@@ -0,0 +1,9 @@
import type { BuildOptions } from 'vite';
export declare const ASTRO_PAGE_EXTENSION_POST_PATTERN = "@_@";
/**
* Generate a unique key to identify each page in the build process.
* @param route Usually pageData.route.route
* @param componentPath Usually pageData.component
*/
export declare function makePageDataKey(route: string, componentPath: string): string;
export declare function shouldInlineAsset(assetContent: string, assetPath: string, assetsInlineLimit: NonNullable<BuildOptions['assetsInlineLimit']>): boolean;

21
node_modules/astro/dist/core/build/plugins/util.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
const ASTRO_PAGE_EXTENSION_POST_PATTERN = "@_@";
const ASTRO_PAGE_KEY_SEPARATOR = "&";
function makePageDataKey(route, componentPath) {
return route + ASTRO_PAGE_KEY_SEPARATOR + componentPath;
}
function shouldInlineAsset(assetContent, assetPath, assetsInlineLimit) {
if (typeof assetsInlineLimit === "function") {
const result = assetsInlineLimit(assetPath, Buffer.from(assetContent));
if (result != null) {
return result;
} else {
return Buffer.byteLength(assetContent) < 4096;
}
}
return Buffer.byteLength(assetContent) < Number(assetsInlineLimit);
}
export {
ASTRO_PAGE_EXTENSION_POST_PATTERN,
makePageDataKey,
shouldInlineAsset
};

26
node_modules/astro/dist/core/build/runtime.d.ts generated vendored Normal file
View File

@@ -0,0 +1,26 @@
import type { BuildInternals } from './internal.js';
import type { PageBuildData, StylesheetAsset } from './types.js';
/**
* From its route and component, get the page data from the build internals.
* @param internals Build Internals with all the pages
* @param route The route of the page, used to identify the page
* @param component The component of the page, used to identify the page
*/
export declare function getPageData(internals: BuildInternals, route: string, component: string): PageBuildData | undefined;
interface OrderInfo {
depth: number;
order: number;
}
/**
* Sort a page's CSS by depth. A higher depth means that the CSS comes from shared subcomponents.
* A lower depth means it comes directly from the top-level page.
* Can be used to sort stylesheets so that shared rules come first
* and page-specific rules come after.
*/
export declare function cssOrder(a: OrderInfo, b: OrderInfo): 1 | -1;
/**
* Merges inline CSS into as few stylesheets as possible,
* preserving ordering when there are non-inlined in between.
*/
export declare function mergeInlineCss(acc: Array<StylesheetAsset>, current: StylesheetAsset): Array<StylesheetAsset>;
export {};

45
node_modules/astro/dist/core/build/runtime.js generated vendored Normal file
View File

@@ -0,0 +1,45 @@
import { makePageDataKey } from "./plugins/util.js";
function getPageData(internals, route, component) {
let pageData = internals.pagesByKeys.get(makePageDataKey(route, component));
if (pageData) {
return pageData;
}
return void 0;
}
function cssOrder(a, b) {
let depthA = a.depth, depthB = b.depth, orderA = a.order, orderB = b.order;
if (orderA === -1 && orderB >= 0) {
return 1;
} else if (orderB === -1 && orderA >= 0) {
return -1;
} else if (orderA > orderB) {
return 1;
} else if (orderA < orderB) {
return -1;
} else {
if (depthA === -1) {
return -1;
} else if (depthB === -1) {
return 1;
} else {
return depthA > depthB ? -1 : 1;
}
}
}
function mergeInlineCss(acc, current) {
const lastAdded = acc.at(acc.length - 1);
const lastWasInline = lastAdded?.type === "inline";
const currentIsInline = current?.type === "inline";
if (lastWasInline && currentIsInline) {
const merged = { type: "inline", content: lastAdded.content + current.content };
acc[acc.length - 1] = merged;
return acc;
}
acc.push(current);
return acc;
}
export {
cssOrder,
getPageData,
mergeInlineCss
};

35
node_modules/astro/dist/core/build/static-build.d.ts generated vendored Normal file
View File

@@ -0,0 +1,35 @@
import { type BuildInternals } from '../../core/build/internal.js';
import type { RouteData } from '../../types/public/internal.js';
import type { StaticBuildOptions } from './types.js';
/**
* Minimal chunk data extracted from RollupOutput for deferred manifest/content injection.
* Allows releasing full RollupOutput objects early to reduce memory usage.
*/
export interface ExtractedChunk {
fileName: string;
code: string;
moduleIds: string[];
prerender: boolean;
}
export declare function viteBuild(opts: StaticBuildOptions): Promise<{
internals: BuildInternals;
}>;
/**
* This function takes the virtual module name of any page entrypoint and
* transforms it to generate a final `.mjs` output file.
*
* Input: `@astro-page:src/pages/index@_@astro`
* Output: `pages/index.astro.mjs`
* Input: `@astro-page:../node_modules/my-dep/injected@_@astro`
* Output: `pages/injected.mjs`
*
* 1. We clean the `facadeModuleId` by removing the `ASTRO_PAGE_MODULE_ID` prefix and `ASTRO_PAGE_EXTENSION_POST_PATTERN`.
* 2. We find the matching route pattern in the manifest (or fall back to the cleaned module id)
* 3. We replace square brackets with underscore (`[slug]` => `_slug_`) and `...` with `` (`[...slug]` => `_---slug_`).
* 4. We append the `.mjs` extension, so the file will always be an ESM module
*
* @param prefix string
* @param facadeModuleId string
* @param pages AllPagesData
*/
export declare function makeAstroPageEntryPointFileName(prefix: string, facadeModuleId: string, routes: RouteData[]): string;

447
node_modules/astro/dist/core/build/static-build.js generated vendored Normal file
View File

@@ -0,0 +1,447 @@
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
import colors from "piccolore";
import * as vite from "vite";
import { LINKS_PLACEHOLDER } from "../../content/consts.js";
import { contentAssetsBuildPostHook } from "../../content/vite-plugin-content-assets.js";
import { createBuildInternals } from "../../core/build/internal.js";
import { emptyDir, removeEmptyDirs } from "../../core/fs/index.js";
import { appendForwardSlash, prependForwardSlash } from "../../core/path.js";
import { runHookBuildSetup } from "../../integrations/hooks.js";
import { SERIALIZED_MANIFEST_RESOLVED_ID } from "../../manifest/serialized.js";
import {
getClientOutputDirectory,
getPrerenderOutputDirectory,
getServerOutputDirectory
} from "../../prerender/utils.js";
import { VIRTUAL_PAGE_RESOLVED_MODULE_ID } from "../../vite-plugin-pages/const.js";
import { PAGE_SCRIPT_ID } from "../../vite-plugin-scripts/index.js";
import { routeIsRedirect } from "../routing/helpers.js";
import { getOutDirWithinCwd } from "./common.js";
import { CHUNKS_PATH } from "./consts.js";
import { generatePages } from "./generate.js";
import { trackPageData } from "./internal.js";
import { getAllBuildPlugins } from "./plugins/index.js";
import { manifestBuildPostHook } from "./plugins/plugin-manifest.js";
import {
isLegacyAdapter,
LEGACY_SSR_ENTRY_VIRTUAL_MODULE,
RESOLVED_LEGACY_SSR_ENTRY_VIRTUAL_MODULE
} from "./plugins/plugin-ssr.js";
import { ASTRO_PAGE_EXTENSION_POST_PATTERN } from "./plugins/util.js";
import { cleanChunkName, getTimeStat, viteBuildReturnToRollupOutputs } from "./util.js";
import { NOOP_MODULE_ID } from "./plugins/plugin-noop.js";
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../constants.js";
import { getSSRAssets } from "./internal.js";
import { SERVER_ISLAND_MAP_MARKER } from "../server-islands/vite-plugin-server-islands.js";
const PRERENDER_ENTRY_FILENAME_PREFIX = "prerender-entry";
function extractRelevantChunks(outputs, prerender) {
const extracted = [];
for (const output of outputs) {
for (const chunk of output.output) {
if (chunk.type === "asset") continue;
const needsContentInjection = chunk.code.includes(LINKS_PLACEHOLDER);
const needsManifestInjection = chunk.moduleIds.includes(SERIALIZED_MANIFEST_RESOLVED_ID);
const needsServerIslandInjection = chunk.code.includes(SERVER_ISLAND_MAP_MARKER);
if (needsContentInjection || needsManifestInjection || needsServerIslandInjection) {
extracted.push({
fileName: chunk.fileName,
code: chunk.code,
moduleIds: [...chunk.moduleIds],
prerender
});
}
}
}
return extracted;
}
async function viteBuild(opts) {
const { allPages, settings } = opts;
const pageInput = /* @__PURE__ */ new Set();
const internals = createBuildInternals();
for (const pageData of Object.values(allPages)) {
const astroModuleURL = new URL("./" + pageData.component, settings.config.root);
const astroModuleId = prependForwardSlash(pageData.component);
trackPageData(internals, pageData.component, pageData, astroModuleId, astroModuleURL);
if (!routeIsRedirect(pageData.route)) {
pageInput.add(astroModuleId);
}
}
if (settings.config?.vite?.build?.emptyOutDir !== false) {
emptyDir(settings.config.outDir, new Set(".git"));
}
const ssrTime = performance.now();
opts.logger.info("build", `Building ${settings.buildOutput} entrypoints...`);
await buildEnvironments(opts, internals);
opts.logger.info(
"build",
colors.green(`\u2713 Completed in ${getTimeStat(ssrTime, performance.now())}.`)
);
return { internals };
}
async function buildEnvironments(opts, internals) {
const { allPages, settings, viteConfig } = opts;
const routes = Object.values(allPages).flatMap((pageData) => pageData.route);
const legacyAdapter = !settings.adapter || isLegacyAdapter(settings.adapter);
const buildPlugins = getAllBuildPlugins(internals, opts);
const flatPlugins = buildPlugins.flat().filter(Boolean);
const plugins = [...flatPlugins, ...viteConfig.plugins || []];
let currentRollupInput = void 0;
let buildPostHooks = [];
plugins.push({
name: "astro:resolve-input",
// When the rollup input is safe to update, we normalize it to always be an object
// so we can reliably identify which entrypoint corresponds to the adapter
enforce: "post",
config(config) {
if (typeof config.build?.rollupOptions?.input === "string") {
config.build.rollupOptions.input = { index: config.build.rollupOptions.input };
} else if (Array.isArray(config.build?.rollupOptions?.input)) {
config.build.rollupOptions.input = Object.fromEntries(
config.build.rollupOptions.input.map((v, i) => [`index_${i}`, v])
);
}
},
// We save the rollup input to be able to check later on
configResolved(config) {
currentRollupInput = config.build.rollupOptions.input;
}
});
plugins.push({
name: "astro:build-generate",
enforce: "post",
buildApp: {
order: "post",
async handler() {
await runManifestInjection(
opts,
internals,
internals.extractedChunks ?? [],
buildPostHooks
);
const prerenderOutputDir = getPrerenderOutputDirectory(settings);
if (settings.buildOutput === "static") {
settings.timer.start("Static generate");
await ssrMoveAssets(opts, internals, prerenderOutputDir);
await generatePages(opts, internals, prerenderOutputDir);
await fs.promises.rm(prerenderOutputDir, { recursive: true, force: true });
settings.timer.end("Static generate");
} else if (settings.buildOutput === "server") {
settings.timer.start("Server generate");
await generatePages(opts, internals, prerenderOutputDir);
await ssrMoveAssets(opts, internals, prerenderOutputDir);
await fs.promises.rm(prerenderOutputDir, { recursive: true, force: true });
settings.timer.end("Server generate");
}
}
}
});
function isRollupInput(moduleName) {
if (!currentRollupInput || !moduleName) {
return false;
}
if (typeof currentRollupInput === "string") {
return currentRollupInput === moduleName;
} else if (Array.isArray(currentRollupInput)) {
return currentRollupInput.includes(moduleName);
} else {
return Object.keys(currentRollupInput).includes(moduleName);
}
}
const viteBuildConfig = {
...viteConfig,
logLevel: viteConfig.logLevel ?? "error",
build: {
target: "esnext",
// Vite defaults cssMinify to false in SSR by default, but we want to minify it
// as the CSS generated are used and served to the client.
cssMinify: viteConfig.build?.minify == null ? true : !!viteConfig.build?.minify,
...viteConfig.build,
emptyOutDir: false,
copyPublicDir: false,
manifest: false,
rollupOptions: {
...viteConfig.build?.rollupOptions,
// Setting as `exports-only` allows us to safely delete inputs that are only used during prerendering
preserveEntrySignatures: "exports-only",
...legacyAdapter && settings.buildOutput === "server" ? { input: LEGACY_SSR_ENTRY_VIRTUAL_MODULE } : {},
output: {
hoistTransitiveImports: false,
format: "esm",
minifyInternalExports: true,
// Server chunks can't go in the assets (_astro) folder
// We need to keep these separate
chunkFileNames(chunkInfo) {
const { name } = chunkInfo;
let prefix = CHUNKS_PATH;
let suffix = "_[hash].mjs";
if (name.includes(ASTRO_PAGE_EXTENSION_POST_PATTERN)) {
const [sanitizedName] = name.split(ASTRO_PAGE_EXTENSION_POST_PATTERN);
return [prefix, cleanChunkName(sanitizedName), suffix].join("");
}
if (name.startsWith("pages/")) {
const sanitizedName = name.split(".")[0];
return [prefix, cleanChunkName(sanitizedName), suffix].join("");
}
return [prefix, cleanChunkName(name), suffix].join("");
},
assetFileNames(assetInfo) {
const name = assetInfo.names?.[0] ?? "";
if (name.includes(ASTRO_PAGE_EXTENSION_POST_PATTERN)) {
const [sanitizedName] = name.split(ASTRO_PAGE_EXTENSION_POST_PATTERN);
return `${settings.config.build.assets}/${sanitizedName}.[hash][extname]`;
}
return `${settings.config.build.assets}/[name].[hash][extname]`;
},
...viteConfig.build?.rollupOptions?.output,
entryFileNames(chunkInfo) {
if (chunkInfo.facadeModuleId?.startsWith(VIRTUAL_PAGE_RESOLVED_MODULE_ID)) {
return makeAstroPageEntryPointFileName(
VIRTUAL_PAGE_RESOLVED_MODULE_ID,
chunkInfo.facadeModuleId,
routes
);
} else if (chunkInfo.facadeModuleId === RESOLVED_LEGACY_SSR_ENTRY_VIRTUAL_MODULE || // This catches the case when the adapter uses `entrypointResolution: 'auto'`. When doing so,
// the adapter must set rollupOptions.input or Astro sets it from `serverEntrypoint`.
isRollupInput(chunkInfo.name) || isRollupInput(chunkInfo.facadeModuleId)) {
return opts.settings.config.build.serverEntry;
} else {
return "[name].mjs";
}
}
}
},
ssr: true,
ssrEmitAssets: true,
// improve build performance
minify: false,
modulePreload: { polyfill: false },
reportCompressedSize: false
},
plugins,
// Top-level buildApp for framework build orchestration
// This takes precedence over platform plugin fallbacks (e.g., Cloudflare)
builder: {
async buildApp(builder2) {
settings.timer.start("Prerender build");
let prerenderOutput = await builder2.build(builder2.environments.prerender);
settings.timer.end("Prerender build");
extractPrerenderEntryFileName(internals, prerenderOutput);
const prerenderOutputs = viteBuildReturnToRollupOutputs(prerenderOutput);
const prerenderChunks = extractRelevantChunks(prerenderOutputs, true);
prerenderOutput = void 0;
let ssrChunks = [];
if (settings.buildOutput !== "static") {
settings.timer.start("SSR build");
let ssrOutput = await builder2.build(
builder2.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr]
);
settings.timer.end("SSR build");
const ssrOutputs = viteBuildReturnToRollupOutputs(ssrOutput);
ssrChunks = extractRelevantChunks(ssrOutputs, false);
ssrOutput = void 0;
}
const ssrPlugins = builder2.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr]?.config.plugins ?? [];
buildPostHooks = ssrPlugins.map(
(plugin) => typeof plugin.api?.buildPostHook === "function" ? plugin.api.buildPostHook : void 0
).filter(Boolean);
internals.clientInput = getClientInput(internals, settings);
if (!internals.clientInput.size) {
internals.clientInput.add(NOOP_MODULE_ID);
}
const sortedClientInput = Array.from(internals.clientInput).sort();
builder2.environments.client.config.build.rollupOptions.input = sortedClientInput;
settings.timer.start("Client build");
await builder2.build(builder2.environments.client);
settings.timer.end("Client build");
internals.extractedChunks = [...ssrChunks, ...prerenderChunks];
}
},
envPrefix: viteConfig.envPrefix ?? "PUBLIC_",
base: settings.config.base,
environments: {
...viteConfig.environments ?? {},
[ASTRO_VITE_ENVIRONMENT_NAMES.prerender]: {
build: {
emitAssets: true,
outDir: fileURLToPath(getPrerenderOutputDirectory(settings)),
rollupOptions: {
// Only skip the default prerender entrypoint if an adapter with `entrypointResolution: 'self'` is used
// AND provides a custom prerenderer. Otherwise, use the default.
...!legacyAdapter && settings.prerenderer ? {} : { input: "astro/entrypoints/prerender" },
output: {
entryFileNames: `${PRERENDER_ENTRY_FILENAME_PREFIX}.[hash].mjs`,
format: "esm",
...viteConfig.environments?.prerender?.build?.rollupOptions?.output
}
},
ssr: true
}
},
[ASTRO_VITE_ENVIRONMENT_NAMES.client]: {
build: {
emitAssets: true,
target: "esnext",
outDir: fileURLToPath(getClientOutputDirectory(settings)),
copyPublicDir: true,
sourcemap: viteConfig.environments?.client?.build?.sourcemap ?? false,
minify: true,
rollupOptions: {
preserveEntrySignatures: "exports-only",
output: {
entryFileNames(chunkInfo) {
return `${settings.config.build.assets}/${cleanChunkName(chunkInfo.name)}.[hash].js`;
},
chunkFileNames(chunkInfo) {
return `${settings.config.build.assets}/${cleanChunkName(chunkInfo.name)}.[hash].js`;
},
assetFileNames(assetInfo) {
const name = assetInfo.names?.[0] ?? "";
if (name.includes(ASTRO_PAGE_EXTENSION_POST_PATTERN)) {
const [sanitizedName] = name.split(ASTRO_PAGE_EXTENSION_POST_PATTERN);
return `${settings.config.build.assets}/${sanitizedName}.[hash][extname]`;
}
return `${settings.config.build.assets}/[name].[hash][extname]`;
},
...viteConfig.environments?.client?.build?.rollupOptions?.output
}
}
}
},
[ASTRO_VITE_ENVIRONMENT_NAMES.ssr]: {
build: {
outDir: fileURLToPath(getServerOutputDirectory(settings)),
rollupOptions: {
output: {
...viteConfig.environments?.ssr?.build?.rollupOptions?.output
}
}
}
}
}
};
const updatedViteBuildConfig = await runHookBuildSetup({
config: settings.config,
pages: internals.pagesByKeys,
vite: viteBuildConfig,
target: "server",
logger: opts.logger
});
const builder = await vite.createBuilder(updatedViteBuildConfig);
await builder.buildApp();
}
function getPrerenderEntryFileName(prerenderOutput) {
const outputs = viteBuildReturnToRollupOutputs(prerenderOutput);
for (const output of outputs) {
for (const chunk of output.output) {
if (chunk.type !== "asset" && "fileName" in chunk) {
const fileName = chunk.fileName;
if (fileName.startsWith(PRERENDER_ENTRY_FILENAME_PREFIX)) {
return fileName;
}
}
}
}
throw new Error(
"Could not find the prerender entry point in the build output. This is likely a bug in Astro."
);
}
function extractPrerenderEntryFileName(internals, prerenderOutput) {
internals.prerenderEntryFileName = getPrerenderEntryFileName(prerenderOutput);
}
async function runManifestInjection(opts, internals, chunks, buildPostHooks) {
const mutations = /* @__PURE__ */ new Map();
const mutate = (fileName, newCode, prerender) => {
mutations.set(fileName, { code: newCode, prerender });
};
await manifestBuildPostHook(opts, internals, { chunks, mutate });
await contentAssetsBuildPostHook(
opts.settings.config.base,
opts.settings.config.build.assetsPrefix,
internals,
{ chunks, mutate }
);
for (const buildPostHook of buildPostHooks) {
await buildPostHook({ chunks, mutate });
}
await writeMutatedChunks(opts, mutations);
}
async function writeMutatedChunks(opts, mutations) {
const { settings } = opts;
const config = settings.config;
for (const [fileName, mutation] of mutations) {
let root;
if (mutation.prerender) {
root = getPrerenderOutputDirectory(settings);
} else if (settings.buildOutput === "server") {
root = config.build.server;
} else {
root = getOutDirWithinCwd(config.outDir);
}
const fullPath = path.join(fileURLToPath(root), fileName);
const fileURL = pathToFileURL(fullPath);
await fs.promises.mkdir(new URL("./", fileURL), { recursive: true });
await fs.promises.writeFile(fileURL, mutation.code, "utf-8");
}
}
async function ssrMoveAssets(opts, internals, prerenderOutputDir) {
opts.logger.info("build", "Rearranging server assets...");
const isFullyStaticSite = opts.settings.buildOutput === "static";
const preserveStructure = opts.settings.adapter?.adapterFeatures?.preserveBuildClientDir;
const serverRoot = opts.settings.config.build.server;
const clientRoot = isFullyStaticSite && !preserveStructure ? opts.settings.config.outDir : opts.settings.config.build.client;
const prerenderAssetsToMove = getSSRAssets(internals, ASTRO_VITE_ENVIRONMENT_NAMES.prerender);
if (prerenderAssetsToMove.size > 0) {
await Promise.all(
Array.from(prerenderAssetsToMove).map(async function moveAsset(filename) {
const currentUrl = new URL(filename, appendForwardSlash(prerenderOutputDir.toString()));
const clientUrl = new URL(filename, appendForwardSlash(clientRoot.toString()));
if (!fs.existsSync(currentUrl)) return;
const dir = new URL(path.parse(clientUrl.href).dir);
if (!fs.existsSync(dir)) await fs.promises.mkdir(dir, { recursive: true });
return fs.promises.rename(currentUrl, clientUrl);
})
);
}
if (isFullyStaticSite) {
return;
}
const ssrAssetsToMove = getSSRAssets(internals, ASTRO_VITE_ENVIRONMENT_NAMES.ssr);
if (ssrAssetsToMove.size > 0) {
await Promise.all(
Array.from(ssrAssetsToMove).map(async function moveAsset(filename) {
const currentUrl = new URL(filename, appendForwardSlash(serverRoot.toString()));
const clientUrl = new URL(filename, appendForwardSlash(clientRoot.toString()));
if (!fs.existsSync(currentUrl)) return;
const dir = new URL(path.parse(clientUrl.href).dir);
if (!fs.existsSync(dir)) await fs.promises.mkdir(dir, { recursive: true });
return fs.promises.rename(currentUrl, clientUrl);
})
);
removeEmptyDirs(fileURLToPath(serverRoot));
}
}
function getClientInput(internals, settings) {
const rendererClientEntrypoints = settings.renderers.map((r) => r.clientEntrypoint).filter((a) => typeof a === "string");
const clientInput = /* @__PURE__ */ new Set([
...internals.discoveredHydratedComponents.keys(),
...internals.discoveredClientOnlyComponents.keys(),
...rendererClientEntrypoints,
...internals.discoveredScripts
]);
if (settings.scripts.some((script) => script.stage === "page")) {
clientInput.add(PAGE_SCRIPT_ID);
}
return clientInput;
}
function makeAstroPageEntryPointFileName(prefix, facadeModuleId, routes) {
const pageModuleId = facadeModuleId.replace(prefix, "").replace(ASTRO_PAGE_EXTENSION_POST_PATTERN, ".");
const route = routes.find((routeData) => routeData.component === pageModuleId);
const name = route?.route ?? pageModuleId;
return `pages${name.replace(/\/$/, "/index").replaceAll(/[[\]]/g, "_").replaceAll("...", "---")}.astro.mjs`;
}
export {
makeAstroPageEntryPointFileName,
viteBuild
};

52
node_modules/astro/dist/core/build/types.d.ts generated vendored Normal file
View File

@@ -0,0 +1,52 @@
import type * as vite from 'vite';
import type { InlineConfig } from 'vite';
import type { AstroSettings, ComponentInstance, RoutesList } from '../../types/astro.js';
import type { MiddlewareHandler } from '../../types/public/common.js';
import type { RuntimeMode } from '../../types/public/config.js';
import type { RouteData } from '../../types/public/internal.js';
import type { AstroLogger } from '../logger/core.js';
type ComponentPath = string;
export type ViteID = string;
export type StylesheetAsset = {
type: 'inline';
content: string;
} | {
type: 'external';
src: string;
};
/** Public type exposed through the `astro:build:setup` integration hook */
export interface PageBuildData {
key: string;
component: ComponentPath;
route: RouteData;
moduleSpecifier: string;
styles: Array<{
depth: number;
order: number;
sheet: StylesheetAsset;
}>;
}
export type AllPagesData = Record<ComponentPath, PageBuildData>;
/** Options for the static build */
export interface StaticBuildOptions {
allPages: AllPagesData;
settings: AstroSettings;
logger: AstroLogger;
routesList: RoutesList;
runtimeMode: RuntimeMode;
origin: string;
pageNames: string[];
viteConfig: InlineConfig;
teardownCompiler: boolean;
key: Promise<CryptoKey>;
}
type ImportComponentInstance = () => Promise<ComponentInstance>;
export interface SinglePageBuiltModule {
page: ImportComponentInstance;
/**
* The `onRequest` hook exported by the middleware
*/
onRequest?: MiddlewareHandler;
}
export type ViteBuildReturn = Awaited<ReturnType<typeof vite.build>>;
export {};

0
node_modules/astro/dist/core/build/types.js generated vendored Normal file
View File

15
node_modules/astro/dist/core/build/util.d.ts generated vendored Normal file
View File

@@ -0,0 +1,15 @@
import type { Rollup } from 'vite';
import type { AstroConfig } from '../../types/public/config.js';
import type { ViteBuildReturn } from './types.js';
export declare function getTimeStat(timeStart: number, timeEnd: number): string;
/**
* Given the Astro configuration, it tells if a slash should be appended or not
*/
export declare function shouldAppendForwardSlash(trailingSlash: AstroConfig['trailingSlash'], buildFormat: AstroConfig['build']['format']): boolean;
/**
* Replaces characters in a chunk name that are not safe for filesystem paths or URLs.
* Characters like `!` and `~` can leak from Vite module IDs into Rollup chunk names
* and break deploys on platforms like Netlify.
*/
export declare function cleanChunkName(name: string): string;
export declare function viteBuildReturnToRollupOutputs(viteBuildReturn: ViteBuildReturn): Rollup.RollupOutput[];

51
node_modules/astro/dist/core/build/util.js generated vendored Normal file
View File

@@ -0,0 +1,51 @@
function getTimeStat(timeStart, timeEnd) {
const buildTime = timeEnd - timeStart;
return buildTime < 1e3 ? `${Math.round(buildTime)}ms` : `${(buildTime / 1e3).toFixed(2)}s`;
}
function shouldAppendForwardSlash(trailingSlash, buildFormat) {
switch (trailingSlash) {
case "always":
return true;
case "never":
return false;
case "ignore": {
switch (buildFormat) {
case "directory":
return true;
case "preserve":
case "file":
return false;
}
}
}
}
const UNSAFE_CHUNK_CHAR_RE = /[^\w.\-/]/g;
function cleanChunkName(name) {
return encodeName(name.replace(UNSAFE_CHUNK_CHAR_RE, "_"));
}
function encodeName(name) {
for (let i = 0; i < name.length; i++) {
if (name[i] === "%") {
const third = name.codePointAt(i + 2) | 32;
if (name[i + 1] !== "2" || third !== 102) {
return `${name.replace(/%/g, "_percent_")}`;
}
}
}
return name;
}
function viteBuildReturnToRollupOutputs(viteBuildReturn) {
const result = [];
if (Array.isArray(viteBuildReturn)) {
result.push(...viteBuildReturn);
} else if ("output" in viteBuildReturn) {
result.push(viteBuildReturn);
}
return result;
}
export {
cleanChunkName,
getTimeStat,
shouldAppendForwardSlash,
viteBuildReturnToRollupOutputs
};

View File

@@ -0,0 +1,9 @@
import type { Plugin } from 'vite';
import { type BuildInternals } from './internal.js';
/**
* Vite plugin that tracks emitted assets and handles cleanup of manifest files.
* This plugin coordinates with emitClientAsset() to track which assets should
* be moved to the client directory. The resolved filenames are stored in
* BuildInternals.ssrAssetsPerEnvironment during generateBundle.
*/
export declare function vitePluginSSRAssets(internals: BuildInternals): Plugin;

View File

@@ -0,0 +1,94 @@
import fs from "node:fs";
import { appendForwardSlash } from "../path.js";
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../constants.js";
import { getHandles, resetHandles } from "../../assets/utils/assets.js";
import { getOrCreateSSRAssets } from "./internal.js";
function vitePluginSSRAssets(internals) {
return {
name: "astro:ssr-assets",
applyToEnvironment(environment) {
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender;
},
configEnvironment(name) {
if (name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender) {
return {
build: {
manifest: true
}
};
}
},
buildStart() {
resetHandles(this.environment);
},
generateBundle() {
const env = this.environment;
const handles = getHandles(env);
const filenames = getOrCreateSSRAssets(internals, env.name);
if (handles) {
for (const handle of handles) {
try {
const filename = this.getFileName(handle);
filenames.add(filename);
} catch {
}
}
}
},
writeBundle: {
sequential: true,
order: "post",
async handler() {
const env = this.environment;
const manifestDir = new URL(appendForwardSlash(`file://${env.config.build.outDir}`));
const manifest = loadViteManifest(manifestDir);
if (manifest) {
const manifestAssets = collectAssetsFromManifest(manifest);
if (manifestAssets.size > 0) {
const filenames = getOrCreateSSRAssets(internals, env.name);
for (const asset of manifestAssets) {
filenames.add(asset);
}
}
}
await deleteViteFolder(env.config.build.outDir);
}
}
};
}
function loadViteManifest(directory) {
const manifestPath = new URL(".vite/manifest.json", appendForwardSlash(directory.toString()));
if (!fs.existsSync(manifestPath)) {
return null;
}
const contents = fs.readFileSync(manifestPath, "utf-8");
return JSON.parse(contents);
}
function collectAssetsFromManifest(manifest) {
const assets = /* @__PURE__ */ new Set();
for (const chunk of Object.values(manifest)) {
if (chunk.css) {
for (const css of chunk.css) {
assets.add(css);
}
}
if (chunk.assets) {
for (const asset of chunk.assets) {
assets.add(asset);
}
}
if (chunk.file.endsWith(".css")) {
assets.add(chunk.file);
}
}
return assets;
}
async function deleteViteFolder(directory) {
const viteFolder = new URL(".vite/", appendForwardSlash(`file://${directory}`));
if (fs.existsSync(viteFolder)) {
await fs.promises.rm(viteFolder, { recursive: true, force: true });
}
}
export {
vitePluginSSRAssets
};