@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.
- package/lib/helpers/edge.js +30 -22
- package/lib/helpers/functions.js +8 -9
- package/lib/index.js +11 -1
- package/package.json +3 -3
- package/src/templates/edge/ipx.ts +36 -16
package/lib/helpers/edge.js
CHANGED
|
@@ -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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
};
|
package/lib/helpers/functions.js
CHANGED
|
@@ -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
|
|
56
|
-
if
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
2
|
-
import type { Context } from
|
|
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
|
|
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
|
-
|
|
14
|
-
const
|
|
15
|
-
const
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export default handler
|
|
52
|
+
export default handler;
|