@netlify/plugin-nextjs 5.1.2 → 5.2.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.
Files changed (42) hide show
  1. package/dist/build/advanced-api-routes.js +121 -4
  2. package/dist/build/cache.js +25 -4
  3. package/dist/build/content/prerendered.js +234 -8
  4. package/dist/build/content/server.js +259 -14
  5. package/dist/build/content/static.js +96 -11
  6. package/dist/build/functions/edge.js +511 -5
  7. package/dist/build/functions/server.js +131 -12
  8. package/dist/build/image-cdn.js +1626 -3
  9. package/dist/build/plugin-context.js +236 -5
  10. package/dist/build/templates/handler-monorepo.tmpl.js +3 -0
  11. package/dist/build/templates/handler.tmpl.js +3 -0
  12. package/dist/build/verification.js +81 -8
  13. package/dist/esm-chunks/{package-RVJOBSMH.js → package-ZBRSUKN7.js} +5 -5
  14. package/dist/index.js +25 -36
  15. package/dist/run/config.js +25 -6
  16. package/dist/run/constants.js +7 -5
  17. package/dist/run/handlers/cache.cjs +6 -567
  18. package/dist/run/handlers/request-context.cjs +8 -1
  19. package/dist/run/handlers/server.js +20 -22
  20. package/dist/run/handlers/tracing.js +1 -1
  21. package/dist/run/headers.js +198 -8
  22. package/dist/run/next.cjs +49 -567
  23. package/dist/{esm-chunks/chunk-PMRBBOBY.js → run/regional-blob-store.cjs} +117 -263
  24. package/dist/run/revalidate.js +17 -3
  25. package/dist/run/systemlog.js +94 -3
  26. package/dist/shared/blobkey.js +15 -3
  27. package/package.json +1 -1
  28. package/dist/esm-chunks/chunk-3SUDZQ7L.js +0 -40
  29. package/dist/esm-chunks/chunk-4BNHE6TP.js +0 -278
  30. package/dist/esm-chunks/chunk-72ZI2IVI.js +0 -36
  31. package/dist/esm-chunks/chunk-BG455SFE.js +0 -133
  32. package/dist/esm-chunks/chunk-HESS57SH.js +0 -127
  33. package/dist/esm-chunks/chunk-HYBEXB2Z.js +0 -105
  34. package/dist/esm-chunks/chunk-K7BTUM7O.js +0 -97
  35. package/dist/esm-chunks/chunk-L6OM53B6.js +0 -238
  36. package/dist/esm-chunks/chunk-MCEOSJH6.js +0 -1637
  37. package/dist/esm-chunks/chunk-MRD3XSKD.js +0 -248
  38. package/dist/esm-chunks/chunk-RL4K4CVH.js +0 -27
  39. package/dist/esm-chunks/chunk-TYCYFZ22.js +0 -25
  40. package/dist/esm-chunks/chunk-UTQSBE5O.js +0 -524
  41. package/dist/esm-chunks/chunk-UYKENJEU.js +0 -19
  42. package/dist/esm-chunks/chunk-V2T6NUOM.js +0 -113
@@ -51202,7 +51202,7 @@ var import_sdk_trace_node = __toESM(require_src14(), 1);
51202
51202
  var import_semantic_conventions = __toESM(require_src(), 1);
51203
51203
  var {
51204
51204
  default: { version, name }
51205
- } = await import("../../esm-chunks/package-RVJOBSMH.js");
51205
+ } = await import("../../esm-chunks/package-ZBRSUKN7.js");
51206
51206
  var sdk = new import_sdk_node.NodeSDK({
51207
51207
  resource: new import_resources.Resource({
51208
51208
  [import_semantic_conventions.SEMRESATTRS_SERVICE_NAME]: name,
@@ -4,15 +4,205 @@
4
4
  return createRequire(import.meta.url);
5
5
  })();
6
6
 
7
- import {
8
- adjustDateHeader,
9
- setCacheControlHeaders,
10
- setCacheStatusHeader,
11
- setCacheTagsHeaders,
12
- setVaryHeaders
13
- } from "../esm-chunks/chunk-PMRBBOBY.js";
14
- import "../esm-chunks/chunk-TYCYFZ22.js";
15
7
  import "../esm-chunks/chunk-5JVNISGM.js";
8
+
9
+ // src/run/headers.ts
10
+ import { encodeBlobKey } from "../shared/blobkey.js";
11
+ import { getRegionalBlobStore } from "./regional-blob-store.cjs";
12
+ var ALL_VARIATIONS = Symbol.for("ALL_VARIATIONS");
13
+ var NetlifyVaryKeys = /* @__PURE__ */ new Set(["header", "language", "cookie", "query", "country"]);
14
+ var isNetlifyVaryKey = (key) => NetlifyVaryKeys.has(key);
15
+ var generateNetlifyVaryValues = ({
16
+ header,
17
+ language,
18
+ cookie,
19
+ query,
20
+ country
21
+ }) => {
22
+ const values = [];
23
+ if (query.length !== 0) {
24
+ if (query.includes(ALL_VARIATIONS)) {
25
+ values.push(`query`);
26
+ } else {
27
+ values.push(`query=${query.join(`|`)}`);
28
+ }
29
+ }
30
+ if (header.length !== 0) {
31
+ values.push(`header=${header.join(`|`)}`);
32
+ }
33
+ if (language.length !== 0) {
34
+ values.push(`language=${language.join(`|`)}`);
35
+ }
36
+ if (cookie.length !== 0) {
37
+ values.push(`cookie=${cookie.join(`|`)}`);
38
+ }
39
+ if (country.length !== 0) {
40
+ values.push(`country=${country.join(`|`)}`);
41
+ }
42
+ return values.join(",");
43
+ };
44
+ var getHeaderValueArray = (header) => {
45
+ return header.split(",").map((value) => value.trim());
46
+ };
47
+ var omitHeaderValues = (header, values) => {
48
+ const headerValues = getHeaderValueArray(header);
49
+ const filteredValues = headerValues.filter(
50
+ (value) => !values.some((val) => value.startsWith(val))
51
+ );
52
+ return filteredValues.join(", ");
53
+ };
54
+ var mapHeaderValues = (header, callback) => {
55
+ const headerValues = getHeaderValueArray(header);
56
+ const mappedValues = headerValues.map(callback);
57
+ return mappedValues.join(", ");
58
+ };
59
+ var setVaryHeaders = (headers, request, { basePath, i18n }) => {
60
+ const netlifyVaryValues = {
61
+ header: ["x-nextjs-data"],
62
+ language: [],
63
+ cookie: ["__prerender_bypass", "__next_preview_data"],
64
+ query: [],
65
+ country: []
66
+ };
67
+ const vary = headers.get("vary");
68
+ if (vary !== null) {
69
+ netlifyVaryValues.header.push(...getHeaderValueArray(vary));
70
+ }
71
+ const path = new URL(request.url).pathname;
72
+ const locales = i18n && i18n.localeDetection !== false ? i18n.locales : [];
73
+ if (locales.length > 1 && (path === "/" || path === basePath)) {
74
+ netlifyVaryValues.language.push(...locales);
75
+ netlifyVaryValues.cookie.push(`NEXT_LOCALE`);
76
+ }
77
+ const userNetlifyVary = headers.get("netlify-vary");
78
+ if (userNetlifyVary) {
79
+ const directives = getHeaderValueArray(userNetlifyVary);
80
+ for (const directive of directives) {
81
+ const [key, value] = directive.split("=");
82
+ if (key === "query" && !value) {
83
+ netlifyVaryValues.query.push(ALL_VARIATIONS);
84
+ } else if (value && isNetlifyVaryKey(key)) {
85
+ netlifyVaryValues[key].push(...value.split("|"));
86
+ }
87
+ }
88
+ }
89
+ headers.set(`netlify-vary`, generateNetlifyVaryValues(netlifyVaryValues));
90
+ };
91
+ var adjustDateHeader = async ({
92
+ headers,
93
+ request,
94
+ span,
95
+ tracer,
96
+ requestContext
97
+ }) => {
98
+ const cacheState = headers.get("x-nextjs-cache");
99
+ const isServedFromCache = cacheState === "HIT" || cacheState === "STALE";
100
+ span.setAttributes({
101
+ "x-nextjs-cache": cacheState ?? void 0,
102
+ isServedFromCache
103
+ });
104
+ if (!isServedFromCache) {
105
+ return;
106
+ }
107
+ const key = new URL(request.url).pathname;
108
+ let lastModified;
109
+ if (requestContext.responseCacheGetLastModified) {
110
+ lastModified = requestContext.responseCacheGetLastModified;
111
+ } else {
112
+ span.recordException(
113
+ new Error("lastModified not found in requestContext, falling back to trying blobs")
114
+ );
115
+ span.setAttributes({
116
+ severity: "alert",
117
+ warning: true
118
+ });
119
+ const blobStore = getRegionalBlobStore({ consistency: "strong" });
120
+ const blobKey = await encodeBlobKey(key);
121
+ lastModified = await tracer.withActiveSpan(
122
+ "get cache to calculate date header",
123
+ async (getBlobForDateSpan) => {
124
+ getBlobForDateSpan.setAttributes({
125
+ key,
126
+ blobKey
127
+ });
128
+ const blob = await blobStore.get(blobKey, { type: "json" }) ?? {};
129
+ getBlobForDateSpan.addEvent(blob ? "Cache hit" : "Cache miss");
130
+ return blob.lastModified;
131
+ }
132
+ );
133
+ }
134
+ if (!lastModified) {
135
+ span.recordException(
136
+ new Error(
137
+ "lastModified not found in either requestContext or blobs, date header for cached response is not set"
138
+ )
139
+ );
140
+ span.setAttributes({
141
+ severity: "alert",
142
+ warning: true
143
+ });
144
+ return;
145
+ }
146
+ const lastModifiedDate = new Date(lastModified);
147
+ headers.set("x-nextjs-date", headers.get("date") ?? lastModifiedDate.toUTCString());
148
+ headers.set("date", lastModifiedDate.toUTCString());
149
+ };
150
+ var setCacheControlHeaders = (headers, request, requestContext) => {
151
+ if (typeof requestContext.routeHandlerRevalidate !== "undefined" && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control")) {
152
+ const cdnCacheControl = (
153
+ // if we are serving already stale response, instruct edge to not attempt to cache that response
154
+ headers.get("x-nextjs-cache") === "STALE" ? "public, max-age=0, must-revalidate" : `s-maxage=${requestContext.routeHandlerRevalidate === false ? 31536e3 : requestContext.routeHandlerRevalidate}, stale-while-revalidate=31536000`
155
+ );
156
+ headers.set("netlify-cdn-cache-control", cdnCacheControl);
157
+ return;
158
+ }
159
+ const cacheControl = headers.get("cache-control");
160
+ if (cacheControl !== null && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control")) {
161
+ const browserCacheControl = omitHeaderValues(cacheControl, [
162
+ "s-maxage",
163
+ "stale-while-revalidate"
164
+ ]);
165
+ const cdnCacheControl = (
166
+ // if we are serving already stale response, instruct edge to not attempt to cache that response
167
+ headers.get("x-nextjs-cache") === "STALE" ? "public, max-age=0, must-revalidate" : mapHeaderValues(
168
+ cacheControl,
169
+ (value) => value === "stale-while-revalidate" ? "stale-while-revalidate=31536000" : value
170
+ )
171
+ );
172
+ headers.set("cache-control", browserCacheControl || "public, max-age=0, must-revalidate");
173
+ headers.set("netlify-cdn-cache-control", cdnCacheControl);
174
+ return;
175
+ }
176
+ if (cacheControl === null && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control") && requestContext.usedFsRead) {
177
+ headers.set("cache-control", "public, max-age=0, must-revalidate");
178
+ headers.set("netlify-cdn-cache-control", `max-age=31536000`);
179
+ }
180
+ };
181
+ function getCanonicalPathFromCacheKey(cacheKey) {
182
+ return cacheKey === "/index" ? "/" : cacheKey;
183
+ }
184
+ var setCacheTagsHeaders = (headers, request, manifest, requestContext) => {
185
+ const path = getCanonicalPathFromCacheKey(requestContext.responseCacheKey) ?? new URL(request.url).pathname;
186
+ const tags = manifest[path];
187
+ if (tags !== void 0) {
188
+ headers.set("netlify-cache-tag", tags);
189
+ }
190
+ };
191
+ var NEXT_CACHE_TO_CACHE_STATUS = {
192
+ HIT: `hit`,
193
+ MISS: `fwd=miss`,
194
+ STALE: `hit; fwd=stale`
195
+ };
196
+ var setCacheStatusHeader = (headers) => {
197
+ const nextCache = headers.get("x-nextjs-cache");
198
+ if (typeof nextCache === "string") {
199
+ if (nextCache in NEXT_CACHE_TO_CACHE_STATUS) {
200
+ const cacheStatus = NEXT_CACHE_TO_CACHE_STATUS[nextCache];
201
+ headers.set("cache-status", `"Next.js"; ${cacheStatus}`);
202
+ }
203
+ headers.delete("x-nextjs-cache");
204
+ }
205
+ };
16
206
  export {
17
207
  adjustDateHeader,
18
208
  setCacheControlHeaders,