@netlify/plugin-nextjs 5.7.4 → 5.8.1
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/dist/build/advanced-api-routes.js +20 -5
- package/dist/build/content/prerendered.js +25 -7
- package/dist/build/content/static.js +7 -1
- package/dist/build/plugin-context.js +26 -0
- package/dist/esm-chunks/{package-5HTSLGL2.js → package-AOKLDA5E.js} +6 -5
- package/dist/run/handlers/server.js +1 -1
- package/dist/run/handlers/tracing.js +1 -1
- package/dist/run/headers.js +8 -4
- package/dist/run/next.cjs +9 -5
- package/dist/run/regional-blob-store.cjs +1 -1
- package/package.json +1 -1
|
@@ -18,23 +18,38 @@ var ApiRouteType = /* @__PURE__ */ ((ApiRouteType2) => {
|
|
|
18
18
|
return ApiRouteType2;
|
|
19
19
|
})(ApiRouteType || {});
|
|
20
20
|
async function getAPIRoutesConfigs(ctx) {
|
|
21
|
+
const uniqueApiRoutes = /* @__PURE__ */ new Set();
|
|
21
22
|
const functionsConfigManifestPath = join(
|
|
22
23
|
ctx.publishDir,
|
|
23
24
|
"server",
|
|
24
25
|
"functions-config-manifest.json"
|
|
25
26
|
);
|
|
26
|
-
if (
|
|
27
|
+
if (existsSync(functionsConfigManifestPath)) {
|
|
28
|
+
const functionsConfigManifest = JSON.parse(
|
|
29
|
+
await readFile(functionsConfigManifestPath, "utf-8")
|
|
30
|
+
);
|
|
31
|
+
for (const apiRoute of Object.keys(functionsConfigManifest.functions)) {
|
|
32
|
+
uniqueApiRoutes.add(apiRoute);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const pagesManifestPath = join(ctx.publishDir, "server", "pages-manifest.json");
|
|
36
|
+
if (existsSync(pagesManifestPath)) {
|
|
37
|
+
const pagesManifest = JSON.parse(await readFile(pagesManifestPath, "utf-8"));
|
|
38
|
+
for (const route of Object.keys(pagesManifest)) {
|
|
39
|
+
if (route.startsWith("/api/")) {
|
|
40
|
+
uniqueApiRoutes.add(route);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (uniqueApiRoutes.size === 0) {
|
|
27
45
|
return [];
|
|
28
46
|
}
|
|
29
|
-
const functionsConfigManifest = JSON.parse(
|
|
30
|
-
await readFile(functionsConfigManifestPath, "utf-8")
|
|
31
|
-
);
|
|
32
47
|
const appDir = ctx.resolveFromSiteDir(".");
|
|
33
48
|
const pagesDir = join(appDir, "pages");
|
|
34
49
|
const srcPagesDir = join(appDir, "src", "pages");
|
|
35
50
|
const { pageExtensions } = ctx.requiredServerFiles.config;
|
|
36
51
|
return Promise.all(
|
|
37
|
-
|
|
52
|
+
[...uniqueApiRoutes].map(async (apiRoute) => {
|
|
38
53
|
const filePath = getSourceFileForPage(apiRoute, [pagesDir, srcPagesDir], pageExtensions);
|
|
39
54
|
const sharedFields = {
|
|
40
55
|
apiRoute,
|
|
@@ -147,11 +147,19 @@ var writeCacheEntry = async (route, value, lastModified, ctx) => {
|
|
|
147
147
|
});
|
|
148
148
|
await writeFile(path, entry, "utf-8");
|
|
149
149
|
};
|
|
150
|
-
var routeToFilePath = (path) =>
|
|
151
|
-
|
|
150
|
+
var routeToFilePath = (path) => {
|
|
151
|
+
if (path === "/") {
|
|
152
|
+
return "/index";
|
|
153
|
+
}
|
|
154
|
+
if (path.startsWith("/")) {
|
|
155
|
+
return path;
|
|
156
|
+
}
|
|
157
|
+
return `/${path}`;
|
|
158
|
+
};
|
|
159
|
+
var buildPagesCacheValue = async (path, shouldUseEnumKind, shouldSkipJson = false) => ({
|
|
152
160
|
kind: shouldUseEnumKind ? "PAGES" : "PAGE",
|
|
153
161
|
html: await readFile(`${path}.html`, "utf-8"),
|
|
154
|
-
pageData: JSON.parse(await readFile(`${path}.json`, "utf-8")),
|
|
162
|
+
pageData: shouldSkipJson ? {} : JSON.parse(await readFile(`${path}.json`, "utf-8")),
|
|
155
163
|
headers: void 0,
|
|
156
164
|
status: void 0
|
|
157
165
|
});
|
|
@@ -203,8 +211,8 @@ var copyPrerenderedContent = async (ctx) => {
|
|
|
203
211
|
const shouldUseEnumKind = ctx.nextVersion ? (0, import_semver.satisfies)(ctx.nextVersion, ">=15.0.0-canary.114 <15.0.0-d || >15.0.0-rc.0", {
|
|
204
212
|
includePrerelease: true
|
|
205
213
|
}) : false;
|
|
206
|
-
await Promise.all(
|
|
207
|
-
Object.entries(manifest.routes).map(
|
|
214
|
+
await Promise.all([
|
|
215
|
+
...Object.entries(manifest.routes).map(
|
|
208
216
|
([route, meta]) => limitConcurrentPrerenderContentHandling(async () => {
|
|
209
217
|
const lastModified = meta.initialRevalidateSeconds ? Date.now() - 31536e6 : Date.now();
|
|
210
218
|
const key = routeToFilePath(route);
|
|
@@ -243,8 +251,18 @@ var copyPrerenderedContent = async (ctx) => {
|
|
|
243
251
|
}
|
|
244
252
|
await writeCacheEntry(key, value, lastModified, ctx);
|
|
245
253
|
})
|
|
246
|
-
)
|
|
247
|
-
|
|
254
|
+
),
|
|
255
|
+
...ctx.getFallbacks(manifest).map(async (route) => {
|
|
256
|
+
const key = routeToFilePath(route);
|
|
257
|
+
const value = await buildPagesCacheValue(
|
|
258
|
+
join(ctx.publishDir, "server/pages", key),
|
|
259
|
+
shouldUseEnumKind,
|
|
260
|
+
true
|
|
261
|
+
// there is no corresponding json file for fallback, so we are skipping it for this entry
|
|
262
|
+
);
|
|
263
|
+
await writeCacheEntry(key, value, Date.now(), ctx);
|
|
264
|
+
})
|
|
265
|
+
]);
|
|
248
266
|
if (existsSync(join(ctx.publishDir, `server/app/_not-found.html`))) {
|
|
249
267
|
const lastModified = Date.now();
|
|
250
268
|
const key = "/404";
|
|
@@ -35,13 +35,19 @@ var copyStaticContent = async (ctx) => {
|
|
|
35
35
|
cwd: srcDir,
|
|
36
36
|
extglob: true
|
|
37
37
|
});
|
|
38
|
+
const fallbacks = ctx.getFallbacks(await ctx.getPrerenderManifest());
|
|
38
39
|
try {
|
|
39
40
|
await mkdir(destDir, { recursive: true });
|
|
40
41
|
await Promise.all(
|
|
41
42
|
paths.filter((path) => !paths.includes(`${path.slice(0, -5)}.json`)).map(async (path) => {
|
|
42
43
|
const html = await readFile(join(srcDir, path), "utf-8");
|
|
43
44
|
verifyNetlifyForms(ctx, html);
|
|
44
|
-
|
|
45
|
+
const isFallback = fallbacks.includes(path.slice(0, -5));
|
|
46
|
+
await writeFile(
|
|
47
|
+
join(destDir, await encodeBlobKey(path)),
|
|
48
|
+
JSON.stringify({ html, isFallback }),
|
|
49
|
+
"utf-8"
|
|
50
|
+
);
|
|
45
51
|
})
|
|
46
52
|
);
|
|
47
53
|
} catch (error) {
|
|
@@ -266,6 +266,32 @@ var PluginContext = class {
|
|
|
266
266
|
}
|
|
267
267
|
return this.#nextVersion;
|
|
268
268
|
}
|
|
269
|
+
#fallbacks = null;
|
|
270
|
+
/**
|
|
271
|
+
* Get an array of localized fallback routes
|
|
272
|
+
*
|
|
273
|
+
* Example return value for non-i18n site: `['blog/[slug]']`
|
|
274
|
+
*
|
|
275
|
+
* Example return value for i18n site: `['en/blog/[slug]', 'fr/blog/[slug]']`
|
|
276
|
+
*/
|
|
277
|
+
getFallbacks(prerenderManifest) {
|
|
278
|
+
if (!this.#fallbacks) {
|
|
279
|
+
const locales = this.buildConfig.i18n?.locales ?? [""];
|
|
280
|
+
this.#fallbacks = Object.entries(prerenderManifest.dynamicRoutes).reduce(
|
|
281
|
+
(fallbacks, [route, meta]) => {
|
|
282
|
+
if (typeof meta.fallback === "string") {
|
|
283
|
+
for (const locale of locales) {
|
|
284
|
+
const localizedRoute = posixJoin(locale, route.replace(/^\/+/g, ""));
|
|
285
|
+
fallbacks.push(localizedRoute);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return fallbacks;
|
|
289
|
+
},
|
|
290
|
+
[]
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
return this.#fallbacks;
|
|
294
|
+
}
|
|
269
295
|
/** Fails a build with a message and an optional error */
|
|
270
296
|
failBuild(message, error) {
|
|
271
297
|
return this.utils.build.failBuild(message, error instanceof Error ? { error } : void 0);
|
|
@@ -8,7 +8,7 @@ import "./chunk-OEQOKJGE.js";
|
|
|
8
8
|
|
|
9
9
|
// package.json
|
|
10
10
|
var name = "@netlify/plugin-nextjs";
|
|
11
|
-
var version = "5.
|
|
11
|
+
var version = "5.8.1";
|
|
12
12
|
var description = "Run Next.js seamlessly on Netlify";
|
|
13
13
|
var main = "./dist/index.js";
|
|
14
14
|
var type = "module";
|
|
@@ -57,14 +57,14 @@ var bugs = {
|
|
|
57
57
|
var homepage = "https://github.com/netlify/next-runtime#readme";
|
|
58
58
|
var devDependencies = {
|
|
59
59
|
"@fastly/http-compute-js": "1.1.4",
|
|
60
|
-
"@netlify/blobs": "^8.0
|
|
61
|
-
"@netlify/build": "^29.
|
|
60
|
+
"@netlify/blobs": "^8.1.0",
|
|
61
|
+
"@netlify/build": "^29.55.3",
|
|
62
62
|
"@netlify/edge-bundler": "^12.2.3",
|
|
63
63
|
"@netlify/edge-functions": "^2.11.0",
|
|
64
64
|
"@netlify/eslint-config-node": "^7.0.1",
|
|
65
65
|
"@netlify/functions": "^2.8.2",
|
|
66
|
-
"@netlify/serverless-functions-api": "^1.
|
|
67
|
-
"@netlify/zip-it-and-ship-it": "^9.
|
|
66
|
+
"@netlify/serverless-functions-api": "^1.30.1",
|
|
67
|
+
"@netlify/zip-it-and-ship-it": "^9.41.0",
|
|
68
68
|
"@opentelemetry/api": "^1.8.0",
|
|
69
69
|
"@opentelemetry/exporter-trace-otlp-http": "^0.51.0",
|
|
70
70
|
"@opentelemetry/resources": "^1.24.0",
|
|
@@ -87,6 +87,7 @@ var devDependencies = {
|
|
|
87
87
|
memfs: "^4.9.2",
|
|
88
88
|
"mock-require": "^3.0.3",
|
|
89
89
|
msw: "^2.0.7",
|
|
90
|
+
"netlify-cli": "^17.37.1",
|
|
90
91
|
next: "^15.0.0-canary.28",
|
|
91
92
|
os: "^0.1.2",
|
|
92
93
|
outdent: "^0.8.0",
|
|
@@ -3161,7 +3161,7 @@ var server_default = async (request, context) => {
|
|
|
3161
3161
|
span.setAttribute("responseCacheKey", requestContext.responseCacheKey);
|
|
3162
3162
|
}
|
|
3163
3163
|
await adjustDateHeader({ headers: response.headers, request, span, tracer, requestContext });
|
|
3164
|
-
setCacheControlHeaders(response
|
|
3164
|
+
setCacheControlHeaders(response, request, requestContext);
|
|
3165
3165
|
setCacheTagsHeaders(response.headers, requestContext);
|
|
3166
3166
|
setVaryHeaders(response.headers, request, nextConfig);
|
|
3167
3167
|
setCacheStatusHeader(response.headers);
|
|
@@ -68866,7 +68866,7 @@ var import_semantic_conventions = __toESM(require_src(), 1);
|
|
|
68866
68866
|
import { getLogger } from "./request-context.cjs";
|
|
68867
68867
|
var {
|
|
68868
68868
|
default: { version, name }
|
|
68869
|
-
} = await import("../../esm-chunks/package-
|
|
68869
|
+
} = await import("../../esm-chunks/package-AOKLDA5E.js");
|
|
68870
68870
|
var sdk = new import_sdk_node.NodeSDK({
|
|
68871
68871
|
resource: new import_resources.Resource({
|
|
68872
68872
|
[import_semantic_conventions.SEMRESATTRS_SERVICE_NAME]: name,
|
package/dist/run/headers.js
CHANGED
|
@@ -42,7 +42,7 @@ var generateNetlifyVaryValues = ({
|
|
|
42
42
|
return values.join(",");
|
|
43
43
|
};
|
|
44
44
|
var getHeaderValueArray = (header) => {
|
|
45
|
-
return header.split(",").map((value) => value.trim());
|
|
45
|
+
return header.split(",").map((value) => value.trim()).filter(Boolean);
|
|
46
46
|
};
|
|
47
47
|
var omitHeaderValues = (header, values) => {
|
|
48
48
|
const headerValues = getHeaderValueArray(header);
|
|
@@ -142,7 +142,7 @@ var adjustDateHeader = async ({
|
|
|
142
142
|
headers.set("x-nextjs-date", headers.get("date") ?? lastModifiedDate.toUTCString());
|
|
143
143
|
headers.set("date", lastModifiedDate.toUTCString());
|
|
144
144
|
};
|
|
145
|
-
var setCacheControlHeaders = (headers, request, requestContext) => {
|
|
145
|
+
var setCacheControlHeaders = ({ headers, status }, request, requestContext) => {
|
|
146
146
|
if (typeof requestContext.routeHandlerRevalidate !== "undefined" && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control")) {
|
|
147
147
|
const cdnCacheControl = (
|
|
148
148
|
// if we are serving already stale response, instruct edge to not attempt to cache that response
|
|
@@ -151,6 +151,10 @@ var setCacheControlHeaders = (headers, request, requestContext) => {
|
|
|
151
151
|
headers.set("netlify-cdn-cache-control", cdnCacheControl);
|
|
152
152
|
return;
|
|
153
153
|
}
|
|
154
|
+
if (status === 404 && request.url.endsWith(".php")) {
|
|
155
|
+
headers.set("cache-control", "public, max-age=0, must-revalidate");
|
|
156
|
+
headers.set("netlify-cdn-cache-control", `max-age=31536000, durable`);
|
|
157
|
+
}
|
|
154
158
|
const cacheControl = headers.get("cache-control");
|
|
155
159
|
if (cacheControl !== null && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control")) {
|
|
156
160
|
const browserCacheControl = omitHeaderValues(cacheControl, [
|
|
@@ -170,13 +174,13 @@ var setCacheControlHeaders = (headers, request, requestContext) => {
|
|
|
170
174
|
headers.set("netlify-cdn-cache-control", cdnCacheControl);
|
|
171
175
|
return;
|
|
172
176
|
}
|
|
173
|
-
if (cacheControl === null && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control") && requestContext.
|
|
177
|
+
if (cacheControl === null && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control") && requestContext.usedFsReadForNonFallback) {
|
|
174
178
|
headers.set("cache-control", "public, max-age=0, must-revalidate");
|
|
175
179
|
headers.set("netlify-cdn-cache-control", `max-age=31536000, durable`);
|
|
176
180
|
}
|
|
177
181
|
};
|
|
178
182
|
var setCacheTagsHeaders = (headers, requestContext) => {
|
|
179
|
-
if (requestContext.responseCacheTags) {
|
|
183
|
+
if (requestContext.responseCacheTags && (headers.has("cache-control") || headers.has("netlify-cdn-cache-control"))) {
|
|
180
184
|
headers.set("netlify-cache-tag", requestContext.responseCacheTags.join(","));
|
|
181
185
|
}
|
|
182
186
|
};
|
package/dist/run/next.cjs
CHANGED
|
@@ -554,13 +554,17 @@ async function getMockedRequestHandlers(...args) {
|
|
|
554
554
|
if (typeof path === "string" && path.endsWith(".html")) {
|
|
555
555
|
const store = (0, import_regional_blob_store.getRegionalBlobStore)();
|
|
556
556
|
const relPath = (0, import_path.relative)((0, import_path.resolve)(".next/server/pages"), path);
|
|
557
|
-
const file = await store.get(await encodeBlobKey(relPath)
|
|
557
|
+
const file = await store.get(await encodeBlobKey(relPath), {
|
|
558
|
+
type: "json"
|
|
559
|
+
});
|
|
558
560
|
if (file !== null) {
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
requestContext
|
|
561
|
+
if (!file.isFallback) {
|
|
562
|
+
const requestContext = (0, import_request_context.getRequestContext)();
|
|
563
|
+
if (requestContext) {
|
|
564
|
+
requestContext.usedFsReadForNonFallback = true;
|
|
565
|
+
}
|
|
562
566
|
}
|
|
563
|
-
return file;
|
|
567
|
+
return file.html;
|
|
564
568
|
}
|
|
565
569
|
}
|
|
566
570
|
throw error;
|
|
@@ -601,7 +601,7 @@ var getDeployStore = (input = {}) => {
|
|
|
601
601
|
if (clientOptions.edgeURL || clientOptions.uncachedEdgeURL) {
|
|
602
602
|
if (!context.primaryRegion) {
|
|
603
603
|
throw new Error(
|
|
604
|
-
"When accessing a deploy store, the Netlify Blobs client needs to be configured with a region, and one was not found in the environment. To manually set the region, set the `region` property in the `getDeployStore` options."
|
|
604
|
+
"When accessing a deploy store, the Netlify Blobs client needs to be configured with a region, and one was not found in the environment. To manually set the region, set the `region` property in the `getDeployStore` options. If you are using the Netlify CLI, you may have an outdated version; run `npm install -g netlify-cli@latest` to update and try again."
|
|
605
605
|
);
|
|
606
606
|
}
|
|
607
607
|
clientOptions.region = context.primaryRegion;
|