1
- // @ts -check
1
+ /* eslint-disable max-lines */
2
+
3
+ const { yellowBright } = require ( 'chalk' )
2
4
const { readJSON, existsSync } = require ( 'fs-extra' )
5
+ const { outdent } = require ( 'outdent' )
3
6
const { join, dirname, relative } = require ( 'pathe' )
4
7
const slash = require ( 'slash' )
5
8
@@ -52,9 +55,9 @@ const getNetlifyRoutes = (nextRoute) => {
52
55
}
53
56
54
57
exports . generateRedirects = async ( { netlifyConfig, basePath, i18n } ) => {
55
- const { dynamicRoutes } = await readJSON ( join ( netlifyConfig . build . publish , 'prerender-manifest.json' ) )
56
-
57
- const redirects = [ ]
58
+ const { dynamicRoutes, routes : staticRoutes } = await readJSON (
59
+ join ( netlifyConfig . build . publish , 'prerender-manifest.json' ) ,
60
+ )
58
61
59
62
netlifyConfig . redirects . push (
60
63
...HIDDEN_PATHS . map ( ( path ) => ( {
@@ -65,15 +68,35 @@ exports.generateRedirects = async ({ netlifyConfig, basePath, i18n }) => {
65
68
} ) ) ,
66
69
)
67
70
71
+ const dataRedirects = [ ]
72
+ const pageRedirects = [ ]
73
+ const isrRedirects = [ ]
74
+ let hasIsr = false
75
+
68
76
const dynamicRouteEntries = Object . entries ( dynamicRoutes )
69
- dynamicRouteEntries . sort ( ( a , b ) => a [ 0 ] . localeCompare ( b [ 0 ] ) )
77
+
78
+ const staticRouteEntries = Object . entries ( staticRoutes )
79
+
80
+ staticRouteEntries . forEach ( ( [ route , { dataRoute, initialRevalidateSeconds } ] ) => {
81
+ // Only look for revalidate as we need to rewrite these to SSR rather than ODB
82
+ if ( initialRevalidateSeconds === false ) {
83
+ // These can be ignored, as they're static files handled by the CDN
84
+ return
85
+ }
86
+ if ( i18n . defaultLocale && route . startsWith ( `/${ i18n . defaultLocale } /` ) ) {
87
+ route = route . slice ( i18n . defaultLocale . length + 1 )
88
+ }
89
+ hasIsr = true
90
+ isrRedirects . push ( ...getNetlifyRoutes ( dataRoute ) , ...getNetlifyRoutes ( route ) )
91
+ } )
70
92
71
93
dynamicRouteEntries . forEach ( ( [ route , { dataRoute, fallback } ] ) => {
72
94
// Add redirects if fallback is "null" (aka blocking) or true/a string
73
95
if ( fallback === false ) {
74
96
return
75
97
}
76
- redirects . push ( ...getNetlifyRoutes ( route ) , ...getNetlifyRoutes ( dataRoute ) )
98
+ pageRedirects . push ( ...getNetlifyRoutes ( route ) )
99
+ dataRedirects . push ( ...getNetlifyRoutes ( dataRoute ) )
77
100
} )
78
101
79
102
if ( i18n ) {
@@ -82,21 +105,57 @@ exports.generateRedirects = async ({ netlifyConfig, basePath, i18n }) => {
82
105
83
106
// This is only used in prod, so dev uses `next dev` directly
84
107
netlifyConfig . redirects . push (
108
+ // Static files are in `static`
85
109
{ from : `${ basePath } /_next/static/*` , to : `/static/:splat` , status : 200 } ,
110
+ // API routes always need to be served from the regular function
111
+ {
112
+ from : `${ basePath } /api` ,
113
+ to : HANDLER_FUNCTION_PATH ,
114
+ status : 200 ,
115
+ } ,
116
+ {
117
+ from : `${ basePath } /api/*` ,
118
+ to : HANDLER_FUNCTION_PATH ,
119
+ status : 200 ,
120
+ } ,
121
+ // Preview mode gets forced to the function, to bypess pre-rendered pages
86
122
{
87
123
from : `${ basePath } /*` ,
88
124
to : HANDLER_FUNCTION_PATH ,
89
125
status : 200 ,
90
126
conditions : { Cookie : [ '__prerender_bypass' , '__next_preview_data' ] } ,
91
127
force : true ,
92
128
} ,
93
- ...redirects . map ( ( redirect ) => ( {
129
+ // ISR redirects are handled by the regular function. Forced to avoid pre-rendered pages
130
+ ...isrRedirects . map ( ( redirect ) => ( {
131
+ from : `${ basePath } ${ redirect } ` ,
132
+ to : HANDLER_FUNCTION_PATH ,
133
+ status : 200 ,
134
+ force : true ,
135
+ } ) ) ,
136
+ // These are pages with fallback set, which need an ODB
137
+ // Data redirects go first, to avoid conflict with splat redirects
138
+ ...dataRedirects . map ( ( redirect ) => ( {
94
139
from : `${ basePath } ${ redirect } ` ,
95
140
to : ODB_FUNCTION_PATH ,
96
141
status : 200 ,
97
142
} ) ) ,
143
+ // ...then all the other fallback pages
144
+ ...pageRedirects . map ( ( redirect ) => ( {
145
+ from : `${ basePath } ${ redirect } ` ,
146
+ to : ODB_FUNCTION_PATH ,
147
+ status : 200 ,
148
+ } ) ) ,
149
+ // Everything else is handled by the regular function
98
150
{ from : `${ basePath } /*` , to : HANDLER_FUNCTION_PATH , status : 200 } ,
99
151
)
152
+ if ( hasIsr ) {
153
+ console . log (
154
+ yellowBright ( outdent `
155
+ You have some pages that use ISR (pages that use getStaticProps with revalidate set), which is not currently fully-supported by this plugin. Be aware that results may be unreliable.
156
+ ` ) ,
157
+ )
158
+ }
100
159
}
101
160
102
161
exports . getNextConfig = async function getNextConfig ( { publish, failBuild = defaultFailBuild } ) {
@@ -159,3 +218,4 @@ exports.configureHandlerFunctions = ({ netlifyConfig, publish, ignore = [] }) =>
159
218
} )
160
219
} )
161
220
}
221
+ /* eslint-enable max-lines */
0 commit comments