Skip to content

Commit bf97d73

Browse files
committed
feat: add additional paths for routes
1 parent fef98a1 commit bf97d73

File tree

3 files changed

+73
-30
lines changed

3 files changed

+73
-30
lines changed

packages/runtime/src/templates/getHandler.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ type Mutable<T> = {
2929
}
3030

3131
// We return a function and then call `toString()` on it to serialise it as the launcher function
32-
// eslint-disable-next-line max-params
32+
// eslint-disable-next-line max-params, max-lines-per-function
3333
const makeHandler = (conf: NextConfig, app, pageRoot, staticManifest: Array<[string, string]> = [], mode = 'ssr') => {
3434
// Change working directory into the site root, unless using Nx, which moves the
3535
// dist directory and handles this itself
@@ -66,21 +66,29 @@ const makeHandler = (conf: NextConfig, app, pageRoot, staticManifest: Array<[str
6666
// the first request because we need the host and port.
6767
let bridge: NodeBridge
6868
const getBridge = (event: HandlerEvent, context: HandlerContext): NodeBridge => {
69+
const {
70+
clientContext: { custom: customContext },
71+
} = context
72+
6973
if (bridge) {
7074
return bridge
7175
}
7276
const url = new URL(event.rawUrl)
7377
const port = Number.parseInt(url.port) || 80
7478
base = url.origin
7579

76-
const nextServer = new NetlifyNextServer({
77-
conf,
78-
dir,
79-
customServer: false,
80-
hostname: url.hostname,
81-
port,
82-
netlifyRevalidateToken: context.clientContext?.custom?.odb_refresh_hooks,
83-
})
80+
const nextServer = new NetlifyNextServer(
81+
{
82+
conf,
83+
dir,
84+
customServer: false,
85+
hostname: url.hostname,
86+
port,
87+
},
88+
{
89+
revalidateToken: customContext.odb_refresh_hooks,
90+
},
91+
)
8492
const requestHandler = nextServer.getRequestHandler()
8593
const server = new Server(async (req, res) => {
8694
try {

packages/runtime/src/templates/handlerUtils.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,9 @@ export const normalizePath = (event: HandlerEvent) => {
224224
return new URL(event.rawUrl).pathname
225225
}
226226

227+
/**
228+
* Simple Netlify API client
229+
*/
227230
export const netlifyApiFetch = <T>({
228231
endpoint,
229232
payload,
@@ -266,3 +269,44 @@ export const netlifyApiFetch = <T>({
266269
req.write(body)
267270
req.end()
268271
})
272+
273+
/**
274+
* Get all paths related to a route including data, i18n and rsc routes
275+
*/
276+
export const getPathsForRoute = (
277+
route: string,
278+
buildId: string,
279+
i18n?: {
280+
defaultLocale: string
281+
locales: string[]
282+
},
283+
): string[] => {
284+
const routes = []
285+
// static files
286+
routes.push(...localizeRoute(route, i18n))
287+
// data routes
288+
routes.push(
289+
...localizeRoute(route.endsWith('/') ? route.slice(0, -1) || '/index' : route, i18n, true).map(
290+
(localizeRoute) => `/_next/data/${buildId}${localizeRoute}.json`,
291+
),
292+
)
293+
// rsc routes
294+
routes.push(route.endsWith('/') ? `${route.slice(0, -1) || '/index'}.rsc/` : `${route}.rsc`)
295+
return routes
296+
}
297+
298+
/**
299+
* Localize a route based on i18n config
300+
* (don't localize if i18n is not configured or if the route is the default locale and not a data route)
301+
*/
302+
export const localizeRoute = (
303+
route: string,
304+
i18n?: {
305+
defaultLocale: string
306+
locales: string[]
307+
},
308+
data = false,
309+
): string[] =>
310+
i18n
311+
? i18n.locales.map((locale) => (locale === i18n.defaultLocale && data === false ? route : `/${locale}${route}`))
312+
: [route]

packages/runtime/src/templates/server.ts

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,43 @@
11
import { NodeRequestHandler, Options } from 'next/dist/server/next-server'
22

3-
// import { netlifyRoutesForNextRoute } from '../helpers/utils'
4-
5-
import { netlifyApiFetch, getNextServer, NextServerType } from './handlerUtils'
3+
import { netlifyApiFetch, getNextServer, NextServerType, getPathsForRoute } from './handlerUtils'
64

75
const NextServer: NextServerType = getNextServer()
86

9-
interface NetlifyNextServerOptions extends Options {
10-
netlifyRevalidateToken?: string
7+
interface NetlifyOptions {
8+
revalidateToken?: string
119
}
1210

1311
class NetlifyNextServer extends NextServer {
14-
private netlifyRevalidateToken?: string
12+
private netlifyOptions: NetlifyOptions
1513

16-
public constructor(options: NetlifyNextServerOptions) {
14+
public constructor(options: Options, netlifyOptions: NetlifyOptions) {
1715
super(options)
18-
this.netlifyRevalidateToken = options.netlifyRevalidateToken
16+
this.netlifyOptions = netlifyOptions
1917
}
2018

2119
public getRequestHandler(): NodeRequestHandler {
2220
const handler = super.getRequestHandler()
2321
return async (req, res, parsedUrl) => {
24-
// on-demand revalidation request
2522
if (req.headers['x-prerender-revalidate']) {
23+
// handle on-demand revalidation by purging the ODB cache
2624
await this.netlifyRevalidate(req.url)
2725
}
26+
// handle the original res.revalidate() request
2827
return handler(req, res, parsedUrl)
2928
}
3029
}
3130

32-
private async netlifyRevalidate(url: string) {
31+
private async netlifyRevalidate(route: string) {
3332
try {
34-
// call netlify API to revalidate the path, including its data routes
33+
// call netlify API to revalidate the path
3534
const result = await netlifyApiFetch<{ ok: boolean; code: number; message: string }>({
3635
endpoint: `sites/${process.env.SITE_ID}/refresh_on_demand_builders`,
3736
payload: {
38-
paths: [
39-
url,
40-
// ...netlifyRoutesForNextRoute({
41-
// route: url,
42-
// buildId: this.buildId,
43-
// i18n: this.nextConfig.i18n,
44-
// }),
45-
// url.endsWith('/') ? `${url.slice(0, -1)}.rsc/` : `${url}.rsc`,
46-
],
37+
paths: getPathsForRoute(route, this.buildId, this.nextConfig?.i18n),
4738
domain: this.hostname,
4839
},
49-
token: this.netlifyRevalidateToken,
40+
token: this.netlifyOptions.revalidateToken,
5041
method: 'POST',
5142
})
5243
if (result.ok !== true) {

0 commit comments

Comments
 (0)