From 061f1f4d0cb306efd0c768645439111aec765c76 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Thu, 18 Jul 2024 14:44:40 +0100 Subject: [PATCH] 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 --- .changeset/cuddly-days-relate.md | 5 +++++ packages/astro/src/container/index.ts | 1 + packages/astro/src/core/app/index.ts | 5 ++++- packages/astro/src/core/app/pipeline.ts | 14 ++++++++++++-- packages/astro/src/core/app/types.ts | 1 + packages/astro/src/core/base-pipeline.ts | 3 ++- packages/astro/src/core/build/generate.ts | 2 ++ packages/astro/src/core/build/pipeline.ts | 4 +++- .../src/core/build/plugins/plugin-manifest.ts | 3 ++- packages/astro/src/core/routing/default.ts | 9 ++++++--- .../astro/src/vite-plugin-astro-server/pipeline.ts | 2 +- .../astro/src/vite-plugin-astro-server/plugin.ts | 2 ++ packages/astro/test/units/test-utils.js | 4 +++- 13 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 .changeset/cuddly-days-relate.md diff --git a/.changeset/cuddly-days-relate.md b/.changeset/cuddly-days-relate.md new file mode 100644 index 0000000000..359f19b947 --- /dev/null +++ b/.changeset/cuddly-days-relate.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Move root inside the manifest and make serialisable diff --git a/packages/astro/src/container/index.ts b/packages/astro/src/container/index.ts index 53bc33e4b9..758d65505e 100644 --- a/packages/astro/src/container/index.ts +++ b/packages/astro/src/container/index.ts @@ -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, diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts index 24bb7b2b7f..04a7d90a85 100644 --- a/packages/astro/src/core/app/index.ts +++ b/packages/astro/src/core/app/index.ts @@ -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); diff --git a/packages/astro/src/core/app/pipeline.ts b/packages/astro/src/core/app/pipeline.ts index 19284ef07a..64c2fdcb86 100644 --- a/packages/astro/src/core/app/pipeline.ts +++ b/packages/astro/src/core/app/pipeline.ts @@ -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 { const module = await this.getModuleForRoute(routeData); return module.page(); diff --git a/packages/astro/src/core/app/types.ts b/packages/astro/src/core/app/types.ts index 69a9a4a491..db65683520 100644 --- a/packages/astro/src/core/app/types.ts +++ b/packages/astro/src/core/app/types.ts @@ -44,6 +44,7 @@ export type AssetsPrefix = | undefined; export type SSRManifest = { + hrefRoot: string; adapterName: string; routes: RouteInfo[]; site?: string; diff --git a/packages/astro/src/core/base-pipeline.ts b/packages/astro/src/core/base-pipeline.ts index 449c99d62e..56c6a7746e 100644 --- a/packages/astro/src/core/base-pipeline.ts +++ b/packages/astro/src/core/base-pipeline.ts @@ -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; + abstract componentMetadata(routeData: RouteData): Promise | void; /** diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts index e394dc156d..05a8f8b647 100644 --- a/packages/astro/src/core/build/generate.ts +++ b/packages/astro/src/core/build/generate.ts @@ -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()), diff --git a/packages/astro/src/core/build/pipeline.ts b/packages/astro/src/core/build/pipeline.ts index 81a5dcfa2d..4a56dca4cd 100644 --- a/packages/astro/src/core/build/pipeline.ts +++ b/packages/astro/src/core/build/pipeline.ts @@ -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(); + 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; diff --git a/packages/astro/src/core/build/plugins/plugin-manifest.ts b/packages/astro/src/core/build/plugins/plugin-manifest.ts index 32caa7b1fc..df7f7b8bdd 100644 --- a/packages/astro/src/core/build/plugins/plugin-manifest.ts +++ b/packages/astro/src/core/build/plugins/plugin-manifest.ts @@ -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, diff --git a/packages/astro/src/core/routing/default.ts b/packages/astro/src/core/routing/default.ts index 5bad66ec4f..67cfbd97c6 100644 --- a/packages/astro/src/core/routing/default.ts +++ b/packages/astro/src/core/routing/default.ts @@ -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, }, diff --git a/packages/astro/src/vite-plugin-astro-server/pipeline.ts b/packages/astro/src/vite-plugin-astro-server/pipeline.ts index 7ad9ead1ea..2c718d3ab1 100644 --- a/packages/astro/src/vite-plugin-astro-server/pipeline.ts +++ b/packages/astro/src/vite-plugin-astro-server/pipeline.ts @@ -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); diff --git a/packages/astro/src/vite-plugin-astro-server/plugin.ts b/packages/astro/src/vite-plugin-astro-server/plugin.ts index 9904d2844d..f9d0073bb0 100644 --- a/packages/astro/src/vite-plugin-astro-server/plugin.ts +++ b/packages/astro/src/vite-plugin-astro-server/plugin.ts @@ -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, diff --git a/packages/astro/test/units/test-utils.js b/packages/astro/test/units/test-utils.js index 53ac33e9b5..0ffae5b0b8 100644 --- a/packages/astro/test/units/test-utils.js +++ b/packages/astro/test/units/test-utils.js @@ -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)),