mirror of
https://github.com/withastro/astro.git
synced 2025-02-17 22:44:24 -05:00
Warn when getStaticPaths
exists without a prerender
statement (#7713)
* wip: warning on getStaticPaths without prerender * refactor: move getStaticPaths warning to scanner plugin * chore: do not add to test fixture * chore: remove legacy getStaticPaths validation * refactor: update warning message * chore: typo * chore: add changeset * chore: remove unused variables * refactor: make settings optional * chore: fix lint * chore: update message to include reason
This commit is contained in:
parent
4eba967d2b
commit
d088351f54
6 changed files with 35 additions and 21 deletions
5
.changeset/sixty-plums-appear.md
Normal file
5
.changeset/sixty-plums-appear.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Update warning when `getStaticPaths` is detected but a route is not prerendered.
|
|
@ -125,7 +125,7 @@ export async function createVite(
|
||||||
mode === 'dev' && astroIntegrationsContainerPlugin({ settings, logging }),
|
mode === 'dev' && astroIntegrationsContainerPlugin({ settings, logging }),
|
||||||
astroScriptsPageSSRPlugin({ settings }),
|
astroScriptsPageSSRPlugin({ settings }),
|
||||||
astroHeadPlugin(),
|
astroHeadPlugin(),
|
||||||
astroScannerPlugin({ settings }),
|
astroScannerPlugin({ settings, logging }),
|
||||||
astroInjectEnvTsPlugin({ settings, logging, fs }),
|
astroInjectEnvTsPlugin({ settings, logging, fs }),
|
||||||
astroContentVirtualModPlugin({ settings }),
|
astroContentVirtualModPlugin({ settings }),
|
||||||
astroContentImportPlugin({ fs, settings }),
|
astroContentImportPlugin({ fs, settings }),
|
||||||
|
|
|
@ -34,7 +34,7 @@ export async function callGetStaticPaths({
|
||||||
const cached = routeCache.get(route);
|
const cached = routeCache.get(route);
|
||||||
if (cached?.staticPaths) return cached.staticPaths;
|
if (cached?.staticPaths) return cached.staticPaths;
|
||||||
|
|
||||||
validateDynamicRouteModule(mod, { ssr, logging, route });
|
validateDynamicRouteModule(mod, { ssr, route });
|
||||||
|
|
||||||
// No static paths in SSR mode. Return an empty RouteCacheEntry.
|
// No static paths in SSR mode. Return an empty RouteCacheEntry.
|
||||||
if (ssr && !route.prerender) {
|
if (ssr && !route.prerender) {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { bold } from 'kleur/colors';
|
|
||||||
import type { ComponentInstance, GetStaticPathsResult, RouteData } from '../../@types/astro';
|
import type { ComponentInstance, GetStaticPathsResult, RouteData } from '../../@types/astro';
|
||||||
import { AstroError, AstroErrorData } from '../errors/index.js';
|
import { AstroError, AstroErrorData } from '../errors/index.js';
|
||||||
import type { LogOptions } from '../logger/core';
|
import type { LogOptions } from '../logger/core';
|
||||||
|
@ -19,26 +18,17 @@ export function validateGetStaticPathsParameter([key, value]: [string, any], rou
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Warn or error for deprecated or malformed route components */
|
/** Error for deprecated or malformed route components */
|
||||||
export function validateDynamicRouteModule(
|
export function validateDynamicRouteModule(
|
||||||
mod: ComponentInstance,
|
mod: ComponentInstance,
|
||||||
{
|
{
|
||||||
ssr,
|
ssr,
|
||||||
logging,
|
|
||||||
route,
|
route,
|
||||||
}: {
|
}: {
|
||||||
ssr: boolean;
|
ssr: boolean;
|
||||||
logging: LogOptions;
|
|
||||||
route: RouteData;
|
route: RouteData;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
if (ssr && mod.getStaticPaths && !route.prerender) {
|
|
||||||
warn(
|
|
||||||
logging,
|
|
||||||
'getStaticPaths',
|
|
||||||
`getStaticPaths() in ${bold(route.component)} is ignored when "output: server" is set.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ((!ssr || route.prerender) && !mod.getStaticPaths) {
|
if ((!ssr || route.prerender) && !mod.getStaticPaths) {
|
||||||
throw new AstroError({
|
throw new AstroError({
|
||||||
...AstroErrorData.GetStaticPathsRequired,
|
...AstroErrorData.GetStaticPathsRequired,
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
import { normalizePath, type Plugin as VitePlugin } from 'vite';
|
import type { Plugin as VitePlugin } from 'vite';
|
||||||
import type { AstroSettings } from '../@types/astro.js';
|
import type { AstroSettings } from '../@types/astro.js';
|
||||||
import { isEndpoint, isPage } from '../core/util.js';
|
import { type LogOptions } from '../core/logger/core.js';
|
||||||
|
|
||||||
import { getPrerenderDefault } from '../prerender/utils.js';
|
import { normalizePath } from 'vite';
|
||||||
|
import { bold } from 'kleur/colors';
|
||||||
|
import { warn } from '../core/logger/core.js';
|
||||||
|
import { isEndpoint, isPage, rootRelativePath } from '../core/util.js';
|
||||||
|
import { getPrerenderDefault, isServerLikeOutput } from '../prerender/utils.js';
|
||||||
import { scan } from './scan.js';
|
import { scan } from './scan.js';
|
||||||
|
|
||||||
export default function astroScannerPlugin({ settings }: { settings: AstroSettings }): VitePlugin {
|
export interface AstroPluginScannerOptions {
|
||||||
|
settings: AstroSettings;
|
||||||
|
logging: LogOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function astroScannerPlugin({ settings, logging }: AstroPluginScannerOptions): VitePlugin {
|
||||||
return {
|
return {
|
||||||
name: 'astro:scanner',
|
name: 'astro:scanner',
|
||||||
enforce: 'post',
|
enforce: 'post',
|
||||||
|
@ -26,11 +35,17 @@ export default function astroScannerPlugin({ settings }: { settings: AstroSettin
|
||||||
const fileIsEndpoint = isEndpoint(fileURL, settings);
|
const fileIsEndpoint = isEndpoint(fileURL, settings);
|
||||||
if (!(fileIsPage || fileIsEndpoint)) return;
|
if (!(fileIsPage || fileIsEndpoint)) return;
|
||||||
const defaultPrerender = getPrerenderDefault(settings.config);
|
const defaultPrerender = getPrerenderDefault(settings.config);
|
||||||
const pageOptions = await scan(code, id, settings.config.output === 'hybrid');
|
const pageOptions = await scan(code, id, settings);
|
||||||
|
|
||||||
if (typeof pageOptions.prerender === 'undefined') {
|
if (typeof pageOptions.prerender === 'undefined') {
|
||||||
pageOptions.prerender = defaultPrerender;
|
pageOptions.prerender = defaultPrerender;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `getStaticPaths` warning is just a string check, should be good enough for most cases
|
||||||
|
if (!pageOptions.prerender && isServerLikeOutput(settings.config) && code.includes('getStaticPaths')) {
|
||||||
|
const reason = ` because \`output: "${settings.config.output}"\` is set`
|
||||||
|
warn(logging, "getStaticPaths", `The getStaticPaths() statement in ${bold(rootRelativePath(settings.config.root, fileURL, true))} has been ignored${reason}.\n\nAdd \`export const prerender = true;\` to prerender this page.`);
|
||||||
|
}
|
||||||
|
|
||||||
const { meta = {} } = this.getModuleInfo(id) ?? {};
|
const { meta = {} } = this.getModuleInfo(id) ?? {};
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
import type { PageOptions } from '../vite-plugin-astro/types.js';
|
||||||
|
import type { AstroSettings } from '../@types/astro.js';
|
||||||
|
|
||||||
import * as eslexer from 'es-module-lexer';
|
import * as eslexer from 'es-module-lexer';
|
||||||
import { AstroError, AstroErrorData } from '../core/errors/index.js';
|
import { AstroError, AstroErrorData } from '../core/errors/index.js';
|
||||||
import type { PageOptions } from '../vite-plugin-astro/types.js';
|
|
||||||
|
|
||||||
const BOOLEAN_EXPORTS = new Set(['prerender']);
|
const BOOLEAN_EXPORTS = new Set(['prerender']);
|
||||||
|
|
||||||
|
@ -34,7 +36,7 @@ function isFalsy(value: string) {
|
||||||
|
|
||||||
let didInit = false;
|
let didInit = false;
|
||||||
|
|
||||||
export async function scan(code: string, id: string, isHybridOutput = false): Promise<PageOptions> {
|
export async function scan(code: string, id: string, settings?: AstroSettings): Promise<PageOptions> {
|
||||||
if (!includesExport(code)) return {};
|
if (!includesExport(code)) return {};
|
||||||
if (!didInit) {
|
if (!didInit) {
|
||||||
await eslexer.init;
|
await eslexer.init;
|
||||||
|
@ -42,6 +44,7 @@ export async function scan(code: string, id: string, isHybridOutput = false): Pr
|
||||||
}
|
}
|
||||||
|
|
||||||
const [, exports] = eslexer.parse(code, id);
|
const [, exports] = eslexer.parse(code, id);
|
||||||
|
|
||||||
let pageOptions: PageOptions = {};
|
let pageOptions: PageOptions = {};
|
||||||
for (const _export of exports) {
|
for (const _export of exports) {
|
||||||
const { n: name, le: endOfLocalName } = _export;
|
const { n: name, le: endOfLocalName } = _export;
|
||||||
|
@ -62,7 +65,7 @@ export async function scan(code: string, id: string, isHybridOutput = false): Pr
|
||||||
if (prefix !== 'const' || !(isTruthy(suffix) || isFalsy(suffix))) {
|
if (prefix !== 'const' || !(isTruthy(suffix) || isFalsy(suffix))) {
|
||||||
throw new AstroError({
|
throw new AstroError({
|
||||||
...AstroErrorData.InvalidPrerenderExport,
|
...AstroErrorData.InvalidPrerenderExport,
|
||||||
message: AstroErrorData.InvalidPrerenderExport.message(prefix, suffix, isHybridOutput),
|
message: AstroErrorData.InvalidPrerenderExport.message(prefix, suffix, settings?.config.output === 'hybrid' ?? false),
|
||||||
location: { file: id },
|
location: { file: id },
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -70,5 +73,6 @@ export async function scan(code: string, id: string, isHybridOutput = false): Pr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pageOptions;
|
return pageOptions;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue