Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/smooth-kids-tease.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': major
---

Allows erroring or ignoring when prerendered routes conflict - ([v6 upgrade guidance](https://deploy-preview-12322--astro-docs-2.netlify.app/en/guides/upgrade-to/v6/#changed-configurable-prerendered-routes-conflict-behavior))
Comment thread
florian-lefebvre marked this conversation as resolved.
Outdated
Comment thread
florian-lefebvre marked this conversation as resolved.
Outdated
4 changes: 2 additions & 2 deletions packages/astro/src/core/build/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ async function getPathsForRoute(

// Current route is lower-priority than matchedRoute.
// Path will be skipped due to collision.
if (config.experimental.failOnPrerenderConflict) {
if (config.prerenderConflictBehavior === 'error') {
throw new AstroError({
...AstroErrorData.PrerenderRouteConflict,
message: AstroErrorData.PrerenderRouteConflict.message(
Expand All @@ -422,7 +422,7 @@ async function getPathsForRoute(
),
hint: AstroErrorData.PrerenderRouteConflict.hint(matchedRoute.route, route.route),
});
} else {
} else if (config.prerenderConflictBehavior === 'warning') {
Comment thread
florian-lefebvre marked this conversation as resolved.
Outdated
const msg = AstroErrorData.PrerenderRouteConflict.message(
matchedRoute.route,
route.route,
Expand Down
10 changes: 5 additions & 5 deletions packages/astro/src/core/config/schemas/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,12 @@ export const ASTRO_CONFIG_DEFAULTS = {
validateSecrets: false,
},
session: undefined,
prerenderConflictBehavior: 'warning',
Comment thread
florian-lefebvre marked this conversation as resolved.
Outdated
experimental: {
clientPrerender: false,
contentIntellisense: false,
csp: false,
chromeDevtoolsWorkspace: false,
failOnPrerenderConflict: false,
svgo: false,
},
} satisfies AstroUserConfig & { server: { open: boolean } };
Expand Down Expand Up @@ -463,6 +463,10 @@ export const AstroConfigSchema = z.object({
ttl: z.number().optional(),
})
.optional(),
prerenderConflictBehavior: z
.enum(['error', 'warning', 'ignore'])
Comment thread
florian-lefebvre marked this conversation as resolved.
Outdated
.optional()
.default(ASTRO_CONFIG_DEFAULTS.prerenderConflictBehavior),
experimental: z
.object({
clientPrerender: z
Expand Down Expand Up @@ -501,10 +505,6 @@ export const AstroConfigSchema = z.object({
.boolean()
.optional()
.default(ASTRO_CONFIG_DEFAULTS.experimental.chromeDevtoolsWorkspace),
failOnPrerenderConflict: z
.boolean()
.optional()
.default(ASTRO_CONFIG_DEFAULTS.experimental.failOnPrerenderConflict),
svgo: z
.union([z.boolean(), z.custom<SvgoConfig>((value) => value && typeof value === 'object')])
.optional()
Expand Down
26 changes: 14 additions & 12 deletions packages/astro/src/types/public/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2029,6 +2029,20 @@ export interface AstroUserConfig<
validateSecrets?: boolean;
};

/**
*
* @name prerenderConflictBehavior
* @type {'warning' | 'error' | 'ignore'}
* @default `'warning'`
* @version 6.0
* @description
* When two routes generate the same prerendered URL, defines Astro's behavior:
Comment thread
florian-lefebvre marked this conversation as resolved.
Outdated
* - Error: fail the build
* - Warning (default): logs a warning when conflicts occur and the highest-priority route wins
* - Ignore: silently picks the highest-priority route when conflicts occur
Comment thread
florian-lefebvre marked this conversation as resolved.
Outdated
*/
prerenderConflictBehavior?: 'warning' | 'error' | 'ignore';

/**
*
* @kind heading
Expand Down Expand Up @@ -2085,18 +2099,6 @@ export interface AstroUserConfig<
*/
clientPrerender?: boolean;

/**
*
* @name experimental.failOnPrerenderConflict
* @type {boolean}
* @default `false`
* @version 5.x
* @description
* When two routes generate the same prerendered URL, fail the build instead of skipping one.
* If disabled (default), a warning is logged when conflicts occur and the highest-priority route wins.
*/
failOnPrerenderConflict?: boolean;

/**
*
* @name experimental.contentIntellisense
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { defineConfig } from 'astro/config';

export default defineConfig({
experimental: {
failOnPrerenderConflict: false,
},
prerenderConflictBehavior: 'warning',
Comment thread
florian-lefebvre marked this conversation as resolved.
Outdated
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { defineConfig } from 'astro/config';

export default defineConfig({
experimental: {
failOnPrerenderConflict: false,
},
prerenderConflictBehavior: 'warning',
Comment thread
florian-lefebvre marked this conversation as resolved.
Outdated
});
14 changes: 7 additions & 7 deletions packages/astro/test/prerender-conflict.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { loadFixture } from './test-utils.js';

/**
* Dynamic vs dynamic duplication should warn by default and succeed.
* When experimental.failOnPrerenderConflict is true, it should fail.
* When prerenderConflictBehavior is set to 'error', it should fail.
* Static vs dynamic should also warn/fail similarly.
*/

Expand Down Expand Up @@ -43,14 +43,14 @@ describe('Prerender conflicts', () => {
);
});

it('fails when experimental.failOnPrerenderConflict = true', async () => {
it('fails when prerenderConflictBehavior is set to error', async () => {
let err;
try {
await fixture.build({ experimental: { failOnPrerenderConflict: true } });
await fixture.build({ prerenderConflictBehavior: 'error' });
} catch (e) {
err = e;
}
assert.ok(err, 'Build should fail when failOnPrerenderConflict is true');
assert.ok(err, 'Build should fail when prerenderConflictBehavior is set to error');
assert.equal(
String(err),
'PrerenderRouteConflict: Could not render `/c` from route `/[foo]` as it conflicts with higher priority route `/[bar]`.',
Expand Down Expand Up @@ -91,14 +91,14 @@ describe('Prerender conflicts', () => {
);
});

it('fails when experimental.failOnPrerenderConflict = true', async () => {
it('fails when prerenderConflictBehavior is set to error', async () => {
let err;
try {
await fixture.build({ experimental: { failOnPrerenderConflict: true } });
await fixture.build({ prerenderConflictBehavior: 'error' });
} catch (e) {
err = e;
}
assert.ok(err, 'Build should fail when failOnPrerenderConflict is true');
assert.ok(err, 'Build should fail when prerenderConflictBehavior is set to error');
assert.equal(
String(err),
'PrerenderRouteConflict: Could not render `/c` from route `/[foo]` as it conflicts with higher priority route `/c`.',
Expand Down