@netlify/plugin-nextjs 4.4.1 → 4.4.4

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/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@netlify/plugin-nextjs",
3
- "version": "4.4.1",
3
+ "version": "4.4.4",
4
4
  "description": "Run Next.js seamlessly on Netlify",
5
5
  "main": "lib/index.js",
6
6
  "files": [
7
7
  "lib/**/*",
8
+ "src/templates/edge/*",
8
9
  "manifest.yml"
9
10
  ],
10
11
  "dependencies": {
@@ -27,6 +28,7 @@
27
28
  "tiny-glob": "^0.2.9"
28
29
  },
29
30
  "devDependencies": {
31
+ "@delucis/if-env": "^1.1.2",
30
32
  "@netlify/build": "^27.0.1",
31
33
  "@types/fs-extra": "^9.0.13",
32
34
  "@types/jest": "^27.4.1",
@@ -0,0 +1,7 @@
1
+ /**
2
+ * This placeholder is replaced with the compiled Next.js bundle at build time
3
+ * @args {Object}
4
+ * @args.request {import("./runtime.ts").RequestData}
5
+ * @returns {Promise<import("./utils.ts").FetchEventResult>}
6
+ */
7
+ export default async (props) => {}
@@ -0,0 +1,32 @@
1
+ import { Accepts } from 'https://deno.land/x/accepts/mod.ts'
2
+ import type { Context } from 'netlify:edge'
3
+
4
+ /**
5
+ * Implement content negotiation for images
6
+ */
7
+
8
+ const handler = async (req: Request, context: Context) => {
9
+ const { searchParams } = new URL(req.url)
10
+ const accept = new Accepts(req.headers)
11
+ const type = accept.types(['avif', 'webp'])
12
+
13
+ const source = searchParams.get('url')
14
+ const width = searchParams.get('w')
15
+ const quality = searchParams.get('q') ?? 75
16
+
17
+ if (!source || !width) {
18
+ return new Response('Invalid request', {
19
+ status: 400,
20
+ })
21
+ }
22
+
23
+ const modifiers = [`w_${width}`, `q_${quality}`]
24
+
25
+ if (type) {
26
+ modifiers.push(`f_${type}`)
27
+ }
28
+
29
+ return context.rewrite(`/_ipx/${modifiers.join(',')}/${encodeURIComponent(source)}`)
30
+ }
31
+
32
+ export default handler
@@ -0,0 +1,63 @@
1
+ import type { Context } from 'netlify:edge'
2
+
3
+ import edgeFunction from './bundle.js'
4
+ import { buildResponse } from './utils.ts'
5
+
6
+ export interface FetchEventResult {
7
+ response: Response
8
+ waitUntil: Promise<any>
9
+ }
10
+
11
+ export interface RequestData {
12
+ geo?: {
13
+ city?: string
14
+ country?: string
15
+ region?: string
16
+ latitude?: string
17
+ longitude?: string
18
+ }
19
+ headers: Record<string, string>
20
+ ip?: string
21
+ method: string
22
+ nextConfig?: {
23
+ basePath?: string
24
+ i18n?: Record<string, unknown>
25
+ trailingSlash?: boolean
26
+ }
27
+ page?: {
28
+ name?: string
29
+ params?: { [key: string]: string }
30
+ }
31
+ url: string
32
+ body?: ReadableStream<Uint8Array>
33
+ }
34
+
35
+ const handler = async (req: Request, context: Context) => {
36
+ const url = new URL(req.url)
37
+ if (url.pathname.startsWith('/_next/')) {
38
+ return
39
+ }
40
+
41
+ const request: RequestData = {
42
+ headers: Object.fromEntries(req.headers.entries()),
43
+ geo: {
44
+ country: context.geo.country?.code,
45
+ region: context.geo.subdivision?.code,
46
+ city: context.geo.city,
47
+ },
48
+ url: url.toString(),
49
+ method: req.method,
50
+ ip: req.headers.get('x-nf-client-address') ?? undefined,
51
+ body: req.body ?? undefined,
52
+ }
53
+
54
+ try {
55
+ const result = await edgeFunction({ request })
56
+ return buildResponse({ result, request: req, context })
57
+ } catch (error) {
58
+ console.error(error)
59
+ return new Response(error.message, { status: 500 })
60
+ }
61
+ }
62
+
63
+ export default handler
@@ -0,0 +1,64 @@
1
+ import type { Context } from 'netlify:edge'
2
+
3
+ export interface FetchEventResult {
4
+ response: Response
5
+ waitUntil: Promise<any>
6
+ }
7
+
8
+ /**
9
+ * This is how Next handles rewritten URLs.
10
+ */
11
+ export function relativizeURL(url: string | string, base: string | URL) {
12
+ const baseURL = typeof base === 'string' ? new URL(base) : base
13
+ const relative = new URL(url, base)
14
+ const origin = `${baseURL.protocol}//${baseURL.host}`
15
+ return `${relative.protocol}//${relative.host}` === origin
16
+ ? relative.toString().replace(origin, '')
17
+ : relative.toString()
18
+ }
19
+
20
+
21
+ export const addMiddlewareHeaders = async (
22
+ originResponse: Promise<Response> | Response,
23
+ middlewareResponse: Response,
24
+ ) => {
25
+ // If there are extra headers, we need to add them to the response.
26
+ if ([...middlewareResponse.headers.keys()].length === 0) {
27
+ return originResponse
28
+ }
29
+ // We need to await the response to get the origin headers, then we can add the ones from middleware.
30
+ const res = await originResponse
31
+ const response = new Response(res.body, res)
32
+ middlewareResponse.headers.forEach((value, key) => {
33
+ response.headers.set(key, value)
34
+ })
35
+ return response
36
+ }
37
+ export const buildResponse = async ({
38
+ result,
39
+ request,
40
+ context,
41
+ }: {
42
+ result: FetchEventResult
43
+ request: Request
44
+ context: Context
45
+ }) => {
46
+ const res = new Response(result.response.body, result.response)
47
+ request.headers.set('x-nf-next-middleware', 'skip')
48
+ const rewrite = res.headers.get('x-middleware-rewrite')
49
+ if (rewrite) {
50
+ const rewriteUrl = new URL(rewrite, request.url)
51
+ const baseUrl = new URL(request.url)
52
+ if(rewriteUrl.hostname !== baseUrl.hostname) {
53
+ // Netlify Edge Functions don't support proxying to external domains, but Next middleware does
54
+ const proxied = fetch(new Request(rewriteUrl.toString(), request))
55
+ return addMiddlewareHeaders(proxied, res)
56
+ }
57
+ res.headers.set('x-middleware-rewrite', relativizeURL(rewrite, request.url))
58
+ return addMiddlewareHeaders(context.rewrite(rewrite), res)
59
+ }
60
+ if (res.headers.get('x-middleware-next') === '1') {
61
+ return addMiddlewareHeaders(context.next(), res)
62
+ }
63
+ return res
64
+ }