0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-06 22:10:10 -05:00

fix: make root serializable (#11489)

* fix: use config root to build default routes

* fix: make root serializable

* fix regression

* Use stringified URLs

* Fix unit tests

---------

Co-authored-by: Matthew Phillips <matthew@skypack.dev>
This commit is contained in:
Emanuele Stoppa 2024-07-18 14:44:40 +01:00 committed by GitHub
parent 6ad02b5902
commit 061f1f4d0c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 44 additions and 11 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Move root inside the manifest and make serialisable

View file

@ -105,6 +105,7 @@ function createManifest(
};
return {
hrefRoot: import.meta.url,
rewritingEnabled: false,
trailingSlash: manifest?.trailingSlash ?? ASTRO_CONFIG_DEFAULTS.trailingSlash,
buildFormat: manifest?.buildFormat ?? ASTRO_CONFIG_DEFAULTS.build.format,

View file

@ -20,10 +20,11 @@ import {
} from '../path.js';
import { RenderContext } from '../render-context.js';
import { createAssetLink } from '../render/ssr-element.js';
import { injectDefaultRoutes } from '../routing/default.js';
import { createDefaultRoutes, injectDefaultRoutes } from '../routing/default.js';
import { matchRoute } from '../routing/match.js';
import { createOriginCheckMiddleware } from './middlewares.js';
import { AppPipeline } from './pipeline.js';
export { deserializeManifest } from './common.js';
export interface RenderOptions {
@ -122,6 +123,7 @@ export class App {
manifest: this.#manifest,
mode: 'production',
renderers: this.#manifest.renderers,
defaultRoutes: createDefaultRoutes(this.#manifest),
resolve: async (specifier: string) => {
if (!(specifier in this.#manifest.entryModules)) {
throw new Error(`Unable to resolve [${specifier}]`);
@ -145,6 +147,7 @@ export class App {
set setManifestData(newManifestData: ManifestData) {
this.#manifestData = newManifestData;
}
removeBase(pathname: string) {
if (pathname.startsWith(this.#manifest.base)) {
return pathname.slice(this.#baseWithoutTrailingSlash.length + 1);

View file

@ -25,9 +25,17 @@ export class AppPipeline extends Pipeline {
resolve,
serverLike,
streaming,
defaultRoutes,
}: Pick<
AppPipeline,
'logger' | 'manifest' | 'mode' | 'renderers' | 'resolve' | 'serverLike' | 'streaming'
| 'logger'
| 'manifest'
| 'mode'
| 'renderers'
| 'resolve'
| 'serverLike'
| 'streaming'
| 'defaultRoutes'
>
) {
const pipeline = new AppPipeline(
@ -46,7 +54,8 @@ export class AppPipeline extends Pipeline {
undefined,
undefined,
undefined,
false
false,
defaultRoutes
);
pipeline.#manifestData = manifestData;
return pipeline;
@ -75,6 +84,7 @@ export class AppPipeline extends Pipeline {
}
componentMetadata() {}
async getComponentByRoute(routeData: RouteData): Promise<ComponentInstance> {
const module = await this.getModuleForRoute(routeData);
return module.page();

View file

@ -44,6 +44,7 @@ export type AssetsPrefix =
| undefined;
export type SSRManifest = {
hrefRoot: string;
adapterName: string;
routes: RouteInfo[];
site?: string;

View file

@ -58,7 +58,7 @@ export abstract class Pipeline {
* Array of built-in, internal, routes.
* Used to find the route module
*/
readonly defaultRoutes = createDefaultRoutes(manifest, new URL(import.meta.url))
readonly defaultRoutes = createDefaultRoutes(manifest)
) {
this.internalMiddleware = [];
// We do use our middleware only if the user isn't using the manual setup
@ -77,6 +77,7 @@ export abstract class Pipeline {
}
abstract headElements(routeData: RouteData): Promise<HeadElements> | HeadElements;
abstract componentMetadata(routeData: RouteData): Promise<SSRResult['componentMetadata']> | void;
/**

View file

@ -417,6 +417,7 @@ interface GeneratePathOptions {
styles: StylesheetAsset[];
mod: ComponentInstance;
}
async function generatePath(
pathname: string,
pipeline: BuildPipeline,
@ -552,6 +553,7 @@ function createBuildManifest(
};
}
return {
hrefRoot: settings.config.root.toString(),
trailingSlash: settings.config.trailingSlash,
assets: new Set(),
entryModules: Object.fromEntries(internals.entrySpecifierToBundleMap.entries()),

View file

@ -55,9 +55,10 @@ export class BuildPipeline extends Pipeline {
readonly options: StaticBuildOptions,
readonly config = options.settings.config,
readonly settings = options.settings,
readonly defaultRoutes = createDefaultRoutes(manifest, config.root)
readonly defaultRoutes = createDefaultRoutes(manifest)
) {
const resolveCache = new Map<string, string>();
async function resolve(specifier: string) {
if (resolveCache.has(specifier)) {
return resolveCache.get(specifier)!;
@ -76,6 +77,7 @@ export class BuildPipeline extends Pipeline {
resolveCache.set(specifier, assetLink);
return assetLink;
}
const serverLike = isServerLikeOutput(config);
// We can skip streaming in SSG for performance as writing as strings are faster
const streaming = serverLike;

View file

@ -27,7 +27,7 @@ const replaceExp = new RegExp(`['"]${manifestReplace}['"]`, 'g');
export const SSR_MANIFEST_VIRTUAL_MODULE_ID = '@astrojs-manifest';
export const RESOLVED_SSR_MANIFEST_VIRTUAL_MODULE_ID = '\0' + SSR_MANIFEST_VIRTUAL_MODULE_ID;
function vitePluginManifest(options: StaticBuildOptions, internals: BuildInternals): VitePlugin {
function vitePluginManifest(_options: StaticBuildOptions, internals: BuildInternals): VitePlugin {
return {
name: '@astro/plugin-build-manifest',
enforce: 'post',
@ -262,6 +262,7 @@ function buildManifest(
}
return {
hrefRoot: opts.settings.config.root.toString(),
adapterName: opts.settings.adapter?.name ?? '',
routes,
site: settings.config.site,

View file

@ -25,17 +25,20 @@ type DefaultRouteParams = {
component: string;
};
export function createDefaultRoutes(manifest: SSRManifest, root: URL): DefaultRouteParams[] {
export function createDefaultRoutes(manifest: SSRManifest): DefaultRouteParams[] {
const root = new URL(manifest.hrefRoot);
return [
{
instance: default404Instance,
matchesComponent: (filePath) => filePath.href === new URL(DEFAULT_404_COMPONENT, root).href,
matchesComponent: (filePath) =>
filePath.href === new URL(DEFAULT_404_COMPONENT, root).href,
route: DEFAULT_404_ROUTE.route,
component: DEFAULT_404_COMPONENT,
},
{
instance: createServerIslandEndpoint(manifest),
matchesComponent: (filePath) => filePath.href === new URL(SERVER_ISLAND_COMPONENT, root).href,
matchesComponent: (filePath) =>
filePath.href === new URL(SERVER_ISLAND_COMPONENT, root).href,
route: SERVER_ISLAND_ROUTE,
component: SERVER_ISLAND_COMPONENT,
},

View file

@ -46,7 +46,7 @@ export class DevPipeline extends Pipeline {
readonly manifest: SSRManifest,
readonly settings: AstroSettings,
readonly config = settings.config,
readonly defaultRoutes = createDefaultRoutes(manifest, config.root)
readonly defaultRoutes = createDefaultRoutes(manifest)
) {
const mode = 'development';
const resolve = createResolve(loader, config.root);

View file

@ -50,6 +50,7 @@ export default function createVitePluginAstroServer({
pipeline.setManifestData(manifestData);
}
}
// Rebuild route manifest on file change, if needed.
viteServer.watcher.on('add', rebuildManifest.bind(null, true));
viteServer.watcher.on('unlink', rebuildManifest.bind(null, true));
@ -128,6 +129,7 @@ export function createDevelopmentManifest(settings: AstroSettings): SSRManifest
};
}
return {
hrefRoot: settings.config.root.toString(),
trailingSlash: settings.config.trailingSlash,
buildFormat: settings.config.build.format,
compressHTML: settings.config.compressHTML,

View file

@ -188,7 +188,9 @@ export function createBasicPipeline(options = {}) {
const mode = options.mode ?? 'development';
const pipeline = new Pipeline(
options.logger ?? defaultLogger,
options.manifest ?? {},
options.manifest ?? {
hrefRoot: import.meta.url
},
options.mode ?? 'development',
options.renderers ?? [],
options.resolve ?? ((s) => Promise.resolve(s)),