From ed662490184f25d539a13a3be33aded99c54b3b8 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Tue, 18 Jul 2023 15:25:06 -0500 Subject: [PATCH 01/11] wip: warning on getStaticPaths without prerender --- packages/astro/src/core/create-vite.ts | 2 +- .../astro/src/vite-plugin-scanner/index.ts | 10 ++++++-- .../astro/src/vite-plugin-scanner/scan.ts | 23 ++++++++++++++++--- .../src/pages/missing/[slug].astro | 16 +++++++++++++ 4 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 packages/astro/test/fixtures/ssr-prerender-get-static-paths/src/pages/missing/[slug].astro diff --git a/packages/astro/src/core/create-vite.ts b/packages/astro/src/core/create-vite.ts index 279a7ffde940..52b5fd277a40 100644 --- a/packages/astro/src/core/create-vite.ts +++ b/packages/astro/src/core/create-vite.ts @@ -125,7 +125,7 @@ export async function createVite( mode === 'dev' && astroIntegrationsContainerPlugin({ settings, logging }), astroScriptsPageSSRPlugin({ settings }), astroHeadPlugin(), - astroScannerPlugin({ settings }), + astroScannerPlugin({ settings, logging }), astroInjectEnvTsPlugin({ settings, logging, fs }), astroContentVirtualModPlugin({ settings }), astroContentImportPlugin({ fs, settings }), diff --git a/packages/astro/src/vite-plugin-scanner/index.ts b/packages/astro/src/vite-plugin-scanner/index.ts index 465ff74ed6c4..f139d4649a24 100644 --- a/packages/astro/src/vite-plugin-scanner/index.ts +++ b/packages/astro/src/vite-plugin-scanner/index.ts @@ -1,11 +1,17 @@ import { normalizePath, type Plugin as VitePlugin } from 'vite'; import type { AstroSettings } from '../@types/astro.js'; +import type { LogOptions } from '../core/logger/core.js'; import { isEndpoint, isPage } from '../core/util.js'; import { getPrerenderDefault } from '../prerender/utils.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 { name: 'astro:scanner', enforce: 'post', @@ -26,7 +32,7 @@ export default function astroScannerPlugin({ settings }: { settings: AstroSettin const fileIsEndpoint = isEndpoint(fileURL, settings); if (!(fileIsPage || fileIsEndpoint)) return; const defaultPrerender = getPrerenderDefault(settings.config); - const pageOptions = await scan(code, id, settings.config.output === 'hybrid'); + const pageOptions = await scan(code, id, settings, logging); if (typeof pageOptions.prerender === 'undefined') { pageOptions.prerender = defaultPrerender; diff --git a/packages/astro/src/vite-plugin-scanner/scan.ts b/packages/astro/src/vite-plugin-scanner/scan.ts index 83ca3c5c5cde..3c3394fa032f 100644 --- a/packages/astro/src/vite-plugin-scanner/scan.ts +++ b/packages/astro/src/vite-plugin-scanner/scan.ts @@ -1,7 +1,12 @@ +import type { PageOptions } from '../vite-plugin-astro/types.js'; +import type { AstroSettings } from '../@types/astro.js'; + import * as eslexer from 'es-module-lexer'; import { AstroError, AstroErrorData } from '../core/errors/index.js'; -import type { PageOptions } from '../vite-plugin-astro/types.js'; +import { isServerLikeOutput } from '../prerender/utils.js'; +import { warn, type LogOptions } from '../core/logger/core.js'; +const FUNCTION_EXPORTS = new Set(['getStaticPaths']); const BOOLEAN_EXPORTS = new Set(['prerender']); // Quick scan to determine if code includes recognized export @@ -10,6 +15,9 @@ function includesExport(code: string) { for (const name of BOOLEAN_EXPORTS) { if (code.includes(name)) return true; } + for (const name of FUNCTION_EXPORTS) { + if (code.includes(name)) return true; + } return false; } @@ -34,7 +42,7 @@ function isFalsy(value: string) { let didInit = false; -export async function scan(code: string, id: string, isHybridOutput = false): Promise { +export async function scan(code: string, id: string, settings: AstroSettings, logging: LogOptions): Promise { if (!includesExport(code)) return {}; if (!didInit) { await eslexer.init; @@ -42,6 +50,7 @@ export async function scan(code: string, id: string, isHybridOutput = false): Pr } const [, exports] = eslexer.parse(code, id); + let pageOptions: PageOptions = {}; for (const _export of exports) { const { n: name, le: endOfLocalName } = _export; @@ -62,7 +71,7 @@ export async function scan(code: string, id: string, isHybridOutput = false): Pr if (prefix !== 'const' || !(isTruthy(suffix) || isFalsy(suffix))) { throw new AstroError({ ...AstroErrorData.InvalidPrerenderExport, - message: AstroErrorData.InvalidPrerenderExport.message(prefix, suffix, isHybridOutput), + message: AstroErrorData.InvalidPrerenderExport.message(prefix, suffix, settings.config.output === 'hybrid'), location: { file: id }, }); } else { @@ -70,5 +79,13 @@ export async function scan(code: string, id: string, isHybridOutput = false): Pr } } } + + if (settings.config.output === 'server' && !pageOptions.prerender) { + const hasGetStaticPaths = Boolean(exports.find(_export => _export.n === 'getStaticPaths')); + if (hasGetStaticPaths) { + warn(logging, 'scan', `getStaticPaths`) + } + } + return pageOptions; } diff --git a/packages/astro/test/fixtures/ssr-prerender-get-static-paths/src/pages/missing/[slug].astro b/packages/astro/test/fixtures/ssr-prerender-get-static-paths/src/pages/missing/[slug].astro new file mode 100644 index 000000000000..c52de0f93efa --- /dev/null +++ b/packages/astro/test/fixtures/ssr-prerender-get-static-paths/src/pages/missing/[slug].astro @@ -0,0 +1,16 @@ +--- +export function getStaticPaths() { + return [ + [ { params: {slug: "slug1"} } ], + [ { params: {slug: "slug2"} } ], + ] +} +// Important! Do not include `export const prerender = true` +--- + + + + Prerender missing + + + From f8bde3c6e808c24aec31bf4e4d19557b88e7b076 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Tue, 18 Jul 2023 15:40:17 -0500 Subject: [PATCH 02/11] refactor: move getStaticPaths warning to scanner plugin --- packages/astro/src/vite-plugin-scanner/index.ts | 11 ++++++++--- packages/astro/src/vite-plugin-scanner/scan.ts | 15 +-------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/packages/astro/src/vite-plugin-scanner/index.ts b/packages/astro/src/vite-plugin-scanner/index.ts index f139d4649a24..3781776c2775 100644 --- a/packages/astro/src/vite-plugin-scanner/index.ts +++ b/packages/astro/src/vite-plugin-scanner/index.ts @@ -1,9 +1,9 @@ import { normalizePath, type Plugin as VitePlugin } from 'vite'; import type { AstroSettings } from '../@types/astro.js'; -import type { LogOptions } from '../core/logger/core.js'; +import { warn, type LogOptions } from '../core/logger/core.js'; import { isEndpoint, isPage } from '../core/util.js'; -import { getPrerenderDefault } from '../prerender/utils.js'; +import { getPrerenderDefault, isServerLikeOutput } from '../prerender/utils.js'; import { scan } from './scan.js'; export interface AstroPluginScannerOptions { @@ -32,11 +32,16 @@ export default function astroScannerPlugin({ settings, logging }: AstroPluginSca const fileIsEndpoint = isEndpoint(fileURL, settings); if (!(fileIsPage || fileIsEndpoint)) return; const defaultPrerender = getPrerenderDefault(settings.config); - const pageOptions = await scan(code, id, settings, logging); + const pageOptions = await scan(code, id, settings); if (typeof pageOptions.prerender === 'undefined') { 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')) { + warn(logging, "getStaticPaths", `The getStaticPaths() statement in ${id} will be ignored. Add \`export const prerender = true;\` to prerender this page.`); + } const { meta = {} } = this.getModuleInfo(id) ?? {}; return { diff --git a/packages/astro/src/vite-plugin-scanner/scan.ts b/packages/astro/src/vite-plugin-scanner/scan.ts index 3c3394fa032f..546129bbe599 100644 --- a/packages/astro/src/vite-plugin-scanner/scan.ts +++ b/packages/astro/src/vite-plugin-scanner/scan.ts @@ -3,10 +3,7 @@ import type { AstroSettings } from '../@types/astro.js'; import * as eslexer from 'es-module-lexer'; import { AstroError, AstroErrorData } from '../core/errors/index.js'; -import { isServerLikeOutput } from '../prerender/utils.js'; -import { warn, type LogOptions } from '../core/logger/core.js'; -const FUNCTION_EXPORTS = new Set(['getStaticPaths']); const BOOLEAN_EXPORTS = new Set(['prerender']); // Quick scan to determine if code includes recognized export @@ -15,9 +12,6 @@ function includesExport(code: string) { for (const name of BOOLEAN_EXPORTS) { if (code.includes(name)) return true; } - for (const name of FUNCTION_EXPORTS) { - if (code.includes(name)) return true; - } return false; } @@ -42,7 +36,7 @@ function isFalsy(value: string) { let didInit = false; -export async function scan(code: string, id: string, settings: AstroSettings, logging: LogOptions): Promise { +export async function scan(code: string, id: string, settings: AstroSettings): Promise { if (!includesExport(code)) return {}; if (!didInit) { await eslexer.init; @@ -80,12 +74,5 @@ export async function scan(code: string, id: string, settings: AstroSettings, lo } } - if (settings.config.output === 'server' && !pageOptions.prerender) { - const hasGetStaticPaths = Boolean(exports.find(_export => _export.n === 'getStaticPaths')); - if (hasGetStaticPaths) { - warn(logging, 'scan', `getStaticPaths`) - } - } - return pageOptions; } From a110d0fdcd98324f59495782baa27dc936410e73 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Tue, 18 Jul 2023 15:46:38 -0500 Subject: [PATCH 03/11] chore: do not add to test fixture --- .../src/pages/missing/[slug].astro | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 packages/astro/test/fixtures/ssr-prerender-get-static-paths/src/pages/missing/[slug].astro diff --git a/packages/astro/test/fixtures/ssr-prerender-get-static-paths/src/pages/missing/[slug].astro b/packages/astro/test/fixtures/ssr-prerender-get-static-paths/src/pages/missing/[slug].astro deleted file mode 100644 index c52de0f93efa..000000000000 --- a/packages/astro/test/fixtures/ssr-prerender-get-static-paths/src/pages/missing/[slug].astro +++ /dev/null @@ -1,16 +0,0 @@ ---- -export function getStaticPaths() { - return [ - [ { params: {slug: "slug1"} } ], - [ { params: {slug: "slug2"} } ], - ] -} -// Important! Do not include `export const prerender = true` ---- - - - - Prerender missing - - - From a6ce2e7ba75bcd37b90630c1daee3a6a9c547677 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Tue, 18 Jul 2023 15:51:03 -0500 Subject: [PATCH 04/11] chore: remove legacy getStaticPaths validation --- packages/astro/src/core/routing/validation.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/astro/src/core/routing/validation.ts b/packages/astro/src/core/routing/validation.ts index 1a3bab82a2ee..2ebf4b1d4aae 100644 --- a/packages/astro/src/core/routing/validation.ts +++ b/packages/astro/src/core/routing/validation.ts @@ -19,7 +19,7 @@ export function validateGetStaticPathsParameter([key, value]: [string, any], rou } } -/** Warn or error for deprecated or malformed route components */ +/** Rrror for deprecated or malformed route components */ export function validateDynamicRouteModule( mod: ComponentInstance, { @@ -32,13 +32,6 @@ export function validateDynamicRouteModule( 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) { throw new AstroError({ ...AstroErrorData.GetStaticPathsRequired, From 4d3a2a95072c6dedb81fa2576148b62fb8de242e Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Tue, 18 Jul 2023 16:00:06 -0500 Subject: [PATCH 05/11] refactor: update warning message --- packages/astro/src/vite-plugin-scanner/index.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/astro/src/vite-plugin-scanner/index.ts b/packages/astro/src/vite-plugin-scanner/index.ts index 3781776c2775..daed05ee9732 100644 --- a/packages/astro/src/vite-plugin-scanner/index.ts +++ b/packages/astro/src/vite-plugin-scanner/index.ts @@ -1,8 +1,11 @@ -import { normalizePath, type Plugin as VitePlugin } from 'vite'; +import type { Plugin as VitePlugin } from 'vite'; import type { AstroSettings } from '../@types/astro.js'; -import { warn, type LogOptions } from '../core/logger/core.js'; -import { isEndpoint, isPage } from '../core/util.js'; +import { type LogOptions } from '../core/logger/core.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'; @@ -40,7 +43,7 @@ export default function astroScannerPlugin({ settings, logging }: AstroPluginSca // `getStaticPaths` warning is just a string check, should be good enough for most cases if (!pageOptions.prerender && isServerLikeOutput(settings.config) && code.includes('getStaticPaths')) { - warn(logging, "getStaticPaths", `The getStaticPaths() statement in ${id} will be ignored. Add \`export const prerender = true;\` to prerender this page.`); + warn(logging, "getStaticPaths", `The getStaticPaths() statement in ${bold(rootRelativePath(settings.config.root, fileURL, true))} has been ignored.\n\nAdd \`export const prerender = true;\` to prerender this page.`); } const { meta = {} } = this.getModuleInfo(id) ?? {}; From 9394006b263ba6f641808aae8682476dcaa8e94b Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Tue, 18 Jul 2023 16:00:34 -0500 Subject: [PATCH 06/11] chore: typo --- packages/astro/src/core/routing/validation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/astro/src/core/routing/validation.ts b/packages/astro/src/core/routing/validation.ts index 2ebf4b1d4aae..cdbb3602aed0 100644 --- a/packages/astro/src/core/routing/validation.ts +++ b/packages/astro/src/core/routing/validation.ts @@ -19,7 +19,7 @@ export function validateGetStaticPathsParameter([key, value]: [string, any], rou } } -/** Rrror for deprecated or malformed route components */ +/** Error for deprecated or malformed route components */ export function validateDynamicRouteModule( mod: ComponentInstance, { From 9c2406aa3405ca670b6cc169119a25ff2201f9a3 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Tue, 18 Jul 2023 16:03:33 -0500 Subject: [PATCH 07/11] chore: add changeset --- .changeset/sixty-plums-appear.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sixty-plums-appear.md diff --git a/.changeset/sixty-plums-appear.md b/.changeset/sixty-plums-appear.md new file mode 100644 index 000000000000..3b8150ca0573 --- /dev/null +++ b/.changeset/sixty-plums-appear.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Update warning when `getStaticPaths` is detected but a route is not prerendered. From 411db3cfa4879d5984559983b8d06e02ed921eb4 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Tue, 18 Jul 2023 16:09:08 -0500 Subject: [PATCH 08/11] chore: remove unused variables --- packages/astro/src/core/render/route-cache.ts | 2 +- packages/astro/src/core/routing/validation.ts | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/astro/src/core/render/route-cache.ts b/packages/astro/src/core/render/route-cache.ts index 71b2966dea35..7ad247ef8d81 100644 --- a/packages/astro/src/core/render/route-cache.ts +++ b/packages/astro/src/core/render/route-cache.ts @@ -34,7 +34,7 @@ export async function callGetStaticPaths({ const cached = routeCache.get(route); 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. if (ssr && !route.prerender) { diff --git a/packages/astro/src/core/routing/validation.ts b/packages/astro/src/core/routing/validation.ts index cdbb3602aed0..9a562c044aa3 100644 --- a/packages/astro/src/core/routing/validation.ts +++ b/packages/astro/src/core/routing/validation.ts @@ -1,4 +1,3 @@ -import { bold } from 'kleur/colors'; import type { ComponentInstance, GetStaticPathsResult, RouteData } from '../../@types/astro'; import { AstroError, AstroErrorData } from '../errors/index.js'; import type { LogOptions } from '../logger/core'; @@ -24,11 +23,9 @@ export function validateDynamicRouteModule( mod: ComponentInstance, { ssr, - logging, route, }: { ssr: boolean; - logging: LogOptions; route: RouteData; } ) { From d79d1417ec9c671ee5236878c566b09a3520a5ad Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Tue, 18 Jul 2023 16:11:29 -0500 Subject: [PATCH 09/11] refactor: make settings optional --- packages/astro/src/vite-plugin-scanner/scan.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/astro/src/vite-plugin-scanner/scan.ts b/packages/astro/src/vite-plugin-scanner/scan.ts index 546129bbe599..c97a6c005b7e 100644 --- a/packages/astro/src/vite-plugin-scanner/scan.ts +++ b/packages/astro/src/vite-plugin-scanner/scan.ts @@ -3,6 +3,7 @@ import type { AstroSettings } from '../@types/astro.js'; import * as eslexer from 'es-module-lexer'; import { AstroError, AstroErrorData } from '../core/errors/index.js'; +import { isServerLikeOutput } from '../prerender/utils.js'; const BOOLEAN_EXPORTS = new Set(['prerender']); @@ -36,7 +37,7 @@ function isFalsy(value: string) { let didInit = false; -export async function scan(code: string, id: string, settings: AstroSettings): Promise { +export async function scan(code: string, id: string, settings?: AstroSettings): Promise { if (!includesExport(code)) return {}; if (!didInit) { await eslexer.init; @@ -65,7 +66,7 @@ export async function scan(code: string, id: string, settings: AstroSettings): P if (prefix !== 'const' || !(isTruthy(suffix) || isFalsy(suffix))) { throw new AstroError({ ...AstroErrorData.InvalidPrerenderExport, - message: AstroErrorData.InvalidPrerenderExport.message(prefix, suffix, settings.config.output === 'hybrid'), + message: AstroErrorData.InvalidPrerenderExport.message(prefix, suffix, settings?.config.output === 'hybrid' ?? false), location: { file: id }, }); } else { From 01bf1ff663164722cde32a5973b0d645cbab2e72 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Tue, 18 Jul 2023 16:41:01 -0500 Subject: [PATCH 10/11] chore: fix lint --- packages/astro/src/vite-plugin-scanner/scan.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/astro/src/vite-plugin-scanner/scan.ts b/packages/astro/src/vite-plugin-scanner/scan.ts index c97a6c005b7e..69a0945d6bb7 100644 --- a/packages/astro/src/vite-plugin-scanner/scan.ts +++ b/packages/astro/src/vite-plugin-scanner/scan.ts @@ -3,7 +3,6 @@ import type { AstroSettings } from '../@types/astro.js'; import * as eslexer from 'es-module-lexer'; import { AstroError, AstroErrorData } from '../core/errors/index.js'; -import { isServerLikeOutput } from '../prerender/utils.js'; const BOOLEAN_EXPORTS = new Set(['prerender']); From 701244c828c1d07e60c5c7e7d3a694d9261adbac Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Tue, 18 Jul 2023 16:44:58 -0500 Subject: [PATCH 11/11] chore: update message to include reason --- packages/astro/src/vite-plugin-scanner/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/astro/src/vite-plugin-scanner/index.ts b/packages/astro/src/vite-plugin-scanner/index.ts index daed05ee9732..439a56d4649f 100644 --- a/packages/astro/src/vite-plugin-scanner/index.ts +++ b/packages/astro/src/vite-plugin-scanner/index.ts @@ -43,7 +43,8 @@ export default function astroScannerPlugin({ settings, logging }: AstroPluginSca // `getStaticPaths` warning is just a string check, should be good enough for most cases if (!pageOptions.prerender && isServerLikeOutput(settings.config) && code.includes('getStaticPaths')) { - warn(logging, "getStaticPaths", `The getStaticPaths() statement in ${bold(rootRelativePath(settings.config.root, fileURL, true))} has been ignored.\n\nAdd \`export const prerender = true;\` to prerender this page.`); + 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) ?? {};