@netlify/plugin-nextjs 4.3.2 → 4.4.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 +100 -0
- package/lib/helpers/files.js +55 -27
- package/lib/helpers/functions.js +9 -5
- package/lib/helpers/verification.js +5 -1
- package/lib/index.js +11 -3
- package/lib/templates/ipx.js +0 -1
- package/package.json +25 -83
- package/README.md +0 -113
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updateConfig = exports.writeMiddleware = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const fs_extra_1 = require("fs-extra");
|
|
7
|
+
const loadMiddlewareManifest = (netlifyConfig) => {
|
|
8
|
+
const middlewarePath = (0, path_1.resolve)(netlifyConfig.build.publish, 'server', 'middleware-manifest.json');
|
|
9
|
+
if (!(0, fs_1.existsSync)(middlewarePath)) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return (0, fs_extra_1.readJson)(middlewarePath);
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Convert the Next middleware name into a valid Edge Function name
|
|
16
|
+
*/
|
|
17
|
+
const sanitizeName = (name) => `next${name === '/' ? '_index' : name.replace(/\W/g, '_')}`;
|
|
18
|
+
/**
|
|
19
|
+
* Initialization added to the top of the edge function bundle
|
|
20
|
+
*/
|
|
21
|
+
const bootstrap = /* js */ `
|
|
22
|
+
globalThis._ENTRIES ||= {}
|
|
23
|
+
delete globalThis.window
|
|
24
|
+
|
|
25
|
+
`;
|
|
26
|
+
// TODO: set the proper env
|
|
27
|
+
const getEnv = () => /* js */ `
|
|
28
|
+
globalThis.process = { env: {} }
|
|
29
|
+
`;
|
|
30
|
+
/**
|
|
31
|
+
* Concatenates the Next edge function code with the required chunks and adds an export
|
|
32
|
+
*/
|
|
33
|
+
const getMiddlewareBundle = async ({ middlewareDefinition, netlifyConfig, }) => {
|
|
34
|
+
const { publish } = netlifyConfig.build;
|
|
35
|
+
const chunks = [bootstrap, getEnv()];
|
|
36
|
+
for (const file of middlewareDefinition.files) {
|
|
37
|
+
const filePath = (0, path_1.join)(publish, file);
|
|
38
|
+
const data = await fs_1.promises.readFile(filePath, 'utf8');
|
|
39
|
+
chunks.push('{', data, '}');
|
|
40
|
+
}
|
|
41
|
+
const middleware = await fs_1.promises.readFile((0, path_1.join)(publish, `server`, `${middlewareDefinition.name}.js`), 'utf8');
|
|
42
|
+
chunks.push(middleware);
|
|
43
|
+
const exports = /* js */ `export default _ENTRIES["middleware_${middlewareDefinition.name}"].default;`;
|
|
44
|
+
chunks.push(exports);
|
|
45
|
+
return chunks.join('\n');
|
|
46
|
+
};
|
|
47
|
+
const copyEdgeSourceFile = ({ file, target, edgeFunctionDir, }) => fs_1.promises.copyFile((0, path_1.join)(__dirname, '..', 'templates', 'edge', file), (0, path_1.join)(edgeFunctionDir, target !== null && target !== void 0 ? target : file));
|
|
48
|
+
// Edge functions don't support lookahead expressions
|
|
49
|
+
const stripLookahead = (regex) => regex.replace('^/(?!_next)', '^/');
|
|
50
|
+
/**
|
|
51
|
+
* Writes Edge Functions for the Next middleware
|
|
52
|
+
*/
|
|
53
|
+
const writeMiddleware = async (netlifyConfig) => {
|
|
54
|
+
const middlewareManifest = await loadMiddlewareManifest(netlifyConfig);
|
|
55
|
+
if (!middlewareManifest) {
|
|
56
|
+
console.error("Couldn't find the middleware manifest");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const manifest = {
|
|
60
|
+
functions: [],
|
|
61
|
+
version: 1,
|
|
62
|
+
};
|
|
63
|
+
const edgeFunctionRoot = (0, path_1.resolve)('.netlify', 'edge-functions');
|
|
64
|
+
await (0, fs_extra_1.emptyDir)(edgeFunctionRoot);
|
|
65
|
+
await copyEdgeSourceFile({ edgeFunctionDir: edgeFunctionRoot, file: 'ipx.ts' });
|
|
66
|
+
manifest.functions.push({
|
|
67
|
+
function: 'ipx',
|
|
68
|
+
path: '/_next/image*',
|
|
69
|
+
});
|
|
70
|
+
for (const middleware of middlewareManifest.sortedMiddleware) {
|
|
71
|
+
const name = sanitizeName(middleware);
|
|
72
|
+
const edgeFunctionDir = (0, path_1.join)(edgeFunctionRoot, name);
|
|
73
|
+
const middlewareDefinition = middlewareManifest.middleware[middleware];
|
|
74
|
+
const bundle = await getMiddlewareBundle({
|
|
75
|
+
middlewareDefinition,
|
|
76
|
+
netlifyConfig,
|
|
77
|
+
});
|
|
78
|
+
await (0, fs_extra_1.ensureDir)(edgeFunctionDir);
|
|
79
|
+
await fs_1.promises.writeFile((0, path_1.join)(edgeFunctionDir, 'bundle.js'), bundle);
|
|
80
|
+
await copyEdgeSourceFile({
|
|
81
|
+
edgeFunctionDir,
|
|
82
|
+
file: 'runtime.ts',
|
|
83
|
+
target: 'index.ts',
|
|
84
|
+
});
|
|
85
|
+
await copyEdgeSourceFile({ edgeFunctionDir, file: 'utils.ts' });
|
|
86
|
+
manifest.functions.push({
|
|
87
|
+
function: name,
|
|
88
|
+
pattern: stripLookahead(middlewareDefinition.regexp),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
await (0, fs_extra_1.writeJson)((0, path_1.join)(edgeFunctionRoot, 'manifest.json'), manifest);
|
|
92
|
+
};
|
|
93
|
+
exports.writeMiddleware = writeMiddleware;
|
|
94
|
+
const updateConfig = async (publish) => {
|
|
95
|
+
const configFile = (0, path_1.join)(publish, 'required-server-files.json');
|
|
96
|
+
const config = await (0, fs_extra_1.readJSON)(configFile);
|
|
97
|
+
config.config.env.NEXT_USE_NETLIFY_EDGE = 'true';
|
|
98
|
+
await (0, fs_extra_1.writeJSON)(configFile, config);
|
|
99
|
+
};
|
|
100
|
+
exports.updateConfig = updateConfig;
|
package/lib/helpers/files.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.movePublicFiles = exports.unpatchNextFiles = exports.patchNextFiles = exports.moveStaticPages = exports.getMiddleware = exports.matchesRewrite = exports.matchesRedirect = exports.matchMiddleware = exports.stripLocale = exports.isDynamicRoute = void 0;
|
|
6
|
+
exports.movePublicFiles = exports.unpatchNextFiles = exports.unpatchFile = exports.patchNextFiles = exports.moveStaticPages = exports.getMiddleware = exports.matchesRewrite = exports.matchesRedirect = exports.matchMiddleware = exports.stripLocale = exports.isDynamicRoute = void 0;
|
|
7
7
|
/* eslint-disable max-lines */
|
|
8
8
|
const os_1 = require("os");
|
|
9
9
|
const chalk_1 = require("chalk");
|
|
@@ -54,7 +54,7 @@ const matchesRewrite = (file, rewrites) => {
|
|
|
54
54
|
exports.matchesRewrite = matchesRewrite;
|
|
55
55
|
const getMiddleware = async (publish) => {
|
|
56
56
|
var _a;
|
|
57
|
-
if (process.env.
|
|
57
|
+
if (process.env.NEXT_USE_NETLIFY_EDGE) {
|
|
58
58
|
return [];
|
|
59
59
|
}
|
|
60
60
|
const manifestPath = (0, pathe_1.join)(publish, 'server', 'middleware-manifest.json');
|
|
@@ -232,17 +232,19 @@ exports.moveStaticPages = moveStaticPages;
|
|
|
232
232
|
/**
|
|
233
233
|
* Attempt to patch a source file, preserving a backup
|
|
234
234
|
*/
|
|
235
|
-
const patchFile = async ({ file,
|
|
235
|
+
const patchFile = async ({ file, replacements, }) => {
|
|
236
236
|
if (!(0, fs_extra_1.existsSync)(file)) {
|
|
237
237
|
console.warn('File was not found');
|
|
238
238
|
return false;
|
|
239
239
|
}
|
|
240
240
|
const content = await (0, fs_extra_1.readFile)(file, 'utf8');
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
241
|
+
const newContent = replacements.reduce((acc, [from, to]) => {
|
|
242
|
+
if (acc.includes(to)) {
|
|
243
|
+
console.log('Already patched. Skipping.');
|
|
244
|
+
return acc;
|
|
245
|
+
}
|
|
246
|
+
return acc.replace(from, to);
|
|
247
|
+
}, content);
|
|
246
248
|
if (newContent === content) {
|
|
247
249
|
console.warn('File was not changed');
|
|
248
250
|
return false;
|
|
@@ -256,32 +258,58 @@ const patchFile = async ({ file, from, to }) => {
|
|
|
256
258
|
* The file we need has moved around a bit over the past few versions,
|
|
257
259
|
* so we iterate through the options until we find it
|
|
258
260
|
*/
|
|
259
|
-
const getServerFile = (root) => {
|
|
260
|
-
const candidates = [
|
|
261
|
-
|
|
262
|
-
'next/dist/server/
|
|
263
|
-
|
|
264
|
-
];
|
|
261
|
+
const getServerFile = (root, includeBase = true) => {
|
|
262
|
+
const candidates = ['next/dist/server/next-server', 'next/dist/next-server/server/next-server'];
|
|
263
|
+
if (includeBase) {
|
|
264
|
+
candidates.unshift('next/dist/server/base-server');
|
|
265
|
+
}
|
|
265
266
|
return (0, utils_1.findModuleFromBase)({ candidates, paths: [root] });
|
|
266
267
|
};
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
268
|
+
const baseServerReplacements = [
|
|
269
|
+
[`let ssgCacheKey = `, `let ssgCacheKey = process.env._BYPASS_SSG || `],
|
|
270
|
+
];
|
|
271
|
+
const nextServerReplacements = [
|
|
272
|
+
[
|
|
273
|
+
`getMiddlewareManifest() {\n if (!this.minimalMode) {`,
|
|
274
|
+
`getMiddlewareManifest() {\n if (!this.minimalMode && !process.env.NEXT_USE_NETLIFY_EDGE) {`,
|
|
275
|
+
],
|
|
276
|
+
[
|
|
277
|
+
`generateCatchAllMiddlewareRoute() {\n if (this.minimalMode) return undefined;`,
|
|
278
|
+
`generateCatchAllMiddlewareRoute() {\n if (this.minimalMode || process.env.NEXT_USE_NETLIFY_EDGE) return undefined;`,
|
|
279
|
+
],
|
|
280
|
+
];
|
|
281
|
+
const patchNextFiles = async (root) => {
|
|
282
|
+
const baseServerFile = getServerFile(root);
|
|
283
|
+
console.log(`Patching ${baseServerFile}`);
|
|
284
|
+
if (baseServerFile) {
|
|
285
|
+
await patchFile({
|
|
286
|
+
file: baseServerFile,
|
|
287
|
+
replacements: baseServerReplacements,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
const nextServerFile = getServerFile(root, false);
|
|
291
|
+
console.log(`Patching ${nextServerFile}`);
|
|
292
|
+
if (nextServerFile) {
|
|
293
|
+
await patchFile({
|
|
294
|
+
file: nextServerFile,
|
|
295
|
+
replacements: nextServerReplacements,
|
|
275
296
|
});
|
|
276
297
|
}
|
|
277
|
-
return false;
|
|
278
298
|
};
|
|
279
299
|
exports.patchNextFiles = patchNextFiles;
|
|
280
|
-
const
|
|
281
|
-
const
|
|
282
|
-
const origFile = `${serverFile}.orig`;
|
|
300
|
+
const unpatchFile = async (file) => {
|
|
301
|
+
const origFile = `${file}.orig`;
|
|
283
302
|
if ((0, fs_extra_1.existsSync)(origFile)) {
|
|
284
|
-
await (0, fs_extra_1.move)(origFile,
|
|
303
|
+
await (0, fs_extra_1.move)(origFile, file, { overwrite: true });
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
exports.unpatchFile = unpatchFile;
|
|
307
|
+
const unpatchNextFiles = async (root) => {
|
|
308
|
+
const baseServerFile = getServerFile(root);
|
|
309
|
+
await (0, exports.unpatchFile)(baseServerFile);
|
|
310
|
+
const nextServerFile = getServerFile(root, false);
|
|
311
|
+
if (nextServerFile !== baseServerFile) {
|
|
312
|
+
await (0, exports.unpatchFile)(nextServerFile);
|
|
285
313
|
}
|
|
286
314
|
};
|
|
287
315
|
exports.unpatchNextFiles = unpatchNextFiles;
|
package/lib/helpers/functions.js
CHANGED
|
@@ -51,12 +51,16 @@ const setupImageFunction = async ({ constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIO
|
|
|
51
51
|
});
|
|
52
52
|
await (0, fs_extra_1.copyFile)((0, pathe_1.join)(__dirname, '..', '..', 'lib', 'templates', 'ipx.js'), (0, pathe_1.join)(functionDirectory, functionName));
|
|
53
53
|
const imagePath = imageconfig.path || '/_next/image';
|
|
54
|
+
// If we have edge, we use content negotiation instead of the redirect
|
|
55
|
+
if (!process.env.NEXT_USE_NETLIFY_EDGE) {
|
|
56
|
+
netlifyConfig.redirects.push({
|
|
57
|
+
from: `${imagePath}*`,
|
|
58
|
+
query: { url: ':url', w: ':width', q: ':quality' },
|
|
59
|
+
to: `${basePath}/${constants_1.IMAGE_FUNCTION_NAME}/w_:width,q_:quality/:url`,
|
|
60
|
+
status: 301,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
54
63
|
netlifyConfig.redirects.push({
|
|
55
|
-
from: `${imagePath}*`,
|
|
56
|
-
query: { url: ':url', w: ':width', q: ':quality' },
|
|
57
|
-
to: `${basePath}/${constants_1.IMAGE_FUNCTION_NAME}/w_:width,q_:quality/:url`,
|
|
58
|
-
status: 301,
|
|
59
|
-
}, {
|
|
60
64
|
from: `${basePath}/${constants_1.IMAGE_FUNCTION_NAME}/*`,
|
|
61
65
|
to: `/.netlify/builders/${constants_1.IMAGE_FUNCTION_NAME}`,
|
|
62
66
|
status: 200,
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
package/lib/index.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const path_1 = require("path");
|
|
4
|
+
const chalk_1 = require("chalk");
|
|
4
5
|
const fs_extra_1 = require("fs-extra");
|
|
6
|
+
const outdent_1 = require("outdent");
|
|
5
7
|
const constants_1 = require("./constants");
|
|
6
8
|
const cache_1 = require("./helpers/cache");
|
|
7
9
|
const config_1 = require("./helpers/config");
|
|
10
|
+
const edge_1 = require("./helpers/edge");
|
|
8
11
|
const files_1 = require("./helpers/files");
|
|
9
12
|
const functions_1 = require("./helpers/functions");
|
|
10
13
|
const redirects_1 = require("./helpers/redirects");
|
|
@@ -45,9 +48,6 @@ const plugin = {
|
|
|
45
48
|
await (0, functions_1.generatePagesResolver)({ target, constants });
|
|
46
49
|
await (0, files_1.movePublicFiles)({ appDir, outdir, publish });
|
|
47
50
|
await (0, files_1.patchNextFiles)(basePath);
|
|
48
|
-
if (process.env.EXPERIMENTAL_MOVE_STATIC_PAGES) {
|
|
49
|
-
console.log("The flag 'EXPERIMENTAL_MOVE_STATIC_PAGES' is no longer required, as it is now the default. To disable this behavior, set the env var 'SERVE_STATIC_FILES_FROM_ORIGIN' to 'true'");
|
|
50
|
-
}
|
|
51
51
|
if (!process.env.SERVE_STATIC_FILES_FROM_ORIGIN) {
|
|
52
52
|
await (0, files_1.moveStaticPages)({ target, netlifyConfig, i18n, basePath });
|
|
53
53
|
}
|
|
@@ -61,6 +61,14 @@ const plugin = {
|
|
|
61
61
|
nextConfig: { basePath, i18n, trailingSlash, appDir },
|
|
62
62
|
buildId,
|
|
63
63
|
});
|
|
64
|
+
if (process.env.NEXT_USE_NETLIFY_EDGE) {
|
|
65
|
+
console.log((0, outdent_1.outdent) `
|
|
66
|
+
✨ Deploying to ${(0, chalk_1.greenBright) `Netlify Edge Functions`} ✨
|
|
67
|
+
This feature is in beta. Please share your feedback here: https://ntl.fyi/next-netlify-edge
|
|
68
|
+
`);
|
|
69
|
+
await (0, edge_1.writeMiddleware)(netlifyConfig);
|
|
70
|
+
await (0, edge_1.updateConfig)(publish);
|
|
71
|
+
}
|
|
64
72
|
},
|
|
65
73
|
async onPostBuild({ netlifyConfig: { build: { publish }, redirects, }, utils: { status, cache, functions, build: { failBuild }, }, constants: { FUNCTIONS_DIST }, }) {
|
|
66
74
|
await (0, cache_1.saveCache)({ cache, publish });
|
package/lib/templates/ipx.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.handler = void 0;
|
|
4
|
-
/* eslint-disable node/no-missing-import, import/no-unresolved, @typescript-eslint/ban-ts-comment */
|
|
5
4
|
const ipx_1 = require("@netlify/ipx");
|
|
6
5
|
// @ts-ignore Injected at build time
|
|
7
6
|
const imageconfig_json_1 = require("./imageconfig.json");
|
package/package.json
CHANGED
|
@@ -1,57 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/plugin-nextjs",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "Run Next.js seamlessly on Netlify",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"lib/**/*",
|
|
8
8
|
"manifest.yml"
|
|
9
9
|
],
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build:demo": "next build demos/default",
|
|
12
|
-
"cy:open": "cypress open --config-file cypress/config/all.json",
|
|
13
|
-
"dev:demo": "next dev demos/default",
|
|
14
|
-
"format": "run-s format:check-fix:*",
|
|
15
|
-
"format:ci": "run-s format:check:*",
|
|
16
|
-
"format:check-fix:lint": "run-e format:check:lint format:fix:lint",
|
|
17
|
-
"format:check:lint": "cross-env-shell eslint $npm_package_config_eslint",
|
|
18
|
-
"format:fix:lint": "cross-env-shell eslint --fix $npm_package_config_eslint",
|
|
19
|
-
"format:check-fix:prettier": "run-e format:check:prettier format:fix:prettier",
|
|
20
|
-
"format:check:prettier": "cross-env-shell prettier --check $npm_package_config_prettier",
|
|
21
|
-
"format:fix:prettier": "cross-env-shell prettier --write $npm_package_config_prettier",
|
|
22
|
-
"prepublishOnly": "run-s publish:pull publish:install clean build test",
|
|
23
|
-
"publish:pull": "git pull",
|
|
24
|
-
"publish:install": "npm ci",
|
|
25
|
-
"publish:test": "npm test",
|
|
26
|
-
"test": "run-s build build:demo test:jest",
|
|
27
|
-
"test:jest": "jest",
|
|
28
|
-
"test:jest:update": "jest --updateSnapshot",
|
|
29
|
-
"test:update": "run-s build build:demo test:jest:update",
|
|
30
|
-
"prepare": "husky install node_modules/@netlify/eslint-config-node/.husky/ && npm run build",
|
|
31
|
-
"clean": "rimraf lib",
|
|
32
|
-
"build": "tsc",
|
|
33
|
-
"watch": "tsc --watch"
|
|
34
|
-
},
|
|
35
|
-
"config": {
|
|
36
|
-
"eslint": "--cache --format=codeframe --max-warnings=0 \"{src,scripts,tests,.github}/**/*.{ts,js,md,html}\" \"*.{ts,js,md,html}\" \".*.{ts,js,md,html}\"",
|
|
37
|
-
"prettier": "--loglevel=warn \"{src,scripts,tests,.github}/**/*.{ts,js,md,yml,json,html}\" \"*.{ts,js,yml,json,html}\" \".*.{ts,js,yml,json,html}\" \"!package-lock.json\""
|
|
38
|
-
},
|
|
39
|
-
"repository": {
|
|
40
|
-
"type": "git",
|
|
41
|
-
"url": "git+https://github.com/netlify/netlify-plugin-nextjs.git"
|
|
42
|
-
},
|
|
43
|
-
"keywords": [
|
|
44
|
-
"nextjs",
|
|
45
|
-
"netlify",
|
|
46
|
-
"next",
|
|
47
|
-
"netlify-plugin"
|
|
48
|
-
],
|
|
49
|
-
"author": "lindsaylevine",
|
|
50
|
-
"license": "MIT",
|
|
51
|
-
"bugs": {
|
|
52
|
-
"url": "https://github.com/netlify/netlify-plugin-nextjs/issues"
|
|
53
|
-
},
|
|
54
|
-
"homepage": "https://github.com/netlify/netlify-plugin-nextjs#readme",
|
|
55
10
|
"dependencies": {
|
|
56
11
|
"@netlify/functions": "^1.0.0",
|
|
57
12
|
"@netlify/ipx": "^0.0.10",
|
|
@@ -72,48 +27,35 @@
|
|
|
72
27
|
"tiny-glob": "^0.2.9"
|
|
73
28
|
},
|
|
74
29
|
"devDependencies": {
|
|
75
|
-
"@
|
|
76
|
-
"@babel/preset-env": "^7.15.8",
|
|
77
|
-
"@babel/preset-typescript": "^7.16.0",
|
|
78
|
-
"@netlify/build": "^26.5.2",
|
|
79
|
-
"@netlify/eslint-config-node": "^5.1.8",
|
|
80
|
-
"@reach/dialog": "^0.16.2",
|
|
81
|
-
"@reach/visually-hidden": "^0.16.0",
|
|
82
|
-
"@testing-library/cypress": "^8.0.1",
|
|
30
|
+
"@netlify/build": "^27.0.1",
|
|
83
31
|
"@types/fs-extra": "^9.0.13",
|
|
84
|
-
"@types/jest": "^27.
|
|
85
|
-
"@types/
|
|
86
|
-
"@types/node": "^17.0.10",
|
|
87
|
-
"@types/react": "^17.0.38",
|
|
88
|
-
"babel-jest": "^27.2.5",
|
|
89
|
-
"cpy": "^8.1.2",
|
|
90
|
-
"cypress": "^9.0.0",
|
|
91
|
-
"eslint-config-next": "^12.0.0",
|
|
32
|
+
"@types/jest": "^27.4.1",
|
|
33
|
+
"@types/node": "^17.0.25",
|
|
92
34
|
"husky": "^7.0.4",
|
|
93
|
-
"
|
|
94
|
-
"netlify-plugin-cypress": "^2.2.0",
|
|
35
|
+
"if-env": "^1.0.4",
|
|
95
36
|
"npm-run-all": "^4.1.5",
|
|
96
|
-
"
|
|
97
|
-
"react": "^17.0.1",
|
|
98
|
-
"react-dom": "^17.0.1",
|
|
99
|
-
"rimraf": "^3.0.2",
|
|
100
|
-
"sass": "^1.49.0",
|
|
101
|
-
"tmp-promise": "^3.0.2",
|
|
102
|
-
"typescript": "^4.3.4"
|
|
37
|
+
"typescript": "^4.6.3"
|
|
103
38
|
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"prepublishOnly": "run-s publish:pull publish:install clean build",
|
|
41
|
+
"publish:pull": "git pull",
|
|
42
|
+
"publish:install": "npm ci",
|
|
43
|
+
"clean": "rimraf lib",
|
|
44
|
+
"build": "tsc",
|
|
45
|
+
"watch": "tsc --watch",
|
|
46
|
+
"prepare": "npm run build"
|
|
47
|
+
},
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "git+https://github.com/netlify/netlify-plugin-nextjs.git"
|
|
51
|
+
},
|
|
52
|
+
"author": "",
|
|
53
|
+
"license": "ISC",
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/netlify/netlify-plugin-nextjs/issues"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/netlify/netlify-plugin-nextjs#readme",
|
|
104
58
|
"engines": {
|
|
105
59
|
"node": ">=12.0.0"
|
|
106
|
-
},
|
|
107
|
-
"jest": {
|
|
108
|
-
"testMatch": [
|
|
109
|
-
"**/test/**/*.js",
|
|
110
|
-
"!**/test/fixtures/**",
|
|
111
|
-
"!**/test/sample/**"
|
|
112
|
-
],
|
|
113
|
-
"transform": {
|
|
114
|
-
"\\.[jt]sx?$": "babel-jest"
|
|
115
|
-
},
|
|
116
|
-
"verbose": true,
|
|
117
|
-
"testTimeout": 60000
|
|
118
60
|
}
|
|
119
61
|
}
|
package/README.md
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-

|
|
2
|
-
|
|
3
|
-
# Essential Next.js Build Plugin
|
|
4
|
-
|
|
5
|
-
<p align="center">
|
|
6
|
-
<a aria-label="npm version" href="https://www.npmjs.com/package/@netlify/plugin-nextjs">
|
|
7
|
-
<img alt="" src="https://img.shields.io/npm/v/@netlify/plugin-nextjs">
|
|
8
|
-
</a>
|
|
9
|
-
<a aria-label="MIT License" href="https://img.shields.io/npm/l/@netlify/plugin-nextjs">
|
|
10
|
-
<img alt="" src="https://img.shields.io/npm/l/@netlify/plugin-nextjs">
|
|
11
|
-
</a>
|
|
12
|
-
</p>
|
|
13
|
-
|
|
14
|
-
## What's new in this version
|
|
15
|
-
|
|
16
|
-
Version 4 is a complete rewrite of the Essential Next.js plugin. For full details of everything that's new, check out
|
|
17
|
-
[the v4 release notes](https://github.com/netlify/netlify-plugin-nextjs/blob/main/docs/release-notes/v4.md)
|
|
18
|
-
|
|
19
|
-
## Installing the plugin
|
|
20
|
-
|
|
21
|
-
The plugin installs automatically for new Next.js sites on Netlify. You can also install it manually like this:
|
|
22
|
-
|
|
23
|
-
```shell
|
|
24
|
-
npm install -D @netlify/plugin-nextjs
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
...then add the plugin to your `netlify.toml` file:
|
|
28
|
-
|
|
29
|
-
```toml
|
|
30
|
-
[[plugins]]
|
|
31
|
-
package = "@netlify/plugin-nextjs"
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Deploying
|
|
35
|
-
|
|
36
|
-
If you build on Netlify, this plugin will work with no additional configuration. However if you are building and
|
|
37
|
-
deploying locally using the Netlify CLI, you must deploy using `netlify deploy --build`. Running the
|
|
38
|
-
build and deploy commands separately will not work, because the plugin will not generate the required configuration.
|
|
39
|
-
|
|
40
|
-
## Migrating from an older version of the plugin
|
|
41
|
-
|
|
42
|
-
You can manually upgrade from the previous version of the plugin by running the following command:
|
|
43
|
-
|
|
44
|
-
```shell
|
|
45
|
-
npm install -D @netlify/plugin-nextjs@latest
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Change the `publish` directory to `.next`:
|
|
49
|
-
|
|
50
|
-
```toml
|
|
51
|
-
[build]
|
|
52
|
-
publish = ".next"
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
If you previously set these values, they're no longer needed and can be removed:
|
|
56
|
-
|
|
57
|
-
- `distDir` in your `next.config.js`
|
|
58
|
-
- `node_bundler = "esbuild"` in `netlify.toml`
|
|
59
|
-
- `external_node_modules` in `netlify.toml`
|
|
60
|
-
|
|
61
|
-
The `serverless` and `experimental-serverless-trace` targets are deprecated in Next 12, and all builds with this plugin
|
|
62
|
-
will now use the default `server` target. If you previously set the target in your `next.config.js`, you should remove
|
|
63
|
-
it.
|
|
64
|
-
|
|
65
|
-
If you currently use redirects or rewrites on your site, see
|
|
66
|
-
[the Rewrites and Redirects guide](https://github.com/netlify/netlify-plugin-nextjs/blob/main/docs/redirects-rewrites.md)
|
|
67
|
-
for information on changes to how they are handled in this version. In particular, note that `_redirects` and `_headers`
|
|
68
|
-
files must be placed in `public`, not in the root of the site.
|
|
69
|
-
|
|
70
|
-
If you want to use Next 12's beta Middleware feature, this will mostly work as expected but please
|
|
71
|
-
[read the docs on some caveats and workarounds](https://github.com/netlify/netlify-plugin-nextjs/blob/main/docs/middleware.md)
|
|
72
|
-
that are currently needed.
|
|
73
|
-
|
|
74
|
-
## Monorepos
|
|
75
|
-
|
|
76
|
-
If you are using a monorepo you will need to change `publish` to point to the full path to the built `.next` directory,
|
|
77
|
-
which may be in a subdirectory. If you have changed your `distDir` then it will need to match that.
|
|
78
|
-
|
|
79
|
-
If you are using Nx, then you will need to point `publish` to the folder inside `dist`, e.g. `dist/apps/myapp/.next`.
|
|
80
|
-
|
|
81
|
-
## Incremental Static Regeneration (ISR)
|
|
82
|
-
|
|
83
|
-
The Essential Next.js plugin now fully supports ISR on Netlify. For more details see
|
|
84
|
-
[the ISR docs](https://github.com/netlify/netlify-plugin-nextjs/blob/main/docs/isr.md).
|
|
85
|
-
|
|
86
|
-
## Use with `next export`
|
|
87
|
-
|
|
88
|
-
If you are using `next export` to generate a static site, you do not need most of the functionality of this plugin and
|
|
89
|
-
you can remove it. Alternatively you can
|
|
90
|
-
[set the environment variable](https://docs.netlify.com/configure-builds/environment-variables/)
|
|
91
|
-
`NETLIFY_NEXT_PLUGIN_SKIP` to `true` and the plugin will handle caching but won't generate any functions for SSR
|
|
92
|
-
support. See [`demos/next-export`](https://github.com/netlify/netlify-plugin-nextjs/tree/main/demos/next-export) for an
|
|
93
|
-
example.
|
|
94
|
-
|
|
95
|
-
## Asset optimization
|
|
96
|
-
|
|
97
|
-
Netlify [asset optimization](https://docs.netlify.com/site-deploys/post-processing/) should not be used with Next.js
|
|
98
|
-
sites. Assets are already optimized by Next.js at build time, and doing further optimization can break your site. Ensure
|
|
99
|
-
that it is not enabled at **Site settings > Build & deploy > Post processing > Asset optimization**.
|
|
100
|
-
|
|
101
|
-
## Generated functions
|
|
102
|
-
|
|
103
|
-
This plugin works by generating three Netlify functions that handle requests that haven't been pre-rendered. These are
|
|
104
|
-
`___netlify-handler` (for SSR and API routes), `___netlify-odb-handler` (for ISR and fallback routes), and `_ipx` (for
|
|
105
|
-
images). You can see the requests for these in [the function logs](https://docs.netlify.com/functions/logs/). For ISR
|
|
106
|
-
and fallback routes you will not see any requests that are served from the edge cache, just actual rendering requests.
|
|
107
|
-
These are all internal functions, so you won't find them in your site's own functions directory.
|
|
108
|
-
|
|
109
|
-
## Feedback
|
|
110
|
-
|
|
111
|
-
If you think you have found a bug in the plugin,
|
|
112
|
-
[please open an issue](https://github.com/netlify/netlify-plugin-nextjs/issues). If you have comments or feature
|
|
113
|
-
requests, [see the dicussion board](https://github.com/netlify/netlify-plugin-nextjs/discussions)
|