@netlify/plugin-nextjs 4.33.0 → 4.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/helpers/edge.js
CHANGED
|
@@ -189,6 +189,7 @@ const writeEdgeFunctions = async ({ netlifyConfig, routesManifest, }) => {
|
|
|
189
189
|
var _a;
|
|
190
190
|
const manifest = {
|
|
191
191
|
functions: [],
|
|
192
|
+
layers: [],
|
|
192
193
|
version: 1,
|
|
193
194
|
};
|
|
194
195
|
const edgeFunctionRoot = (0, path_1.resolve)('.netlify', 'edge-functions');
|
|
@@ -291,7 +292,11 @@ const writeEdgeFunctions = async ({ netlifyConfig, routesManifest, }) => {
|
|
|
291
292
|
manifest.functions.push({
|
|
292
293
|
function: 'ipx',
|
|
293
294
|
name: 'next/image handler',
|
|
294
|
-
path: '/_next/image
|
|
295
|
+
path: nextConfig.images.path || '/_next/image',
|
|
296
|
+
});
|
|
297
|
+
manifest.layers.push({
|
|
298
|
+
name: 'https://ipx-edge-function-layer.netlify.app/mod.ts',
|
|
299
|
+
flag: 'ipx-edge-function-layer-url',
|
|
295
300
|
});
|
|
296
301
|
}
|
|
297
302
|
else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/plugin-nextjs",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.34.0",
|
|
4
4
|
"description": "Run Next.js seamlessly on Netlify",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@netlify/esbuild": "0.14.39",
|
|
15
15
|
"@netlify/functions": "^1.4.0",
|
|
16
|
-
"@netlify/ipx": "^1.
|
|
16
|
+
"@netlify/ipx": "^1.4.0",
|
|
17
17
|
"@vercel/node-bridge": "^2.1.0",
|
|
18
18
|
"chalk": "^4.1.2",
|
|
19
19
|
"chokidar": "^3.5.3",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@delucis/if-env": "^1.1.2",
|
|
40
|
-
"@netlify/build": "^29.
|
|
40
|
+
"@netlify/build": "^29.9.0",
|
|
41
41
|
"@types/fs-extra": "^9.0.13",
|
|
42
42
|
"@types/jest": "^27.4.1",
|
|
43
43
|
"@types/merge-stream": "^1.1.2",
|
|
@@ -1,73 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { Context } from 'https://edge.netlify.com'
|
|
3
|
-
// Available at build time
|
|
4
|
-
import imageconfig from './imageconfig.json' assert { type: 'json' }
|
|
5
|
-
|
|
6
|
-
const defaultFormat = 'webp'
|
|
7
|
-
|
|
8
|
-
interface ImageConfig extends Record<string, unknown> {
|
|
9
|
-
formats?: string[]
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Checks if a URL param is numeric
|
|
13
|
-
const isNumeric = (value: string | null) => Number(value).toString() === value
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Implement content negotiation for images
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
// deno-lint-ignore require-await
|
|
20
|
-
const handler = async (req: Request, context: Context) => {
|
|
21
|
-
const { searchParams } = new URL(req.url)
|
|
22
|
-
const accept = new Accepts(req.headers)
|
|
23
|
-
const { formats = [defaultFormat] } = imageconfig as ImageConfig
|
|
24
|
-
if (formats.length === 0) {
|
|
25
|
-
formats.push(defaultFormat)
|
|
26
|
-
}
|
|
27
|
-
let type = accept.types(formats) || defaultFormat
|
|
28
|
-
if (Array.isArray(type)) {
|
|
29
|
-
type = type[0]
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const source = searchParams.get('url')
|
|
33
|
-
const width = searchParams.get('w')
|
|
34
|
-
const quality = searchParams.get('q') ?? '75'
|
|
1
|
+
import { getHandler } from 'https://ipx-edge-function-layer.netlify.app/mod.ts'
|
|
35
2
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (!source) {
|
|
39
|
-
errors.push('Missing "url" parameter')
|
|
40
|
-
} else if (!source.startsWith('http') && !source.startsWith('/')) {
|
|
41
|
-
errors.push('The "url" parameter must be a valid URL or path')
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (!width) {
|
|
45
|
-
errors.push('Missing "w" parameter')
|
|
46
|
-
} else if (!isNumeric(width)) {
|
|
47
|
-
errors.push('Invalid "w" parameter')
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (!isNumeric(quality)) {
|
|
51
|
-
errors.push('Invalid "q" parameter')
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (!source || errors.length > 0) {
|
|
55
|
-
return new Response(`Invalid request: \n${errors.join('\n')}`, {
|
|
56
|
-
status: 400,
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const modifiers = [`w_${width}`, `q_${quality}`]
|
|
61
|
-
|
|
62
|
-
if (type) {
|
|
63
|
-
if (type.includes('/')) {
|
|
64
|
-
// If this is a mimetype, strip "image/"
|
|
65
|
-
type = type.split('/')[1]
|
|
66
|
-
}
|
|
67
|
-
modifiers.push(`f_${type}`)
|
|
68
|
-
}
|
|
69
|
-
const target = `/_ipx/${modifiers.join(',')}/${encodeURIComponent(source)}`
|
|
70
|
-
return context.rewrite(target)
|
|
71
|
-
}
|
|
3
|
+
import imageconfig from './imageconfig.json' assert { type: 'json' }
|
|
72
4
|
|
|
73
|
-
export default
|
|
5
|
+
export default getHandler({ formats: imageconfig?.formats })
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import type { EdgeFunction } from 'https://edge.netlify.com'
|
|
2
2
|
|
|
3
|
+
// These are copied from next/dist/build. This file gets copied as part of the next
|
|
4
|
+
// runtime build and can't reference the next package directly.
|
|
5
|
+
//
|
|
6
|
+
// Latest types at https://github.com/vercel/next.js/blob/4a2df3c3752aeddc50fd5ab053440eccf71ae50b/packages/next/src/build/index.ts#L140
|
|
3
7
|
export declare type SsgRoute = {
|
|
4
8
|
initialRevalidateSeconds: number | false
|
|
5
9
|
srcRoute: string | null
|
|
6
|
-
dataRoute: string
|
|
10
|
+
dataRoute: string | null
|
|
7
11
|
}
|
|
8
12
|
export declare type DynamicSsgRoute = {
|
|
9
13
|
routeRegex: string
|
|
10
14
|
fallback: string | null | false
|
|
11
|
-
dataRoute: string
|
|
15
|
+
dataRoute: string | null
|
|
12
16
|
dataRouteRegex: string
|
|
13
17
|
}
|
|
14
18
|
export declare type PrerenderManifest = {
|
|
@@ -35,7 +39,7 @@ const rscifyPath = (route: string) => {
|
|
|
35
39
|
export const getRscDataRouter = ({ routes: staticRoutes, dynamicRoutes }: PrerenderManifest): EdgeFunction => {
|
|
36
40
|
const staticRouteSet = new Set(
|
|
37
41
|
Object.entries(staticRoutes)
|
|
38
|
-
.filter(([, { dataRoute }]) => dataRoute
|
|
42
|
+
.filter(([, { dataRoute }]) => dataRoute?.endsWith('.rsc'))
|
|
39
43
|
.map(([route]) => route),
|
|
40
44
|
)
|
|
41
45
|
|
|
@@ -57,10 +57,15 @@ export const addMiddlewareHeaders = async (
|
|
|
57
57
|
return response
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
interface ResponseCookies {
|
|
61
|
+
readonly _headers: Headers
|
|
62
|
+
}
|
|
63
|
+
|
|
60
64
|
interface MiddlewareResponse extends Response {
|
|
61
65
|
originResponse: Response
|
|
62
66
|
dataTransforms: NextDataTransform[]
|
|
63
67
|
elementHandlers: Array<[selector: string, handlers: ElementHandlers]>
|
|
68
|
+
get cookies(): ResponseCookies
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
interface MiddlewareRequest {
|
|
@@ -184,6 +189,12 @@ export const buildResponse = async ({
|
|
|
184
189
|
if (request.method === 'HEAD' || request.method === 'OPTIONS') {
|
|
185
190
|
return response.originResponse
|
|
186
191
|
}
|
|
192
|
+
|
|
193
|
+
// NextResponse doesn't set cookies onto the originResponse, so we need to copy them over
|
|
194
|
+
if (response.cookies._headers.has('set-cookie')) {
|
|
195
|
+
response.originResponse.headers.set('set-cookie', response.cookies._headers.get('set-cookie')!)
|
|
196
|
+
}
|
|
197
|
+
|
|
187
198
|
// If it's JSON we don't need to use the rewriter, we can just parse it
|
|
188
199
|
if (response.originResponse.headers.get('content-type')?.includes('application/json')) {
|
|
189
200
|
const props = await response.originResponse.json()
|