Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fix(hybrid-output): no matched route when using getStaticPaths (#7150)
* `isPrenderDefault` ---> `isPrerenderDefault`

* test: add test fixture

* test: add hybrid getStaticPaths tests

* try fix in ci

* bring back edit lost on merge conflict fix

* back static paths guard

* move function to new file to avoid bundling issues

* remove unsued import

* debugging cleanup

* chore: update fixture's package.json

* cleanup test

* small test refactoring

* `status.ts` --> `metadata.ts`

* smol refactor

* chore: changeset

* just return the prerender metadata

* refactor tests

* chore: update lock file
  • Loading branch information
MoustaphaDev committed May 22, 2023
1 parent 0616ef2 commit 8f418d1
Show file tree
Hide file tree
Showing 12 changed files with 318 additions and 120 deletions.
5 changes: 5 additions & 0 deletions .changeset/strange-ties-cry.md
@@ -0,0 +1,5 @@
---
'astro': patch
---

fix no matched path when using `getStaticPaths` without `prerender` export.
3 changes: 2 additions & 1 deletion packages/astro/src/core/build/plugins/plugin-prerender.ts
Expand Up @@ -4,6 +4,7 @@ import type { BuildInternals } from '../internal.js';
import type { AstroBuildPlugin } from '../plugin.js';
import type { StaticBuildOptions } from '../types';
import { extendManualChunks } from './util.js';
import { getPrerenderMetadata } from '../../../prerender/metadata.js';

function vitePluginPrerender(opts: StaticBuildOptions, internals: BuildInternals): VitePlugin {
return {
Expand All @@ -20,7 +21,7 @@ function vitePluginPrerender(opts: StaticBuildOptions, internals: BuildInternals
if (pageInfo) {
// prerendered pages should be split into their own chunk
// Important: this can't be in the `pages/` directory!
if (meta.getModuleInfo(id)?.meta.astro?.pageOptions?.prerender) {
if (getPrerenderMetadata(meta.getModuleInfo(id))) {
pageInfo.route.prerender = true;
return 'prerender';
}
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/endpoint/index.ts
Expand Up @@ -138,7 +138,7 @@ export async function callEndpoint<MiddlewareResult = Response | EndpointOutput>
};
}

if (env.ssr && !mod.prerender) {
if (env.ssr && !ctx.route?.prerender) {
if (response.hasOwnProperty('headers')) {
warn(
logging,
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/render/core.ts
Expand Up @@ -89,7 +89,7 @@ export async function getParamsAndProps(
routeCache.set(route, routeCacheEntry);
}
const matchedStaticPath = findPathItemByKey(routeCacheEntry.staticPaths, params, route);
if (!matchedStaticPath && (ssr ? mod.prerender : true)) {
if (!matchedStaticPath && (ssr ? route.prerender : true)) {
return GetParamsAndPropsError.NoMatchingStaticPath;
}
// Note: considered using Object.create(...) for performance
Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/core/render/dev/index.ts
Expand Up @@ -66,6 +66,7 @@ export async function preload({
try {
// Load the module from the Vite SSR Runtime.
const mod = (await env.loader.import(fileURLToPath(filePath))) as ComponentInstance;

return [renderers, mod];
} catch (error) {
// If the error came from Markdown or CSS, we already handled it and there's no need to enhance it
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/render/route-cache.ts
Expand Up @@ -31,7 +31,7 @@ export async function callGetStaticPaths({
}: CallGetStaticPathsOptions): Promise<RouteCacheEntry> {
validateDynamicRouteModule(mod, { ssr, logging, route });
// No static paths in SSR mode. Return an empty RouteCacheEntry.
if (ssr && !mod.prerender) {
if (ssr && !route.prerender) {
return { staticPaths: Object.assign([], { keyed: new Map() }) };
}
// Add a check here to make TypeScript happy.
Expand Down
6 changes: 3 additions & 3 deletions packages/astro/src/core/routing/manifest/create.ts
Expand Up @@ -227,7 +227,7 @@ export function createRouteManifest(
]);
const validEndpointExtensions: Set<string> = new Set(['.js', '.ts']);
const localFs = fsMod ?? nodeFs;
const isPrenderDefault = isHybridOutput(settings.config);
const isPrerenderDefault = isHybridOutput(settings.config);

const foundInvalidFileExtensions: Set<string> = new Set();

Expand Down Expand Up @@ -340,7 +340,7 @@ export function createRouteManifest(
component,
generate,
pathname: pathname || undefined,
prerender: isPrenderDefault,
prerender: isPrerenderDefault,
});
}
});
Expand Down Expand Up @@ -416,7 +416,7 @@ export function createRouteManifest(
component,
generate,
pathname: pathname || void 0,
prerender: isPrenderDefault,
prerender: isPrerenderDefault,
});
});

Expand Down
4 changes: 2 additions & 2 deletions packages/astro/src/core/routing/validation.ts
Expand Up @@ -32,14 +32,14 @@ export function validateDynamicRouteModule(
route: RouteData;
}
) {
if (ssr && mod.getStaticPaths && !mod.prerender) {
if (ssr && mod.getStaticPaths && !route.prerender) {
warn(
logging,
'getStaticPaths',
`getStaticPaths() in ${bold(route.component)} is ignored when "output: server" is set.`
);
}
if ((!ssr || mod.prerender) && !mod.getStaticPaths) {
if ((!ssr || route.prerender) && !mod.getStaticPaths) {
throw new AstroError({
...AstroErrorData.GetStaticPathsRequired,
location: { file: route.component },
Expand Down
22 changes: 22 additions & 0 deletions packages/astro/src/prerender/metadata.ts
@@ -0,0 +1,22 @@
import type { ModuleInfo, ModuleLoader } from '../core/module-loader';
import { viteID } from '../core/util.js';

type GetPrerenderStatusParams = {
filePath: URL;
loader: ModuleLoader;
};

export function getPrerenderStatus({
filePath,
loader,
}: GetPrerenderStatusParams): boolean | undefined {
const fileID = viteID(filePath);
const moduleInfo = loader.getModuleInfo(fileID);
if (!moduleInfo) return;
const prerenderStatus = getPrerenderMetadata(moduleInfo);
return prerenderStatus;
}

export function getPrerenderMetadata(moduleInfo: ModuleInfo) {
return moduleInfo?.meta?.astro?.pageOptions?.prerender;
}
12 changes: 12 additions & 0 deletions packages/astro/src/vite-plugin-astro-server/route.ts
Expand Up @@ -19,6 +19,7 @@ import { matchAllRoutes } from '../core/routing/index.js';
import { isHybridOutput } from '../prerender/utils.js';
import { log404 } from './common.js';
import { handle404Response, writeSSRResult, writeWebResponse } from './response.js';
import { getPrerenderStatus } from '../prerender/metadata.js';

type AsyncReturnType<T extends (...args: any) => Promise<any>> = T extends (
...args: any
Expand Down Expand Up @@ -50,6 +51,17 @@ export async function matchRoute(
for await (const maybeRoute of matches) {
const filePath = new URL(`./${maybeRoute.component}`, settings.config.root);
const preloadedComponent = await preload({ env, filePath });

// gets the prerender metadata set by the `astro:scanner` vite plugin
const prerenderStatus = getPrerenderStatus({
filePath,
loader: env.loader,
});

if (prerenderStatus !== undefined) {
maybeRoute.prerender = prerenderStatus;
}

const [, mod] = preloadedComponent;
// attempt to get static paths
// if this fails, we have a bad URL match!
Expand Down

0 comments on commit 8f418d1

Please sign in to comment.