194 lines
6.8 KiB
JavaScript
194 lines
6.8 KiB
JavaScript
import { fileURLToPath } from "node:url";
|
|
import { Pipeline } from "../core/base-pipeline.js";
|
|
import { ASTRO_VERSION } from "../core/constants.js";
|
|
import { enhanceViteSSRError } from "../core/errors/dev/index.js";
|
|
import { AggregateError, CSSError, MarkdownError } from "../core/errors/index.js";
|
|
import { RedirectComponentInstance } from "../core/redirects/index.js";
|
|
import { loadRenderer } from "../core/render/index.js";
|
|
import { routeIsRedirect } from "../core/routing/helpers.js";
|
|
import { findRouteToRewrite } from "../core/routing/rewrite.js";
|
|
import { isPage } from "../core/util.js";
|
|
import { getComponentMetadata } from "../vite-plugin-astro-server/metadata.js";
|
|
import { createResolve } from "../vite-plugin-astro-server/resolve.js";
|
|
import { PAGE_SCRIPT_ID } from "../vite-plugin-scripts/index.js";
|
|
import { newNodePool } from "../runtime/server/render/queue/pool.js";
|
|
import { HTMLStringCache } from "../runtime/server/html-string-cache.js";
|
|
import { queueRenderingEnabled } from "../core/app/manifest.js";
|
|
class RunnablePipeline extends Pipeline {
|
|
getName() {
|
|
return "RunnablePipeline";
|
|
}
|
|
// renderers are loaded on every request,
|
|
// so it needs to be mutable here unlike in other environments
|
|
renderers = new Array();
|
|
routesList;
|
|
loader;
|
|
settings;
|
|
getDebugInfo;
|
|
constructor(loader, logger, manifest, settings, getDebugInfo, defaultRoutes) {
|
|
const resolve = createResolve(loader, manifest.rootDir);
|
|
const streaming = true;
|
|
super(
|
|
logger,
|
|
manifest,
|
|
"development",
|
|
[],
|
|
resolve,
|
|
streaming,
|
|
void 0,
|
|
void 0,
|
|
void 0,
|
|
void 0,
|
|
void 0,
|
|
void 0,
|
|
void 0,
|
|
void 0,
|
|
defaultRoutes
|
|
);
|
|
this.loader = loader;
|
|
this.settings = settings;
|
|
this.getDebugInfo = getDebugInfo;
|
|
}
|
|
static create(manifestData, {
|
|
loader,
|
|
logger,
|
|
manifest,
|
|
settings,
|
|
getDebugInfo
|
|
}) {
|
|
const pipeline = new RunnablePipeline(loader, logger, manifest, settings, getDebugInfo);
|
|
pipeline.routesList = manifestData;
|
|
if (queueRenderingEnabled(manifest.experimentalQueuedRendering)) {
|
|
pipeline.nodePool = newNodePool(manifest.experimentalQueuedRendering);
|
|
if (manifest.experimentalQueuedRendering.contentCache) {
|
|
pipeline.htmlStringCache = new HTMLStringCache(1e3);
|
|
}
|
|
}
|
|
return pipeline;
|
|
}
|
|
async headElements(routeData) {
|
|
const { manifest, runtimeMode, settings } = this;
|
|
const filePath = new URL(`${routeData.component}`, manifest.rootDir);
|
|
const scripts = /* @__PURE__ */ new Set();
|
|
if (settings) {
|
|
if (isPage(filePath, settings) && runtimeMode === "development") {
|
|
scripts.add({
|
|
props: { type: "module", src: "/@vite/client" },
|
|
children: ""
|
|
});
|
|
if (this.manifest.devToolbar.enabled) {
|
|
scripts.add({
|
|
props: {
|
|
type: "module",
|
|
src: "/@id/astro/runtime/client/dev-toolbar/entrypoint.js"
|
|
},
|
|
children: ""
|
|
});
|
|
const additionalMetadata = {
|
|
root: fileURLToPath(settings.config.root),
|
|
version: ASTRO_VERSION,
|
|
latestAstroVersion: settings.latestAstroVersion,
|
|
// TODO: Currently the debug info is always fetched, which slows things down.
|
|
// We should look into not loading it if the dev toolbar is disabled. And when
|
|
// enabled, it would nice to request the debug info through import.meta.hot
|
|
// when the button is click to defer execution as much as possible
|
|
debugInfo: await this.getDebugInfo(),
|
|
placement: settings.config.devToolbar.placement
|
|
};
|
|
const children = `window.__astro_dev_toolbar__ = ${JSON.stringify(additionalMetadata)}`;
|
|
scripts.add({ props: {}, children });
|
|
}
|
|
}
|
|
for (const script of settings.scripts) {
|
|
if (script.stage === "head-inline") {
|
|
scripts.add({
|
|
props: {},
|
|
children: script.content
|
|
});
|
|
} else if (script.stage === "page" && isPage(filePath, settings)) {
|
|
scripts.add({
|
|
props: { type: "module", src: `/@id/${PAGE_SCRIPT_ID}` },
|
|
children: ""
|
|
});
|
|
}
|
|
}
|
|
}
|
|
const { devCSSMap } = await import("virtual:astro:dev-css-all");
|
|
const importer = devCSSMap.get(routeData.component);
|
|
let css = /* @__PURE__ */ new Set();
|
|
if (importer) {
|
|
const cssModule = await importer();
|
|
css = cssModule.css;
|
|
} else {
|
|
this.logger.warn(
|
|
"assets",
|
|
`Unable to find CSS for ${routeData.component}. This is likely a bug in Astro.`
|
|
);
|
|
}
|
|
const links = /* @__PURE__ */ new Set();
|
|
const styles = /* @__PURE__ */ new Set();
|
|
for (const { id, url: src, content } of css) {
|
|
scripts.add({ props: { type: "module", src }, children: "" });
|
|
styles.add({ props: { "data-vite-dev-id": id }, children: content });
|
|
}
|
|
return { scripts, styles, links };
|
|
}
|
|
componentMetadata(routeData) {
|
|
const filePath = new URL(`${routeData.component}`, this.manifest.rootDir);
|
|
return getComponentMetadata(filePath, this.loader);
|
|
}
|
|
async preload(routeData, filePath) {
|
|
if (routeIsRedirect(routeData)) {
|
|
return RedirectComponentInstance;
|
|
}
|
|
const { loader } = this;
|
|
for (const route of this.defaultRoutes) {
|
|
if (route.matchesComponent(filePath)) {
|
|
return route.instance;
|
|
}
|
|
}
|
|
if (this.settings) {
|
|
const renderers__ = this.settings.renderers.map((r) => loadRenderer(r, loader));
|
|
const renderers_ = await Promise.all(renderers__);
|
|
this.renderers = renderers_.filter((r) => Boolean(r));
|
|
}
|
|
try {
|
|
return await loader.import(filePath.toString());
|
|
} catch (error) {
|
|
if (MarkdownError.is(error) || CSSError.is(error) || AggregateError.is(error)) {
|
|
throw error;
|
|
}
|
|
throw enhanceViteSSRError({ error, filePath, loader });
|
|
}
|
|
}
|
|
clearRouteCache() {
|
|
this.routeCache.clearAll();
|
|
}
|
|
async getComponentByRoute(routeData) {
|
|
const filePath = new URL(`${routeData.component}`, this.manifest.rootDir);
|
|
return await this.preload(routeData, filePath);
|
|
}
|
|
async tryRewrite(payload, request) {
|
|
if (!this.routesList) {
|
|
throw new Error("Missing manifest data. This is an internal error, please file an issue.");
|
|
}
|
|
const { routeData, pathname, newUrl } = findRouteToRewrite({
|
|
payload,
|
|
request,
|
|
routes: this.routesList?.routes,
|
|
trailingSlash: this.manifest.trailingSlash,
|
|
buildFormat: this.manifest.buildFormat,
|
|
base: this.manifest.base,
|
|
outDir: this.manifest.outDir
|
|
});
|
|
const componentInstance = await this.getComponentByRoute(routeData);
|
|
return { newUrl, pathname, componentInstance, routeData };
|
|
}
|
|
setManifestData(manifestData) {
|
|
this.routesList = manifestData;
|
|
}
|
|
}
|
|
export {
|
|
RunnablePipeline
|
|
};
|