Skip to content

Commit aad9e5f

Browse files
taty2010nickytonlineLekoArts
authored
Fix: Legacy fallback env var (#2074)
Co-authored-by: Nick Taylor <[email protected]> Co-authored-by: Lennart <[email protected]>
1 parent 39be74a commit aad9e5f

File tree

4 files changed

+106
-2
lines changed

4 files changed

+106
-2
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ The Next.js Runtime fully supports ISR on Netlify. For more details see
8989

9090
Note that Netlify has a minimum TTL of 60 seconds for revalidation.
9191

92+
## Disable Static 404 on Dynamic Routes with fallback:false
93+
94+
Currently when hitting a non-prerendered path with `fallback=false` it will default to a 404 page. You can now change this default setting by using the environemnt variable `LEGACY_FALLBACK_FALSE=true`. With the environment variable set, those non-prerendered paths will now be routed through using the ISR Handler and will allow you to add redirects for those non-prerendered paths.
95+
9296
## Use with `next export`
9397

9498
If you are using `next export` to generate a static site, you do not need most of the functionality of this Next.js

demos/default/next.config.js

+5
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ module.exports = {
6767
destination: '/',
6868
permanent: true,
6969
},
70+
{
71+
source: '/getStaticProps/4/',
72+
destination: '/',
73+
permanent: true,
74+
},
7075
]
7176
},
7277
// https://nextjs.org/docs/basic-features/image-optimization#domains

packages/runtime/src/helpers/redirects.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { NetlifyConfig } from '@netlify/build'
22
import { yellowBright } from 'chalk'
3+
import destr from 'destr'
34
import { readJSON } from 'fs-extra'
45
import type { NextConfig } from 'next'
56
import type { PrerenderManifest, SsgRoute } from 'next/dist/build'
@@ -194,7 +195,7 @@ const generateStaticIsrRewrites = ({
194195
/**
195196
* Generate rewrites for all dynamic routes
196197
*/
197-
const generateDynamicRewrites = ({
198+
export const generateDynamicRewrites = ({
198199
dynamicRoutes,
199200
prerenderedDynamicRoutes,
200201
middleware,
@@ -238,7 +239,11 @@ const generateDynamicRewrites = ({
238239
withData: true,
239240
}),
240241
)
241-
} else if (prerenderedDynamicRoutes[route.page].fallback === false && !is404Isr) {
242+
} else if (
243+
prerenderedDynamicRoutes[route.page].fallback === false &&
244+
!is404Isr &&
245+
!destr(process.env.LEGACY_FALLBACK_FALSE)
246+
) {
242247
dynamicRewrites.push(...redirectsForNext404Route({ route: route.page, buildId, basePath, i18n }))
243248
} else {
244249
dynamicRewrites.push(

test/helpers/utils.spec.ts

+90
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,55 @@
11
import Chance from 'chance'
2+
import type { PrerenderManifest } from 'next/dist/build'
23
import { ExperimentalConfig } from 'next/dist/server/config-shared'
34

5+
import { generateDynamicRewrites } from '../../packages/runtime/src/helpers/redirects'
46
import {
57
getCustomImageResponseHeaders,
68
getRemotePatterns,
79
ImagesConfig,
810
redirectsForNext404Route,
911
} from '../../packages/runtime/src/helpers/utils'
1012

13+
const basePrerenderManifest: PrerenderManifest = {
14+
version: 3,
15+
routes: {},
16+
dynamicRoutes: {},
17+
notFoundRoutes: [],
18+
}
19+
20+
const prerenderManifest: PrerenderManifest = {
21+
...basePrerenderManifest,
22+
dynamicRoutes: {
23+
'/getStaticProps/[id]': {
24+
routeRegex: '^/getStaticProps/([^/]+?)(?:/)?$',
25+
dataRoute: '/_next/data/build-id/getStaticProps/[id].json',
26+
fallback: false,
27+
dataRouteRegex: '^/_next/data/build\\-id/getStaticProps/([^/]+?)\\.json$',
28+
},
29+
},
30+
}
31+
32+
const dynamicRoutes = [
33+
{
34+
page: '/getStaticProps/[id]',
35+
regex: '^/getStaticProps/([^/]+?)(?:/)?$',
36+
routeKeys: {
37+
nextParamid: 'nextParamid',
38+
},
39+
namedRegex: '^/getStaticProps/(?<nextParamid>[^/]+?)(?:/)?$',
40+
},
41+
]
42+
43+
const route = {
44+
dynamicRoutes,
45+
prerenderedDynamicRoutes: prerenderManifest.dynamicRoutes,
46+
basePath: '',
47+
i18n: null,
48+
buildId: 'test',
49+
middleware: [],
50+
is404Isr: false,
51+
}
52+
1153
const chance = new Chance()
1254

1355
describe('getCustomImageResponseHeaders', () => {
@@ -132,4 +174,52 @@ describe('redirectsForNext404Route', () => {
132174
{ force: false, from: '/fr/test', status: 404, to: '/server/pages/fr/404.html' },
133175
])
134176
})
177+
178+
it('returns static 404 redirects when LEGACY_FALLBACK_FALSE is not set', async () => {
179+
const expected = {
180+
dynamicRewrites: [
181+
{
182+
force: false,
183+
from: '/_next/data/test/getStaticProps/:id.json',
184+
status: 404,
185+
to: '/server/pages/404.html',
186+
},
187+
{
188+
force: false,
189+
from: '/getStaticProps/:id',
190+
status: 404,
191+
to: '/server/pages/404.html',
192+
},
193+
],
194+
dynamicRoutesThatMatchMiddleware: [],
195+
}
196+
197+
expect(generateDynamicRewrites(route)).toStrictEqual(expected)
198+
})
199+
200+
it('does not return static 404 redirects when LEGACY_FALLBACK_FALSE is set', async () => {
201+
process.env.LEGACY_FALLBACK_FALSE = 'true'
202+
203+
const expected = {
204+
dynamicRewrites: [
205+
{
206+
force: false,
207+
from: '/_next/data/test/getStaticProps/:id.json',
208+
status: 200,
209+
to: '/.netlify/builders/___netlify-odb-handler',
210+
},
211+
{
212+
force: false,
213+
from: '/getStaticProps/:id',
214+
status: 200,
215+
to: '/.netlify/builders/___netlify-odb-handler',
216+
},
217+
],
218+
dynamicRoutesThatMatchMiddleware: [],
219+
}
220+
221+
expect(generateDynamicRewrites(route)).toStrictEqual(expected)
222+
223+
delete process.env.LEGACY_FALLBACK_FALSE
224+
})
135225
})

0 commit comments

Comments
 (0)