@netlify/plugin-nextjs 5.0.0-rc.5 → 5.0.0-rc.6

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.
@@ -7,7 +7,7 @@
7
7
  import {
8
8
  copyFetchContent,
9
9
  copyPrerenderedContent
10
- } from "../../esm-chunks/chunk-VSH4JS2L.js";
10
+ } from "../../esm-chunks/chunk-75UGFPYW.js";
11
11
  import "../../esm-chunks/chunk-VZNKO4OO.js";
12
12
  import "../../esm-chunks/chunk-TYCYFZ22.js";
13
13
  import "../../esm-chunks/chunk-5JVNISGM.js";
@@ -1,4 +1,9 @@
1
- import tracing, { trace } from '{{cwd}}/.netlify/dist/run/handlers/tracing.js'
1
+ import {
2
+ createRequestContext,
3
+ runWithRequestContext,
4
+ } from '{{cwd}}/.netlify/dist/run/handlers/request-context.cjs'
5
+ import { getTracer } from '{{cwd}}/.netlify/dist/run/handlers/tracer.cjs'
6
+ import tracing from '{{cwd}}/.netlify/dist/run/handlers/tracing.js'
2
7
 
3
8
  process.chdir('{{cwd}}')
4
9
 
@@ -8,10 +13,13 @@ export default async function (req, context) {
8
13
  tracing.start()
9
14
  }
10
15
 
11
- /** @type {import('@opentelemetry/api').Tracer} */
12
- const tracer = trace.getTracer('Next.js Runtime')
13
- return tracer.startActiveSpan('Next.js Server Handler', async (span) => {
14
- try {
16
+ const requestContext = createRequestContext(
17
+ req.headers.get('x-nf-debug-logging') || req.headers.get('x-next-debug-logging'),
18
+ )
19
+ const tracer = getTracer()
20
+
21
+ const handlerResponse = await runWithRequestContext(requestContext, () => {
22
+ return tracer.withActiveSpan('Next.js Server Handler', async (span) => {
15
23
  span.setAttributes({
16
24
  'account.id': context.account.id,
17
25
  'deploy.id': context.deploy.id,
@@ -31,16 +39,14 @@ export default async function (req, context) {
31
39
  'http.status_code': response.status,
32
40
  })
33
41
  return response
34
- } catch (error) {
35
- span.recordException(error)
36
- if (error instanceof Error) {
37
- span.addEvent({ name: error.name, message: error.message })
38
- }
39
- throw error
40
- } finally {
41
- span.end()
42
- }
42
+ })
43
43
  })
44
+
45
+ if (requestContext.serverTiming) {
46
+ handlerResponse.headers.set('server-timing', requestContext.serverTiming)
47
+ }
48
+
49
+ return handlerResponse
44
50
  }
45
51
 
46
52
  export const config = {
@@ -1,15 +1,22 @@
1
+ import {
2
+ createRequestContext,
3
+ runWithRequestContext,
4
+ } from './.netlify/dist/run/handlers/request-context.cjs'
1
5
  import serverHandler from './.netlify/dist/run/handlers/server.js'
2
- import tracing, { trace } from './.netlify/dist/run/handlers/tracing.js'
6
+ import { getTracer } from './.netlify/dist/run/handlers/tracer.cjs'
7
+ import tracing from './.netlify/dist/run/handlers/tracing.js'
3
8
 
4
9
  export default async function handler(req, context) {
5
10
  if (process.env.NETLIFY_OTLP_TRACE_EXPORTER_URL) {
6
11
  tracing.start()
7
12
  }
13
+ const requestContext = createRequestContext(
14
+ req.headers.get('x-nf-debug-logging') || req.headers.get('x-next-debug-logging'),
15
+ )
16
+ const tracer = getTracer()
8
17
 
9
- /** @type {import('@opentelemetry/api').Tracer} */
10
- const tracer = trace.getTracer('Next.js Runtime')
11
- return tracer.startActiveSpan('Next.js Server Handler', async (span) => {
12
- try {
18
+ const handlerResponse = await runWithRequestContext(requestContext, () => {
19
+ return tracer.withActiveSpan('Next.js Server Handler', async (span) => {
13
20
  span.setAttributes({
14
21
  'account.id': context.account.id,
15
22
  'deploy.id': context.deploy.id,
@@ -25,16 +32,14 @@ export default async function handler(req, context) {
25
32
  'http.status_code': response.status,
26
33
  })
27
34
  return response
28
- } catch (error) {
29
- span.recordException(error)
30
- if (error instanceof Error) {
31
- span.addEvent({ name: error.name, message: error.message })
32
- }
33
- throw error
34
- } finally {
35
- span.end()
36
- }
35
+ })
37
36
  })
37
+
38
+ if (requestContext.serverTiming) {
39
+ handlerResponse.headers.set('server-timing', requestContext.serverTiming)
40
+ }
41
+
42
+ return handlerResponse
38
43
  }
39
44
 
40
45
  export const config = {
@@ -0,0 +1,233 @@
1
+
2
+ var require = await (async () => {
3
+ var { createRequire } = await import("node:module");
4
+ return createRequire(import.meta.url);
5
+ })();
6
+
7
+ import {
8
+ require_out
9
+ } from "./chunk-VZNKO4OO.js";
10
+ import {
11
+ encodeBlobKey
12
+ } from "./chunk-TYCYFZ22.js";
13
+ import {
14
+ __toESM
15
+ } from "./chunk-5JVNISGM.js";
16
+
17
+ // src/build/content/prerendered.ts
18
+ var import_fast_glob = __toESM(require_out(), 1);
19
+ import { existsSync } from "node:fs";
20
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
21
+ import { join } from "node:path";
22
+
23
+ // node_modules/yocto-queue/index.js
24
+ var Node = class {
25
+ value;
26
+ next;
27
+ constructor(value) {
28
+ this.value = value;
29
+ }
30
+ };
31
+ var Queue = class {
32
+ #head;
33
+ #tail;
34
+ #size;
35
+ constructor() {
36
+ this.clear();
37
+ }
38
+ enqueue(value) {
39
+ const node = new Node(value);
40
+ if (this.#head) {
41
+ this.#tail.next = node;
42
+ this.#tail = node;
43
+ } else {
44
+ this.#head = node;
45
+ this.#tail = node;
46
+ }
47
+ this.#size++;
48
+ }
49
+ dequeue() {
50
+ const current = this.#head;
51
+ if (!current) {
52
+ return;
53
+ }
54
+ this.#head = this.#head.next;
55
+ this.#size--;
56
+ return current.value;
57
+ }
58
+ clear() {
59
+ this.#head = void 0;
60
+ this.#tail = void 0;
61
+ this.#size = 0;
62
+ }
63
+ get size() {
64
+ return this.#size;
65
+ }
66
+ *[Symbol.iterator]() {
67
+ let current = this.#head;
68
+ while (current) {
69
+ yield current.value;
70
+ current = current.next;
71
+ }
72
+ }
73
+ };
74
+
75
+ // node_modules/p-limit/index.js
76
+ function pLimit(concurrency) {
77
+ if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
78
+ throw new TypeError("Expected `concurrency` to be a number from 1 and up");
79
+ }
80
+ const queue = new Queue();
81
+ let activeCount = 0;
82
+ const next = () => {
83
+ activeCount--;
84
+ if (queue.size > 0) {
85
+ queue.dequeue()();
86
+ }
87
+ };
88
+ const run = async (fn, resolve, args) => {
89
+ activeCount++;
90
+ const result = (async () => fn(...args))();
91
+ resolve(result);
92
+ try {
93
+ await result;
94
+ } catch {
95
+ }
96
+ next();
97
+ };
98
+ const enqueue = (fn, resolve, args) => {
99
+ queue.enqueue(run.bind(void 0, fn, resolve, args));
100
+ (async () => {
101
+ await Promise.resolve();
102
+ if (activeCount < concurrency && queue.size > 0) {
103
+ queue.dequeue()();
104
+ }
105
+ })();
106
+ };
107
+ const generator = (fn, ...args) => new Promise((resolve) => {
108
+ enqueue(fn, resolve, args);
109
+ });
110
+ Object.defineProperties(generator, {
111
+ activeCount: {
112
+ get: () => activeCount
113
+ },
114
+ pendingCount: {
115
+ get: () => queue.size
116
+ },
117
+ clearQueue: {
118
+ value: () => {
119
+ queue.clear();
120
+ }
121
+ }
122
+ });
123
+ return generator;
124
+ }
125
+
126
+ // src/build/content/prerendered.ts
127
+ var writeCacheEntry = async (route, value, lastModified, ctx) => {
128
+ const path = join(ctx.blobDir, await encodeBlobKey(route));
129
+ const entry = JSON.stringify({
130
+ lastModified,
131
+ value
132
+ });
133
+ await writeFile(path, entry, "utf-8");
134
+ };
135
+ var routeToFilePath = (path) => path === "/" ? "/index" : path;
136
+ var buildPagesCacheValue = async (path) => ({
137
+ kind: "PAGE",
138
+ html: await readFile(`${path}.html`, "utf-8"),
139
+ pageData: JSON.parse(await readFile(`${path}.json`, "utf-8")),
140
+ postponed: void 0,
141
+ headers: void 0,
142
+ status: void 0
143
+ });
144
+ var buildAppCacheValue = async (path) => {
145
+ const meta = JSON.parse(await readFile(`${path}.meta`, "utf-8"));
146
+ const rsc = await readFile(`${path}.rsc`, "utf-8").catch(
147
+ () => readFile(`${path}.prefetch.rsc`, "utf-8")
148
+ );
149
+ if (!meta.status && rsc.includes("NEXT_NOT_FOUND")) {
150
+ meta.status = 404;
151
+ }
152
+ return {
153
+ kind: "PAGE",
154
+ html: await readFile(`${path}.html`, "utf-8"),
155
+ pageData: rsc,
156
+ ...meta
157
+ };
158
+ };
159
+ var buildRouteCacheValue = async (path) => ({
160
+ kind: "ROUTE",
161
+ body: await readFile(`${path}.body`, "base64"),
162
+ ...JSON.parse(await readFile(`${path}.meta`, "utf-8"))
163
+ });
164
+ var buildFetchCacheValue = async (path) => ({
165
+ kind: "FETCH",
166
+ ...JSON.parse(await readFile(path, "utf-8"))
167
+ });
168
+ var copyPrerenderedContent = async (ctx) => {
169
+ try {
170
+ await mkdir(ctx.blobDir, { recursive: true });
171
+ const manifest = await ctx.getPrerenderManifest();
172
+ const limitConcurrentPrerenderContentHandling = pLimit(10);
173
+ await Promise.all(
174
+ Object.entries(manifest.routes).map(
175
+ ([route, meta]) => limitConcurrentPrerenderContentHandling(async () => {
176
+ const lastModified = meta.initialRevalidateSeconds ? Date.now() - 31536e6 : Date.now();
177
+ const key = routeToFilePath(route);
178
+ let value;
179
+ switch (true) {
180
+ case (meta.dataRoute?.endsWith("/default.rsc") && !existsSync(join(ctx.publishDir, "server/app", `${key}.html`))):
181
+ return;
182
+ case meta.dataRoute?.endsWith(".json"):
183
+ if (manifest.notFoundRoutes.includes(route)) {
184
+ return;
185
+ }
186
+ value = await buildPagesCacheValue(join(ctx.publishDir, "server/pages", key));
187
+ break;
188
+ case meta.dataRoute?.endsWith(".rsc"):
189
+ value = await buildAppCacheValue(join(ctx.publishDir, "server/app", key));
190
+ break;
191
+ case meta.dataRoute === null:
192
+ value = await buildRouteCacheValue(join(ctx.publishDir, "server/app", key));
193
+ break;
194
+ default:
195
+ throw new Error(`Unrecognized content: ${route}`);
196
+ }
197
+ await writeCacheEntry(key, value, lastModified, ctx);
198
+ })
199
+ )
200
+ );
201
+ if (existsSync(join(ctx.publishDir, `server/app/_not-found.html`))) {
202
+ const lastModified = Date.now();
203
+ const key = "/404";
204
+ const value = await buildAppCacheValue(join(ctx.publishDir, "server/app/_not-found"));
205
+ await writeCacheEntry(key, value, lastModified, ctx);
206
+ }
207
+ } catch (error) {
208
+ ctx.failBuild("Failed assembling prerendered content for upload", error);
209
+ }
210
+ };
211
+ var copyFetchContent = async (ctx) => {
212
+ try {
213
+ const paths = await (0, import_fast_glob.glob)(["!(*.*)"], {
214
+ cwd: join(ctx.publishDir, "cache/fetch-cache"),
215
+ extglob: true
216
+ });
217
+ await Promise.all(
218
+ paths.map(async (key) => {
219
+ const lastModified = Date.now() - 31536e6;
220
+ const path = join(ctx.publishDir, "cache/fetch-cache", key);
221
+ const value = await buildFetchCacheValue(path);
222
+ await writeCacheEntry(key, value, lastModified, ctx);
223
+ })
224
+ );
225
+ } catch (error) {
226
+ ctx.failBuild("Failed assembling fetch content for upload", error);
227
+ }
228
+ };
229
+
230
+ export {
231
+ copyPrerenderedContent,
232
+ copyFetchContent
233
+ };
@@ -617,7 +617,7 @@ var adjustDateHeader = async ({
617
617
  });
618
618
  const blobKey = await encodeBlobKey(key);
619
619
  const blobStore = getDeployStore({ fetch: fetchBeforeNextPatchedIt, consistency: "strong" });
620
- lastModified = await tracer.startActiveSpan(
620
+ lastModified = await tracer.withActiveSpan(
621
621
  "get cache to calculate date header",
622
622
  async (getBlobForDateSpan) => {
623
623
  getBlobForDateSpan.setAttributes({
@@ -626,7 +626,6 @@ var adjustDateHeader = async ({
626
626
  });
627
627
  const blob = await blobStore.get(blobKey, { type: "json" }) ?? {};
628
628
  getBlobForDateSpan.addEvent(blob ? "Cache hit" : "Cache miss");
629
- getBlobForDateSpan.end();
630
629
  return blob.lastModified;
631
630
  }
632
631
  );
@@ -8,7 +8,7 @@ import "./chunk-5JVNISGM.js";
8
8
 
9
9
  // package.json
10
10
  var name = "@netlify/plugin-nextjs";
11
- var version = "5.0.0-rc.5";
11
+ var version = "5.0.0-rc.6";
12
12
  var description = "Run Next.js seamlessly on Netlify";
13
13
  var main = "./dist/index.js";
14
14
  var type = "module";
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  import {
8
8
  copyPrerenderedContent
9
- } from "./esm-chunks/chunk-VSH4JS2L.js";
9
+ } from "./esm-chunks/chunk-75UGFPYW.js";
10
10
  import {
11
11
  copyStaticAssets,
12
12
  copyStaticContent,