@netlify/plugin-nextjs 4.9.3 → 4.11.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.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.updateConfig = exports.writeEdgeFunctions = void 0;
3
+ exports.updateConfig = exports.writeEdgeFunctions = exports.loadMiddlewareManifest = void 0;
4
4
  const fs_1 = require("fs");
5
5
  const path_1 = require("path");
6
6
  const fs_extra_1 = require("fs-extra");
@@ -11,6 +11,7 @@ const loadMiddlewareManifest = (netlifyConfig) => {
11
11
  }
12
12
  return (0, fs_extra_1.readJson)(middlewarePath);
13
13
  };
14
+ exports.loadMiddlewareManifest = loadMiddlewareManifest;
14
15
  /**
15
16
  * Convert the Next middleware name into a valid Edge Function name
16
17
  */
@@ -69,35 +70,30 @@ const writeEdgeFunction = async ({ edgeFunctionDefinition, edgeFunctionRoot, net
69
70
  * Writes Edge Functions for the Next middleware
70
71
  */
71
72
  const writeEdgeFunctions = async (netlifyConfig) => {
72
- const middlewareManifest = await loadMiddlewareManifest(netlifyConfig);
73
- if (!middlewareManifest) {
74
- console.error("Couldn't find the middleware manifest");
75
- return;
76
- }
77
73
  const manifest = {
78
74
  functions: [],
79
75
  version: 1,
80
76
  };
81
77
  const edgeFunctionRoot = (0, path_1.resolve)('.netlify', 'edge-functions');
82
78
  await (0, fs_extra_1.emptyDir)(edgeFunctionRoot);
83
- await copyEdgeSourceFile({ edgeFunctionDir: edgeFunctionRoot, file: 'ipx.ts' });
84
- manifest.functions.push({
85
- function: 'ipx',
86
- path: '/_next/image*',
87
- });
88
- for (const middleware of middlewareManifest.sortedMiddleware) {
89
- const edgeFunctionDefinition = middlewareManifest.middleware[middleware];
90
- const functionDefinition = await writeEdgeFunction({
91
- edgeFunctionDefinition,
92
- edgeFunctionRoot,
93
- netlifyConfig,
79
+ if (!process.env.NEXT_DISABLE_EDGE_IMAGES) {
80
+ if (!process.env.NEXT_USE_NETLIFY_EDGE) {
81
+ console.log('Using Netlify Edge Functions for image format detection. Set env var "NEXT_DISABLE_EDGE_IMAGES=true" to disable.');
82
+ }
83
+ await copyEdgeSourceFile({ edgeFunctionDir: edgeFunctionRoot, file: 'ipx.ts' });
84
+ manifest.functions.push({
85
+ function: 'ipx',
86
+ path: '/_next/image*',
94
87
  });
95
- manifest.functions.push(functionDefinition);
96
88
  }
97
- // Older versions of the manifest format don't have the functions field
98
- // No, the version field was not incremented
99
- if (typeof middlewareManifest.functions === 'object') {
100
- for (const edgeFunctionDefinition of Object.values(middlewareManifest.functions)) {
89
+ if (process.env.NEXT_USE_NETLIFY_EDGE) {
90
+ const middlewareManifest = await (0, exports.loadMiddlewareManifest)(netlifyConfig);
91
+ if (!middlewareManifest) {
92
+ console.error("Couldn't find the middleware manifest");
93
+ return;
94
+ }
95
+ for (const middleware of middlewareManifest.sortedMiddleware) {
96
+ const edgeFunctionDefinition = middlewareManifest.middleware[middleware];
101
97
  const functionDefinition = await writeEdgeFunction({
102
98
  edgeFunctionDefinition,
103
99
  edgeFunctionRoot,
@@ -105,6 +101,18 @@ const writeEdgeFunctions = async (netlifyConfig) => {
105
101
  });
106
102
  manifest.functions.push(functionDefinition);
107
103
  }
104
+ // Older versions of the manifest format don't have the functions field
105
+ // No, the version field was not incremented
106
+ if (typeof middlewareManifest.functions === 'object') {
107
+ for (const edgeFunctionDefinition of Object.values(middlewareManifest.functions)) {
108
+ const functionDefinition = await writeEdgeFunction({
109
+ edgeFunctionDefinition,
110
+ edgeFunctionRoot,
111
+ netlifyConfig,
112
+ });
113
+ manifest.functions.push(functionDefinition);
114
+ }
115
+ }
108
116
  }
109
117
  await (0, fs_extra_1.writeJson)((0, path_1.join)(edgeFunctionRoot, 'manifest.json'), manifest);
110
118
  };
@@ -52,15 +52,14 @@ const setupImageFunction = async ({ constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIO
52
52
  });
53
53
  await (0, fs_extra_1.copyFile)((0, pathe_1.join)(__dirname, '..', '..', 'lib', 'templates', 'ipx.js'), (0, pathe_1.join)(functionDirectory, functionName));
54
54
  const imagePath = imageconfig.path || '/_next/image';
55
- // If we have edge, we use content negotiation instead of the redirect
56
- if (!process.env.NEXT_USE_NETLIFY_EDGE) {
57
- netlifyConfig.redirects.push({
58
- from: `${imagePath}*`,
59
- query: { url: ':url', w: ':width', q: ':quality' },
60
- to: `${basePath}/${constants_1.IMAGE_FUNCTION_NAME}/w_:width,q_:quality/:url`,
61
- status: 301,
62
- });
63
- }
55
+ // If we have edge functions then the request will have already been rewritten
56
+ // so this won't match. This is matched if edge is disabled or unavailable.
57
+ netlifyConfig.redirects.push({
58
+ from: `${imagePath}*`,
59
+ query: { url: ':url', w: ':width', q: ':quality' },
60
+ to: `${basePath}/${constants_1.IMAGE_FUNCTION_NAME}/w_:width,q_:quality/:url`,
61
+ status: 301,
62
+ });
64
63
  netlifyConfig.redirects.push({
65
64
  from: `${basePath}/${constants_1.IMAGE_FUNCTION_NAME}/*`,
66
65
  to: `/.netlify/builders/${constants_1.IMAGE_FUNCTION_NAME}`,
package/lib/index.js CHANGED
@@ -34,6 +34,7 @@ const plugin = {
34
34
  netlifyConfig.build.environment.NEXT_PRIVATE_TARGET = 'server';
35
35
  },
36
36
  async onBuild({ constants, netlifyConfig, utils: { build: { failBuild }, }, }) {
37
+ var _a;
37
38
  if ((0, utils_1.shouldSkip)()) {
38
39
  return;
39
40
  }
@@ -85,14 +86,23 @@ const plugin = {
85
86
  nextConfig: { basePath, i18n, trailingSlash, appDir },
86
87
  buildId,
87
88
  });
89
+ // We call this even if we don't have edge functions enabled because we still use it for images
90
+ await (0, edge_1.writeEdgeFunctions)(netlifyConfig);
88
91
  if (process.env.NEXT_USE_NETLIFY_EDGE) {
89
92
  console.log((0, outdent_1.outdent) `
90
93
  ✨ Deploying to ${(0, chalk_1.greenBright) `Netlify Edge Functions`} ✨
91
94
  This feature is in beta. Please share your feedback here: https://ntl.fyi/next-netlify-edge
92
95
  `);
93
- await (0, edge_1.writeEdgeFunctions)(netlifyConfig);
94
96
  await (0, edge_1.updateConfig)(publish);
95
97
  }
98
+ const middlewareManifest = await (0, edge_1.loadMiddlewareManifest)(netlifyConfig);
99
+ if (!process.env.NEXT_USE_NETLIFY_EDGE && ((_a = middlewareManifest === null || middlewareManifest === void 0 ? void 0 : middlewareManifest.sortedMiddleware) === null || _a === void 0 ? void 0 : _a.length)) {
100
+ console.log((0, chalk_1.yellowBright)((0, outdent_1.outdent) `
101
+ You are using Next.js Middleware without Netlify Edge Functions.
102
+ This will soon be deprecated because it negatively affects performance and will disable ISR and static rendering.
103
+ To get the best performance and use Netlify Edge Functions, set the env var ${(0, chalk_1.bold) `NEXT_USE_NETLIFY_EDGE=true`}.
104
+ `));
105
+ }
96
106
  },
97
107
  async onPostBuild({ netlifyConfig: { build: { publish }, redirects, headers, }, utils: { status, cache, functions, build: { failBuild }, }, constants: { FUNCTIONS_DIST }, }) {
98
108
  await (0, cache_1.saveCache)({ cache, publish });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/plugin-nextjs",
3
- "version": "4.9.3",
3
+ "version": "4.11.0",
4
4
  "description": "Run Next.js seamlessly on Netlify",
5
5
  "main": "lib/index.js",
6
6
  "files": [
@@ -28,11 +28,11 @@
28
28
  },
29
29
  "devDependencies": {
30
30
  "@delucis/if-env": "^1.1.2",
31
- "@netlify/build": "^27.2.0",
31
+ "@netlify/build": "^27.3.1",
32
32
  "@types/fs-extra": "^9.0.13",
33
33
  "@types/jest": "^27.4.1",
34
34
  "@types/node": "^17.0.25",
35
- "next": "^12.1.7-canary.33",
35
+ "next": "^12.2.0",
36
36
  "npm-run-all": "^4.1.5",
37
37
  "typescript": "^4.6.3"
38
38
  },
@@ -1,32 +1,52 @@
1
- import { Accepts } from 'https://deno.land/x/accepts/mod.ts'
2
- import type { Context } from 'netlify:edge'
1
+ import { Accepts } from "https://deno.land/x/accepts@2.1.1/mod.ts";
2
+ import type { Context } from "netlify:edge";
3
+ import imageconfig from "../functions-internal/_ipx/imageconfig.json" assert {
4
+ type: "json",
5
+ };
6
+
7
+ const defaultFormat = "webp"
3
8
 
4
9
  /**
5
10
  * Implement content negotiation for images
6
11
  */
7
12
 
13
+ // deno-lint-ignore require-await
8
14
  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'])
15
+ const { searchParams } = new URL(req.url);
16
+ const accept = new Accepts(req.headers);
17
+ const { formats = [defaultFormat] } = imageconfig;
18
+ if (formats.length === 0) {
19
+ formats.push(defaultFormat);
20
+ }
21
+ let type = accept.types(formats) || defaultFormat;
22
+ if(Array.isArray(type)) {
23
+ type = type[0];
24
+ }
12
25
 
13
- const source = searchParams.get('url')
14
- const width = searchParams.get('w')
15
- const quality = searchParams.get('q') ?? 75
26
+
27
+ const source = searchParams.get("url");
28
+ const width = searchParams.get("w");
29
+ const quality = searchParams.get("q") ?? 75;
16
30
 
17
31
  if (!source || !width) {
18
- return new Response('Invalid request', {
32
+ return new Response("Invalid request", {
19
33
  status: 400,
20
- })
34
+ });
21
35
  }
22
36
 
23
- const modifiers = [`w_${width}`, `q_${quality}`]
37
+ const modifiers = [`w_${width}`, `q_${quality}`];
24
38
 
25
39
  if (type) {
26
- modifiers.push(`f_${type}`)
40
+ if(type.includes('/')) {
41
+ // If this is a mimetype, strip "image/"
42
+ type = type.split('/')[1];
43
+ }
44
+ modifiers.push(`f_${type}`);
27
45
  }
46
+ const target = `/_ipx/${modifiers.join(",")}/${encodeURIComponent(source)}`;
47
+ return context.rewrite(
48
+ target,
49
+ );
50
+ };
28
51
 
29
- return context.rewrite(`/_ipx/${modifiers.join(',')}/${encodeURIComponent(source)}`)
30
- }
31
-
32
- export default handler
52
+ export default handler;