@netlify/plugin-nextjs 4.29.2 → 4.29.3-appdir.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 +39 -25
- package/lib/helpers/files.js +10 -8
- package/lib/helpers/functions.js +4 -1
- package/lib/index.js +6 -3
- package/lib/templates/getApiHandler.js +1 -1
- package/lib/templates/getHandler.js +2 -7
- package/lib/templates/handlerUtils.js +7 -6
- package/lib/templates/ipx.js +1 -1
- package/package.json +2 -2
- package/src/templates/edge/runtime.ts +7 -1
package/lib/helpers/edge.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.writeEdgeFunctions = exports.writeDevEdgeFunction = exports.cleanupEdgeFunctions = exports.loadMiddlewareManifest = void 0;
|
|
6
|
+
exports.writeEdgeFunctions = exports.writeDevEdgeFunction = exports.cleanupEdgeFunctions = exports.loadAppPathRoutesManifest = exports.loadMiddlewareManifest = void 0;
|
|
7
7
|
/* eslint-disable max-lines */
|
|
8
8
|
const fs_1 = require("fs");
|
|
9
9
|
const path_1 = require("path");
|
|
@@ -13,14 +13,15 @@ const fs_extra_1 = require("fs-extra");
|
|
|
13
13
|
const outdent_1 = require("outdent");
|
|
14
14
|
const config_1 = require("./config");
|
|
15
15
|
const matchers_1 = require("./matchers");
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return null;
|
|
16
|
+
const maybeLoadJson = (path) => {
|
|
17
|
+
if ((0, fs_1.existsSync)(path)) {
|
|
18
|
+
return (0, fs_extra_1.readJson)(path);
|
|
20
19
|
}
|
|
21
|
-
return (0, fs_extra_1.readJson)(middlewarePath);
|
|
22
20
|
};
|
|
21
|
+
const loadMiddlewareManifest = (netlifyConfig) => maybeLoadJson((0, path_1.resolve)(netlifyConfig.build.publish, 'server', 'middleware-manifest.json'));
|
|
23
22
|
exports.loadMiddlewareManifest = loadMiddlewareManifest;
|
|
23
|
+
const loadAppPathRoutesManifest = (netlifyConfig) => maybeLoadJson((0, path_1.resolve)(netlifyConfig.build.publish, 'app-path-routes-manifest.json'));
|
|
24
|
+
exports.loadAppPathRoutesManifest = loadAppPathRoutesManifest;
|
|
24
25
|
/**
|
|
25
26
|
* Convert the Next middleware name into a valid Edge Function name
|
|
26
27
|
*/
|
|
@@ -35,27 +36,23 @@ import {
|
|
|
35
36
|
// Deno defines "window", but naughty libraries think this means it's a browser
|
|
36
37
|
delete globalThis.window
|
|
37
38
|
globalThis.process = { env: {...Deno.env.toObject(), NEXT_RUNTIME: 'edge', 'NEXT_PRIVATE_MINIMAL_MODE': '1' } }
|
|
39
|
+
globalThis.EdgeRuntime = "netlify-edge"
|
|
38
40
|
// Next uses "self" as a function-scoped global-like object
|
|
39
41
|
const self = {}
|
|
40
42
|
let _ENTRIES = {}
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
.map(([, value]) => value);
|
|
54
|
-
};
|
|
55
|
-
}
|
|
44
|
+
// Next.js uses this extension to the Headers API implemented by Cloudflare workerd
|
|
45
|
+
if(!('getAll' in Headers.prototype)) {
|
|
46
|
+
Headers.prototype.getAll = function getAll(name) {
|
|
47
|
+
name = name.toLowerCase();
|
|
48
|
+
if (name !== "set-cookie") {
|
|
49
|
+
throw new Error("Headers.getAll is only supported for Set-Cookie");
|
|
50
|
+
}
|
|
51
|
+
return [...this.entries()]
|
|
52
|
+
.filter(([key]) => key === name)
|
|
53
|
+
.map(([, value]) => value);
|
|
54
|
+
};
|
|
56
55
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
56
|
// Next uses blob: urls to refer to local assets, so we need to intercept these
|
|
60
57
|
const _fetch = globalThis.fetch
|
|
61
58
|
const fetch = async (url, init) => {
|
|
@@ -112,7 +109,7 @@ const getMiddlewareBundle = async ({ edgeFunctionDefinition, netlifyConfig, }) =
|
|
|
112
109
|
};
|
|
113
110
|
const getEdgeTemplatePath = (file) => (0, path_1.join)(__dirname, '..', '..', 'src', 'templates', 'edge', file);
|
|
114
111
|
const copyEdgeSourceFile = ({ file, target, edgeFunctionDir, }) => fs_1.promises.copyFile(getEdgeTemplatePath(file), (0, path_1.join)(edgeFunctionDir, target !== null && target !== void 0 ? target : file));
|
|
115
|
-
const writeEdgeFunction = async ({ edgeFunctionDefinition, edgeFunctionRoot, netlifyConfig, nextConfig, }) => {
|
|
112
|
+
const writeEdgeFunction = async ({ edgeFunctionDefinition, edgeFunctionRoot, netlifyConfig, pageRegexMap, appPathRoutesManifest = {}, nextConfig, cache, }) => {
|
|
116
113
|
const name = sanitizeName(edgeFunctionDefinition.name);
|
|
117
114
|
const edgeFunctionDir = (0, path_1.join)(edgeFunctionRoot, name);
|
|
118
115
|
const bundle = await getMiddlewareBundle({
|
|
@@ -140,11 +137,19 @@ const writeEdgeFunction = async ({ edgeFunctionDefinition, edgeFunctionRoot, net
|
|
|
140
137
|
else {
|
|
141
138
|
matchers.push(...edgeFunctionDefinition.matchers);
|
|
142
139
|
}
|
|
140
|
+
// If the EF matches a page, it's an app dir page so needs a matcher too
|
|
141
|
+
// The object will be empty if appDir isn't enabled in the Next config
|
|
142
|
+
if (pageRegexMap && edgeFunctionDefinition.page in appPathRoutesManifest) {
|
|
143
|
+
const regexp = pageRegexMap.get(appPathRoutesManifest[edgeFunctionDefinition.page]);
|
|
144
|
+
if (regexp) {
|
|
145
|
+
matchers.push({ regexp });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
143
148
|
await (0, fs_extra_1.writeJson)((0, path_1.join)(edgeFunctionDir, 'matchers.json'), matchers);
|
|
144
149
|
// We add a defintion for each matching path
|
|
145
150
|
return matchers.map((matcher) => {
|
|
146
151
|
const pattern = (0, matchers_1.stripLookahead)(matcher.regexp);
|
|
147
|
-
return { function: name, pattern, name: edgeFunctionDefinition.name };
|
|
152
|
+
return { function: name, pattern, name: edgeFunctionDefinition.name, cache };
|
|
148
153
|
});
|
|
149
154
|
};
|
|
150
155
|
const cleanupEdgeFunctions = ({ INTERNAL_EDGE_FUNCTIONS_SRC = '.netlify/edge-functions', }) => (0, fs_extra_1.emptyDir)(INTERNAL_EDGE_FUNCTIONS_SRC);
|
|
@@ -172,7 +177,7 @@ exports.writeDevEdgeFunction = writeDevEdgeFunction;
|
|
|
172
177
|
/**
|
|
173
178
|
* Writes Edge Functions for the Next middleware
|
|
174
179
|
*/
|
|
175
|
-
const writeEdgeFunctions = async (netlifyConfig) => {
|
|
180
|
+
const writeEdgeFunctions = async ({ netlifyConfig, routesManifest, }) => {
|
|
176
181
|
const manifest = {
|
|
177
182
|
functions: [],
|
|
178
183
|
version: 1,
|
|
@@ -219,13 +224,22 @@ const writeEdgeFunctions = async (netlifyConfig) => {
|
|
|
219
224
|
// Older versions of the manifest format don't have the functions field
|
|
220
225
|
// No, the version field was not incremented
|
|
221
226
|
if (typeof middlewareManifest.functions === 'object') {
|
|
227
|
+
// When using the app dir, we also need to check if the EF matches a page
|
|
228
|
+
const appPathRoutesManifest = await (0, exports.loadAppPathRoutesManifest)(netlifyConfig);
|
|
229
|
+
const pageRegexMap = new Map([...(routesManifest.dynamicRoutes || []), ...(routesManifest.staticRoutes || [])].map((route) => [
|
|
230
|
+
route.page,
|
|
231
|
+
route.regex,
|
|
232
|
+
]));
|
|
222
233
|
for (const edgeFunctionDefinition of Object.values(middlewareManifest.functions)) {
|
|
223
234
|
usesEdge = true;
|
|
224
235
|
const functionDefinitions = await writeEdgeFunction({
|
|
225
236
|
edgeFunctionDefinition,
|
|
226
237
|
edgeFunctionRoot,
|
|
227
238
|
netlifyConfig,
|
|
239
|
+
pageRegexMap,
|
|
240
|
+
appPathRoutesManifest,
|
|
228
241
|
nextConfig,
|
|
242
|
+
cache: 'manual',
|
|
229
243
|
});
|
|
230
244
|
manifest.functions.push(...functionDefinitions);
|
|
231
245
|
}
|
package/lib/helpers/files.js
CHANGED
|
@@ -70,7 +70,6 @@ exports.getMiddleware = getMiddleware;
|
|
|
70
70
|
const moveStaticPages = async ({ netlifyConfig, target, i18n, basePath, }) => {
|
|
71
71
|
console.log('Moving static page files to serve from CDN...');
|
|
72
72
|
const outputDir = (0, pathe_1.join)(netlifyConfig.build.publish, target === 'server' ? 'server' : 'serverless');
|
|
73
|
-
const root = (0, pathe_1.join)(outputDir, 'pages');
|
|
74
73
|
const buildId = (0, fs_extra_1.readFileSync)((0, pathe_1.join)(netlifyConfig.build.publish, 'BUILD_ID'), 'utf8').trim();
|
|
75
74
|
const dataDir = (0, pathe_1.join)('_next', 'data', buildId);
|
|
76
75
|
await (0, fs_extra_1.ensureDir)((0, pathe_1.join)(netlifyConfig.build.publish, dataDir));
|
|
@@ -92,14 +91,17 @@ const moveStaticPages = async ({ netlifyConfig, target, i18n, basePath, }) => {
|
|
|
92
91
|
}
|
|
93
92
|
}
|
|
94
93
|
});
|
|
95
|
-
|
|
94
|
+
let fileCount = 0;
|
|
96
95
|
const filesManifest = {};
|
|
97
96
|
const moveFile = async (file) => {
|
|
97
|
+
// Strip the initial 'app' or 'pages' directory from the output path
|
|
98
|
+
const pathname = file.split('/').slice(1).join('/');
|
|
99
|
+
// .rsc data files go next to the html file
|
|
98
100
|
const isData = file.endsWith('.json');
|
|
99
|
-
const source = (0, pathe_1.join)(
|
|
100
|
-
const targetFile = isData ? (0, pathe_1.join)(dataDir,
|
|
101
|
+
const source = (0, pathe_1.join)(outputDir, file);
|
|
102
|
+
const targetFile = isData ? (0, pathe_1.join)(dataDir, pathname) : pathname;
|
|
101
103
|
const targetPath = basePath ? (0, pathe_1.join)(basePath, targetFile) : targetFile;
|
|
102
|
-
|
|
104
|
+
fileCount += 1;
|
|
103
105
|
filesManifest[file] = targetPath;
|
|
104
106
|
const dest = (0, pathe_1.join)(netlifyConfig.build.publish, targetPath);
|
|
105
107
|
try {
|
|
@@ -110,8 +112,8 @@ const moveStaticPages = async ({ netlifyConfig, target, i18n, basePath, }) => {
|
|
|
110
112
|
}
|
|
111
113
|
};
|
|
112
114
|
// Move all static files, except error documents and nft manifests
|
|
113
|
-
const pages = await (0, globby_1.default)(['
|
|
114
|
-
cwd:
|
|
115
|
+
const pages = await (0, globby_1.default)(['{app,pages}/**/*.{html,json,rsc}', '!**/(500|404|*.js.nft).{html,json}'], {
|
|
116
|
+
cwd: outputDir,
|
|
115
117
|
dot: true,
|
|
116
118
|
});
|
|
117
119
|
const matchingMiddleware = new Set();
|
|
@@ -149,7 +151,7 @@ const moveStaticPages = async ({ netlifyConfig, target, i18n, basePath, }) => {
|
|
|
149
151
|
return limit(moveFile, filePath);
|
|
150
152
|
});
|
|
151
153
|
await Promise.all(promises);
|
|
152
|
-
console.log(`Moved ${
|
|
154
|
+
console.log(`Moved ${fileCount} files`);
|
|
153
155
|
if (matchedPages.size !== 0) {
|
|
154
156
|
console.log((0, chalk_1.yellowBright)((0, outdent_1.outdent) `
|
|
155
157
|
Skipped moving ${matchedPages.size} ${matchedPages.size === 1 ? 'file because it matches' : 'files because they match'} middleware, so cannot be deployed to the CDN and will be served from the origin instead.
|
package/lib/helpers/functions.js
CHANGED
|
@@ -20,10 +20,13 @@ const utils_1 = require("./utils");
|
|
|
20
20
|
const generateFunctions = async ({ FUNCTIONS_SRC = constants_1.DEFAULT_FUNCTIONS_SRC, INTERNAL_FUNCTIONS_SRC, PUBLISH_DIR }, appDir, apiRoutes) => {
|
|
21
21
|
const publish = (0, pathe_1.resolve)(PUBLISH_DIR);
|
|
22
22
|
const functionsDir = (0, pathe_1.resolve)(INTERNAL_FUNCTIONS_SRC || FUNCTIONS_SRC);
|
|
23
|
-
console.log({ functionsDir });
|
|
24
23
|
const functionDir = (0, pathe_1.join)(functionsDir, constants_1.HANDLER_FUNCTION_NAME);
|
|
25
24
|
const publishDir = (0, pathe_1.relative)(functionDir, publish);
|
|
26
25
|
for (const { route, config, compiled } of apiRoutes) {
|
|
26
|
+
// Don't write a lambda if the runtime is edge
|
|
27
|
+
if (config.runtime === 'experimental-edge') {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
27
30
|
const apiHandlerSource = await (0, getApiHandler_1.getApiHandler)({
|
|
28
31
|
page: route,
|
|
29
32
|
config,
|
package/lib/index.js
CHANGED
|
@@ -44,7 +44,7 @@ const plugin = {
|
|
|
44
44
|
}
|
|
45
45
|
const { publish } = netlifyConfig.build;
|
|
46
46
|
(0, verification_1.checkNextSiteHasBuilt)({ publish, failBuild });
|
|
47
|
-
const { appDir, basePath, i18n, images, target, ignore, trailingSlash, outdir, experimental } = await (0, config_1.getNextConfig)({
|
|
47
|
+
const { appDir, basePath, i18n, images, target, ignore, trailingSlash, outdir, experimental, routesManifest } = await (0, config_1.getNextConfig)({
|
|
48
48
|
publish,
|
|
49
49
|
failBuild,
|
|
50
50
|
});
|
|
@@ -118,7 +118,7 @@ const plugin = {
|
|
|
118
118
|
buildId,
|
|
119
119
|
apiRoutes,
|
|
120
120
|
});
|
|
121
|
-
await (0, edge_1.writeEdgeFunctions)(netlifyConfig);
|
|
121
|
+
await (0, edge_1.writeEdgeFunctions)({ netlifyConfig, routesManifest });
|
|
122
122
|
},
|
|
123
123
|
async onPostBuild({ netlifyConfig: { build: { publish }, redirects, headers, }, utils: { status, cache, functions, build: { failBuild }, }, constants: { FUNCTIONS_DIST }, }) {
|
|
124
124
|
await (0, cache_1.saveCache)({ cache, publish });
|
|
@@ -134,11 +134,14 @@ const plugin = {
|
|
|
134
134
|
await (0, verification_1.checkForOldFunctions)({ functions });
|
|
135
135
|
await (0, verification_1.checkZipSize)((0, path_1.join)(FUNCTIONS_DIST, `${constants_1.ODB_FUNCTION_NAME}.zip`));
|
|
136
136
|
const nextConfig = await (0, config_1.getNextConfig)({ publish, failBuild });
|
|
137
|
-
const { basePath, appDir } = nextConfig;
|
|
137
|
+
const { basePath, appDir, experimental } = nextConfig;
|
|
138
138
|
(0, config_1.generateCustomHeaders)(nextConfig, headers);
|
|
139
139
|
(0, verification_1.warnForProblematicUserRewrites)({ basePath, redirects });
|
|
140
140
|
(0, verification_1.warnForRootRedirects)({ appDir });
|
|
141
141
|
await (0, functions_1.warnOnApiRoutes)({ FUNCTIONS_DIST });
|
|
142
|
+
if (experimental === null || experimental === void 0 ? void 0 : experimental.appDir) {
|
|
143
|
+
console.log('🧪 Thank you for testing "appDir" support on Netlify. For known issues and to give feedback, visit https://ntl.fyi/next-13-feedback');
|
|
144
|
+
}
|
|
142
145
|
},
|
|
143
146
|
};
|
|
144
147
|
// The types haven't been updated yet
|
|
@@ -105,7 +105,7 @@ const getApiHandler = ({ page, config, publishDir = '../../../.next', appDir = '
|
|
|
105
105
|
const { config } = require("${publishDir}/required-server-files.json")
|
|
106
106
|
let staticManifest
|
|
107
107
|
const path = require("path");
|
|
108
|
-
const pageRoot = path.resolve(path.join(__dirname, "${publishDir}", "
|
|
108
|
+
const pageRoot = path.resolve(path.join(__dirname, "${publishDir}", "server"));
|
|
109
109
|
const handler = (${makeHandler.toString()})(config, "${appDir}", pageRoot, ${JSON.stringify(page)})
|
|
110
110
|
exports.handler = ${config.type === "experimental-scheduled" /* ApiRouteType.SCHEDULED */ ? `schedule(${JSON.stringify(config.schedule)}, handler);` : 'handler'}
|
|
111
111
|
`;
|
|
@@ -37,9 +37,7 @@ const makeHandler = (conf, app, pageRoot, staticManifest = [], mode = 'ssr') =>
|
|
|
37
37
|
for (const [key, value] of Object.entries(conf.env)) {
|
|
38
38
|
process.env[key] = String(value);
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
let base;
|
|
42
|
-
augmentFsModule({ promises, staticManifest, pageRoot, getBase: () => base });
|
|
40
|
+
augmentFsModule({ promises, staticManifest, pageRoot });
|
|
43
41
|
// We memoize this because it can be shared between requests, but don't instantiate it until
|
|
44
42
|
// the first request because we need the host and port.
|
|
45
43
|
let bridge;
|
|
@@ -49,9 +47,6 @@ const makeHandler = (conf, app, pageRoot, staticManifest = [], mode = 'ssr') =>
|
|
|
49
47
|
}
|
|
50
48
|
const url = new URL(event.rawUrl);
|
|
51
49
|
const port = Number.parseInt(url.port) || 80;
|
|
52
|
-
const { host } = event.headers;
|
|
53
|
-
const protocol = event.headers['x-forwarded-proto'] || 'http';
|
|
54
|
-
base = `${protocol}://${host}`;
|
|
55
50
|
const NextServer = getNextServer();
|
|
56
51
|
const nextServer = new NextServer({
|
|
57
52
|
conf,
|
|
@@ -149,7 +144,7 @@ const getHandler = ({ isODB = false, publishDir = '../../../.next', appDir = '..
|
|
|
149
144
|
staticManifest = require("${publishDir}/static-manifest.json")
|
|
150
145
|
} catch {}
|
|
151
146
|
const path = require("path");
|
|
152
|
-
const pageRoot = path.resolve(path.join(__dirname, "${publishDir}",
|
|
147
|
+
const pageRoot = path.resolve(path.join(__dirname, "${publishDir}", "server"));
|
|
153
148
|
exports.handler = ${isODB
|
|
154
149
|
? `builder((${makeHandler.toString()})(config, "${appDir}", pageRoot, staticManifest, 'odb'));`
|
|
155
150
|
: `(${makeHandler.toString()})(config, "${appDir}", pageRoot, staticManifest, 'ssr');`}
|
|
@@ -75,7 +75,7 @@ exports.getMultiValueHeaders = getMultiValueHeaders;
|
|
|
75
75
|
/**
|
|
76
76
|
* Monkey-patch the fs module to download missing files from the CDN
|
|
77
77
|
*/
|
|
78
|
-
const augmentFsModule = ({ promises, staticManifest, pageRoot,
|
|
78
|
+
const augmentFsModule = ({ promises, staticManifest, pageRoot, }) => {
|
|
79
79
|
// Only do this if we have some static files moved to the CDN
|
|
80
80
|
if (staticManifest.length === 0) {
|
|
81
81
|
return;
|
|
@@ -93,22 +93,23 @@ const augmentFsModule = ({ promises, staticManifest, pageRoot, getBase, }) => {
|
|
|
93
93
|
const statsOrig = promises.stat;
|
|
94
94
|
// ...then money-patch it to see if it's requesting a CDN file
|
|
95
95
|
promises.readFile = (async (file, options) => {
|
|
96
|
-
|
|
96
|
+
// In production use the public URL (e.g. https://example.com). Otherwise use the deploy URL, e.g. https://deploy-preview-123--example.netlify.app
|
|
97
|
+
const baseUrl = process.env.CONTEXT === 'production' ? process.env.URL : process.env.DEPLOY_PRIME_URL;
|
|
97
98
|
// We only care about page files
|
|
98
99
|
if (file.startsWith(pageRoot)) {
|
|
99
|
-
// We only want the part after
|
|
100
|
+
// We only want the part after `.next/server/`
|
|
100
101
|
const filePath = file.slice(pageRoot.length + 1);
|
|
101
102
|
// Is it in the CDN and not local?
|
|
102
103
|
if (staticFiles.has(filePath) && !(0, fs_1.existsSync)(file)) {
|
|
103
104
|
// This name is safe to use, because it's one that was already created by Next
|
|
104
105
|
const cacheFile = path_1.default.join(cacheDir, filePath);
|
|
105
|
-
const url = `${
|
|
106
|
+
const url = `${baseUrl}/${staticFiles.get(filePath)}`;
|
|
106
107
|
// If it's already downloading we can wait for it to finish
|
|
107
108
|
if (downloadPromises.has(url)) {
|
|
108
109
|
await downloadPromises.get(url);
|
|
109
110
|
}
|
|
110
111
|
// Have we already cached it? We download every time if running locally to avoid staleness
|
|
111
|
-
if ((!(0, fs_1.existsSync)(cacheFile) || process.env.NETLIFY_DEV) &&
|
|
112
|
+
if ((!(0, fs_1.existsSync)(cacheFile) || process.env.NETLIFY_DEV) && baseUrl) {
|
|
112
113
|
await promises.mkdir(path_1.default.dirname(cacheFile), { recursive: true });
|
|
113
114
|
try {
|
|
114
115
|
// Append the path to our host and we can load it like a regular page
|
|
@@ -129,7 +130,7 @@ const augmentFsModule = ({ promises, staticManifest, pageRoot, getBase, }) => {
|
|
|
129
130
|
promises.stat = ((file, options) => {
|
|
130
131
|
// We only care about page files
|
|
131
132
|
if (file.startsWith(pageRoot)) {
|
|
132
|
-
// We only want the part after `
|
|
133
|
+
// We only want the part after `.next/server`
|
|
133
134
|
const cacheFile = path_1.default.join(cacheDir, file.slice(pageRoot.length + 1));
|
|
134
135
|
if ((0, fs_1.existsSync)(cacheFile)) {
|
|
135
136
|
return statsOrig(cacheFile, options);
|
package/lib/templates/ipx.js
CHANGED
|
@@ -10,4 +10,4 @@ exports.handler = (0, ipx_1.createIPXHandler)({
|
|
|
10
10
|
remotePatterns: imageconfig_json_1.remotePatterns,
|
|
11
11
|
responseHeaders: imageconfig_json_1.responseHeaders,
|
|
12
12
|
});
|
|
13
|
-
/* eslint-enable
|
|
13
|
+
/* eslint-enable import/no-unresolved, @typescript-eslint/ban-ts-comment */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/plugin-nextjs",
|
|
3
|
-
"version": "4.29.
|
|
3
|
+
"version": "4.29.3-appdir.0",
|
|
4
4
|
"description": "Run Next.js seamlessly on Netlify",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@delucis/if-env": "^1.1.2",
|
|
39
|
-
"@netlify/build": "^28.
|
|
39
|
+
"@netlify/build": "^28.4.4",
|
|
40
40
|
"@types/fs-extra": "^9.0.13",
|
|
41
41
|
"@types/jest": "^27.4.1",
|
|
42
42
|
"@types/merge-stream": "^1.1.2",
|
|
@@ -13,6 +13,12 @@ export interface FetchEventResult {
|
|
|
13
13
|
waitUntil: Promise<any>
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
export interface I18NConfig {
|
|
17
|
+
defaultLocale: string
|
|
18
|
+
localeDetection?: false
|
|
19
|
+
locales: string[]
|
|
20
|
+
}
|
|
21
|
+
|
|
16
22
|
export interface RequestData {
|
|
17
23
|
geo?: {
|
|
18
24
|
city?: string
|
|
@@ -27,7 +33,7 @@ export interface RequestData {
|
|
|
27
33
|
method: string
|
|
28
34
|
nextConfig?: {
|
|
29
35
|
basePath?: string
|
|
30
|
-
i18n?:
|
|
36
|
+
i18n?: I18NConfig | null
|
|
31
37
|
trailingSlash?: boolean
|
|
32
38
|
}
|
|
33
39
|
page?: {
|