@netlify/plugin-nextjs 5.0.0-beta.8 → 5.0.0-beta.9
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/README.md +23 -0
- package/dist/build/cache.js +1 -1
- package/dist/build/content/prerendered.js +2 -1
- package/dist/build/content/server.js +2 -1
- package/dist/build/functions/edge.js +2 -3
- package/dist/build/functions/server.js +4 -4
- package/dist/build/image-cdn.js +1 -1
- package/dist/build/plugin-context.js +1 -2
- package/dist/build/templates/handler-monorepo.tmpl.js +33 -30
- package/dist/build/templates/handler.tmpl.js +31 -25
- package/dist/esm-chunks/{chunk-YMFYCTRI.js → chunk-4J4A5OE2.js} +23 -3
- package/dist/esm-chunks/{chunk-XFDUV7DP.js → chunk-67EWAGDQ.js} +29 -20
- package/dist/esm-chunks/chunk-72ZI2IVI.js +36 -0
- package/dist/esm-chunks/{chunk-N23TUUXK.js → chunk-AU7XDLZH.js} +58 -26
- package/dist/esm-chunks/{chunk-IZ2AVCVF.js → chunk-DWC6JSN7.js} +48 -24
- package/dist/esm-chunks/{chunk-XIP2W57K.js → chunk-NL5YH5N6.js} +5 -4
- package/dist/esm-chunks/{chunk-WSPFUAK4.js → chunk-T6AZTXZF.js} +6 -6
- package/dist/esm-chunks/{chunk-EPSI5TTB.js → chunk-TOK7TKP3.js} +1 -1
- package/dist/esm-chunks/{chunk-K233JI4O.js → chunk-UYKENJEU.js} +4 -2
- package/dist/esm-chunks/{chunk-ETPYUOBQ.js → chunk-YIE34LVX.js} +5 -5
- package/dist/esm-chunks/{package-2CI3IXK3.js → package-6DFWHFJA.js} +8 -6
- package/dist/index.js +12 -13
- package/dist/run/config.js +2 -2
- package/dist/run/constants.js +5 -3
- package/dist/run/handlers/cache.cjs +155 -79
- package/dist/run/handlers/request-context.cjs +56 -0
- package/dist/run/handlers/server.js +30 -16
- package/dist/run/handlers/tracing.js +1 -1
- package/dist/run/headers.js +3 -3
- package/edge-runtime/lib/response.ts +24 -20
- package/edge-runtime/lib/util.ts +6 -1
- package/package.json +1 -1
- package/dist/esm-chunks/chunk-XA2CZH5Y.js +0 -32
package/README.md
CHANGED
|
@@ -3,6 +3,29 @@
|
|
|
3
3
|
Next.js is supported natively on Netlify, and in most cases you will not need to install or
|
|
4
4
|
configure anything. This repo includes the packages used to support Next.js on Netlify.
|
|
5
5
|
|
|
6
|
+
## Lambda Folder structure:
|
|
7
|
+
|
|
8
|
+
For a simple next.js app
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
/___netlify-server-handler
|
|
12
|
+
├── .netlify
|
|
13
|
+
│ ├── tags-manifest.json
|
|
14
|
+
│ └── dist // the compiled runtime code
|
|
15
|
+
│ └── run
|
|
16
|
+
│ ├── handlers
|
|
17
|
+
│ │ ├── server.js
|
|
18
|
+
│ │ └── cache.cjs
|
|
19
|
+
│ └── next.cjs
|
|
20
|
+
├── .next // or distDir name from the next.config.js
|
|
21
|
+
│ └── // content from standalone
|
|
22
|
+
├── run-config.json // the config object from the required-server-files.json
|
|
23
|
+
├── node_modules
|
|
24
|
+
├── ___netlify-server-handler.json
|
|
25
|
+
├── ___netlify-server-handler.mjs
|
|
26
|
+
└── package.json
|
|
27
|
+
```
|
|
28
|
+
|
|
6
29
|
## Testing
|
|
7
30
|
|
|
8
31
|
### Integration testing
|
package/dist/build/cache.js
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
import {
|
|
8
8
|
copyFetchContent,
|
|
9
9
|
copyPrerenderedContent
|
|
10
|
-
} from "../../esm-chunks/chunk-
|
|
10
|
+
} from "../../esm-chunks/chunk-67EWAGDQ.js";
|
|
11
11
|
import "../../esm-chunks/chunk-VZNKO4OO.js";
|
|
12
|
+
import "../../esm-chunks/chunk-TYCYFZ22.js";
|
|
12
13
|
import "../../esm-chunks/chunk-5JVNISGM.js";
|
|
13
14
|
export {
|
|
14
15
|
copyFetchContent,
|
|
@@ -8,8 +8,9 @@ import {
|
|
|
8
8
|
copyNextDependencies,
|
|
9
9
|
copyNextServerCode,
|
|
10
10
|
writeTagsManifest
|
|
11
|
-
} from "../../esm-chunks/chunk-
|
|
11
|
+
} from "../../esm-chunks/chunk-4J4A5OE2.js";
|
|
12
12
|
import "../../esm-chunks/chunk-VZNKO4OO.js";
|
|
13
|
+
import "../../esm-chunks/chunk-UYKENJEU.js";
|
|
13
14
|
import "../../esm-chunks/chunk-5JVNISGM.js";
|
|
14
15
|
export {
|
|
15
16
|
copyNextDependencies,
|
|
@@ -6,10 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
createEdgeHandlers
|
|
9
|
-
} from "../../esm-chunks/chunk-
|
|
10
|
-
import "../../esm-chunks/chunk-IZ2AVCVF.js";
|
|
9
|
+
} from "../../esm-chunks/chunk-YIE34LVX.js";
|
|
11
10
|
import "../../esm-chunks/chunk-VZNKO4OO.js";
|
|
12
|
-
import "../../esm-chunks/chunk-
|
|
11
|
+
import "../../esm-chunks/chunk-DWC6JSN7.js";
|
|
13
12
|
import "../../esm-chunks/chunk-5JVNISGM.js";
|
|
14
13
|
export {
|
|
15
14
|
createEdgeHandlers
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
createServerHandler
|
|
9
|
-
} from "../../esm-chunks/chunk-
|
|
10
|
-
import "../../esm-chunks/chunk-
|
|
11
|
-
import "../../esm-chunks/chunk-IZ2AVCVF.js";
|
|
9
|
+
} from "../../esm-chunks/chunk-T6AZTXZF.js";
|
|
10
|
+
import "../../esm-chunks/chunk-4J4A5OE2.js";
|
|
12
11
|
import "../../esm-chunks/chunk-VZNKO4OO.js";
|
|
13
|
-
import "../../esm-chunks/chunk-
|
|
12
|
+
import "../../esm-chunks/chunk-DWC6JSN7.js";
|
|
13
|
+
import "../../esm-chunks/chunk-UYKENJEU.js";
|
|
14
14
|
import "../../esm-chunks/chunk-5JVNISGM.js";
|
|
15
15
|
export {
|
|
16
16
|
createServerHandler
|
package/dist/build/image-cdn.js
CHANGED
|
@@ -8,8 +8,7 @@ import {
|
|
|
8
8
|
EDGE_HANDLER_NAME,
|
|
9
9
|
PluginContext,
|
|
10
10
|
SERVER_HANDLER_NAME
|
|
11
|
-
} from "../esm-chunks/chunk-
|
|
12
|
-
import "../esm-chunks/chunk-TYCYFZ22.js";
|
|
11
|
+
} from "../esm-chunks/chunk-DWC6JSN7.js";
|
|
13
12
|
import "../esm-chunks/chunk-5JVNISGM.js";
|
|
14
13
|
export {
|
|
15
14
|
EDGE_HANDLER_NAME,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import tracing, { trace } from '{{cwd}}/dist/run/handlers/tracing.js'
|
|
1
|
+
import tracing, { trace } from '{{cwd}}/.netlify/dist/run/handlers/tracing.js'
|
|
2
2
|
|
|
3
3
|
process.chdir('{{cwd}}')
|
|
4
4
|
|
|
@@ -8,36 +8,39 @@ export default async function (req, context) {
|
|
|
8
8
|
tracing.start()
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
const response = await cachedHandler(req, context)
|
|
30
|
-
span.setAttributes({
|
|
31
|
-
'http.status_code': response.status,
|
|
32
|
-
})
|
|
33
|
-
return response
|
|
34
|
-
} catch (error) {
|
|
35
|
-
span.recordException(error)
|
|
36
|
-
throw error
|
|
37
|
-
} finally {
|
|
38
|
-
span.end()
|
|
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 {
|
|
15
|
+
span.setAttributes({
|
|
16
|
+
'account.id': context.account.id,
|
|
17
|
+
'deploy.id': context.deploy.id,
|
|
18
|
+
'request.id': context.requestId,
|
|
19
|
+
'site.id': context.site.id,
|
|
20
|
+
'http.method': req.method,
|
|
21
|
+
'http.target': req.url,
|
|
22
|
+
monorepo: true,
|
|
23
|
+
cwd: '{{cwd}}',
|
|
24
|
+
})
|
|
25
|
+
if (!cachedHandler) {
|
|
26
|
+
const { default: handler } = await import('{{nextServerHandler}}')
|
|
27
|
+
cachedHandler = handler
|
|
39
28
|
}
|
|
40
|
-
|
|
29
|
+
const response = await cachedHandler(req, context)
|
|
30
|
+
span.setAttributes({
|
|
31
|
+
'http.status_code': response.status,
|
|
32
|
+
})
|
|
33
|
+
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
|
+
}
|
|
43
|
+
})
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
export const config = {
|
|
@@ -1,34 +1,40 @@
|
|
|
1
|
-
import serverHandler from '
|
|
2
|
-
import tracing, { trace } from '
|
|
1
|
+
import serverHandler from './.netlify/dist/run/handlers/server.js'
|
|
2
|
+
import tracing, { trace } from './.netlify/dist/run/handlers/tracing.js'
|
|
3
3
|
|
|
4
4
|
export default async function handler(req, context) {
|
|
5
5
|
if (process.env.NETLIFY_OTLP_TRACE_EXPORTER_URL) {
|
|
6
6
|
tracing.start()
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
8
|
+
|
|
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 {
|
|
13
|
+
span.setAttributes({
|
|
14
|
+
'account.id': context.account.id,
|
|
15
|
+
'deploy.id': context.deploy.id,
|
|
16
|
+
'request.id': context.requestId,
|
|
17
|
+
'site.id': context.site.id,
|
|
18
|
+
'http.method': req.method,
|
|
19
|
+
'http.target': req.url,
|
|
20
|
+
monorepo: false,
|
|
21
|
+
cwd: process.cwd(),
|
|
22
|
+
})
|
|
23
|
+
const response = await serverHandler(req, context)
|
|
24
|
+
span.setAttributes({
|
|
25
|
+
'http.status_code': response.status,
|
|
26
|
+
})
|
|
27
|
+
return response
|
|
28
|
+
} catch (error) {
|
|
29
|
+
span.recordException(error)
|
|
30
|
+
if (error instanceof Error) {
|
|
31
|
+
span.addEvent({ name: error.name, message: error.message })
|
|
30
32
|
}
|
|
31
|
-
|
|
33
|
+
throw error
|
|
34
|
+
} finally {
|
|
35
|
+
span.end()
|
|
36
|
+
}
|
|
37
|
+
})
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
export const config = {
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
import {
|
|
8
8
|
require_out
|
|
9
9
|
} from "./chunk-VZNKO4OO.js";
|
|
10
|
+
import {
|
|
11
|
+
RUN_CONFIG
|
|
12
|
+
} from "./chunk-UYKENJEU.js";
|
|
10
13
|
import {
|
|
11
14
|
__toESM
|
|
12
15
|
} from "./chunk-5JVNISGM.js";
|
|
@@ -18,8 +21,25 @@ import { cp, mkdir, readFile, readdir, readlink, symlink, writeFile } from "node
|
|
|
18
21
|
import { createRequire } from "node:module";
|
|
19
22
|
import { dirname, join, resolve } from "node:path";
|
|
20
23
|
var copyNextServerCode = async (ctx) => {
|
|
21
|
-
const
|
|
22
|
-
|
|
24
|
+
const reqServerFilesPath = join(
|
|
25
|
+
ctx.standaloneRootDir,
|
|
26
|
+
ctx.relPublishDir,
|
|
27
|
+
"required-server-files.json"
|
|
28
|
+
);
|
|
29
|
+
const reqServerFiles = JSON.parse(await readFile(reqServerFilesPath, "utf-8"));
|
|
30
|
+
if (ctx.distDir.replace(new RegExp(`^${ctx.packagePath}/?`), "") !== reqServerFiles.config.distDir) {
|
|
31
|
+
reqServerFiles.config.distDir = ctx.nextDistDir;
|
|
32
|
+
await writeFile(reqServerFilesPath, JSON.stringify(reqServerFiles));
|
|
33
|
+
}
|
|
34
|
+
await mkdir(ctx.serverHandlerDir, { recursive: true });
|
|
35
|
+
await writeFile(
|
|
36
|
+
join(ctx.serverHandlerDir, RUN_CONFIG),
|
|
37
|
+
JSON.stringify(reqServerFiles.config),
|
|
38
|
+
"utf-8"
|
|
39
|
+
);
|
|
40
|
+
const srcDir = join(ctx.standaloneDir, ctx.nextDistDir);
|
|
41
|
+
const nextFolder = ctx.distDir === ctx.buildConfig.distDir ? ctx.distDir : ctx.nextDistDir;
|
|
42
|
+
const destDir = join(ctx.serverHandlerDir, nextFolder);
|
|
23
43
|
const paths = await (0, import_fast_glob.default)(
|
|
24
44
|
[`*`, `server/*`, `server/chunks/*`, `server/edge-chunks/*`, `server/+(app|pages)/**/*.js`],
|
|
25
45
|
{
|
|
@@ -67,7 +87,7 @@ async function recreateNodeModuleSymlinks(src, dest, org) {
|
|
|
67
87
|
var copyNextDependencies = async (ctx) => {
|
|
68
88
|
const entries = await readdir(ctx.standaloneDir);
|
|
69
89
|
const promises = entries.map(async (entry) => {
|
|
70
|
-
if (entry === "package.json" || entry ===
|
|
90
|
+
if (entry === "package.json" || entry === ctx.nextDistDir) {
|
|
71
91
|
return;
|
|
72
92
|
}
|
|
73
93
|
const src = join(ctx.standaloneDir, entry);
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
import {
|
|
8
8
|
require_out
|
|
9
9
|
} from "./chunk-VZNKO4OO.js";
|
|
10
|
+
import {
|
|
11
|
+
encodeBlobKey
|
|
12
|
+
} from "./chunk-TYCYFZ22.js";
|
|
10
13
|
import {
|
|
11
14
|
__toESM
|
|
12
15
|
} from "./chunk-5JVNISGM.js";
|
|
@@ -14,13 +17,25 @@ import {
|
|
|
14
17
|
// src/build/content/prerendered.ts
|
|
15
18
|
var import_fast_glob = __toESM(require_out(), 1);
|
|
16
19
|
import { existsSync } from "node:fs";
|
|
17
|
-
import { readFile } from "node:fs/promises";
|
|
18
|
-
import { join } from "node:path";
|
|
20
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
21
|
+
import { dirname, join } from "node:path";
|
|
22
|
+
var writeCacheEntry = async (route, value, lastModified, ctx) => {
|
|
23
|
+
const path = join(ctx.blobDir, await encodeBlobKey(route));
|
|
24
|
+
const entry = JSON.stringify({
|
|
25
|
+
lastModified,
|
|
26
|
+
value
|
|
27
|
+
});
|
|
28
|
+
await mkdir(dirname(path), { recursive: true });
|
|
29
|
+
await writeFile(path, entry, "utf-8");
|
|
30
|
+
};
|
|
19
31
|
var routeToFilePath = (path) => path === "/" ? "/index" : path;
|
|
20
32
|
var buildPagesCacheValue = async (path) => ({
|
|
21
33
|
kind: "PAGE",
|
|
22
34
|
html: await readFile(`${path}.html`, "utf-8"),
|
|
23
|
-
pageData: JSON.parse(await readFile(`${path}.json`, "utf-8"))
|
|
35
|
+
pageData: JSON.parse(await readFile(`${path}.json`, "utf-8")),
|
|
36
|
+
postponed: void 0,
|
|
37
|
+
headers: void 0,
|
|
38
|
+
status: void 0
|
|
24
39
|
});
|
|
25
40
|
var buildAppCacheValue = async (path) => ({
|
|
26
41
|
kind: "PAGE",
|
|
@@ -42,39 +57,32 @@ var copyPrerenderedContent = async (ctx) => {
|
|
|
42
57
|
const manifest = await ctx.getPrerenderManifest();
|
|
43
58
|
await Promise.all(
|
|
44
59
|
Object.entries(manifest.routes).map(async ([route, meta]) => {
|
|
60
|
+
const lastModified = meta.initialRevalidateSeconds ? Date.now() - 31536e6 : Date.now();
|
|
45
61
|
const key = routeToFilePath(route);
|
|
46
62
|
let value;
|
|
47
|
-
let path;
|
|
48
63
|
switch (true) {
|
|
49
64
|
case (meta.dataRoute?.endsWith("/default.rsc") && !existsSync(join(ctx.publishDir, "server/app", `${key}.html`))):
|
|
50
65
|
return;
|
|
51
66
|
case meta.dataRoute?.endsWith(".json"):
|
|
52
|
-
|
|
53
|
-
value = await buildPagesCacheValue(path);
|
|
67
|
+
value = await buildPagesCacheValue(join(ctx.publishDir, "server/pages", key));
|
|
54
68
|
break;
|
|
55
69
|
case meta.dataRoute?.endsWith(".rsc"):
|
|
56
|
-
|
|
57
|
-
value = await buildAppCacheValue(path);
|
|
70
|
+
value = await buildAppCacheValue(join(ctx.publishDir, "server/app", key));
|
|
58
71
|
break;
|
|
59
72
|
case meta.dataRoute === null:
|
|
60
|
-
|
|
61
|
-
value = await buildRouteCacheValue(path);
|
|
73
|
+
value = await buildRouteCacheValue(join(ctx.publishDir, "server/app", key));
|
|
62
74
|
break;
|
|
63
75
|
default:
|
|
64
76
|
throw new Error(`Unrecognized content: ${route}`);
|
|
65
77
|
}
|
|
66
|
-
await
|
|
67
|
-
key,
|
|
68
|
-
value,
|
|
69
|
-
meta.dataRoute === null ? `${path}.body` : `${path}.html`
|
|
70
|
-
);
|
|
78
|
+
await writeCacheEntry(key, value, lastModified, ctx);
|
|
71
79
|
})
|
|
72
80
|
);
|
|
73
81
|
if (existsSync(join(ctx.publishDir, `server/app/_not-found.html`))) {
|
|
82
|
+
const lastModified = Date.now();
|
|
74
83
|
const key = "/404";
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
await ctx.writeCacheEntry(key, value, `${path}.html`);
|
|
84
|
+
const value = await buildAppCacheValue(join(ctx.publishDir, "server/app/_not-found"));
|
|
85
|
+
await writeCacheEntry(key, value, lastModified, ctx);
|
|
78
86
|
}
|
|
79
87
|
} catch (error) {
|
|
80
88
|
ctx.failBuild("Failed assembling prerendered content for upload", error);
|
|
@@ -82,15 +90,16 @@ var copyPrerenderedContent = async (ctx) => {
|
|
|
82
90
|
};
|
|
83
91
|
var copyFetchContent = async (ctx) => {
|
|
84
92
|
try {
|
|
85
|
-
const paths = await (0, import_fast_glob.
|
|
93
|
+
const paths = await (0, import_fast_glob.glob)(["!(*.*)"], {
|
|
86
94
|
cwd: join(ctx.publishDir, "cache/fetch-cache"),
|
|
87
95
|
extglob: true
|
|
88
96
|
});
|
|
89
97
|
await Promise.all(
|
|
90
98
|
paths.map(async (key) => {
|
|
99
|
+
const lastModified = Date.now() - 31536e6;
|
|
91
100
|
const path = join(ctx.publishDir, "cache/fetch-cache", key);
|
|
92
101
|
const value = await buildFetchCacheValue(path);
|
|
93
|
-
await
|
|
102
|
+
await writeCacheEntry(key, value, lastModified, ctx);
|
|
94
103
|
})
|
|
95
104
|
);
|
|
96
105
|
} catch (error) {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
var require = await (async () => {
|
|
3
|
+
var { createRequire } = await import("node:module");
|
|
4
|
+
return createRequire(import.meta.url);
|
|
5
|
+
})();
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
// src/build/cache.ts
|
|
9
|
+
import { existsSync } from "node:fs";
|
|
10
|
+
import { rm } from "node:fs/promises";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
var saveBuildCache = async (ctx) => {
|
|
13
|
+
const { cache } = ctx.utils;
|
|
14
|
+
const cacheDir = join(ctx.publishDir, "cache");
|
|
15
|
+
if (existsSync(cacheDir)) {
|
|
16
|
+
await rm(join(cacheDir, "fetch-cache"), { recursive: true, force: true });
|
|
17
|
+
await cache.save(cacheDir);
|
|
18
|
+
console.log("Next.js cache saved");
|
|
19
|
+
} else {
|
|
20
|
+
console.log("No Next.js cache to save");
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
var restoreBuildCache = async (ctx) => {
|
|
24
|
+
const { cache } = ctx.utils;
|
|
25
|
+
const cacheDir = join(ctx.publishDir, "cache");
|
|
26
|
+
if (await cache.restore(cacheDir)) {
|
|
27
|
+
console.log("Next.js cache restored");
|
|
28
|
+
} else {
|
|
29
|
+
console.log("No Next.js cache to restore");
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
saveBuildCache,
|
|
35
|
+
restoreBuildCache
|
|
36
|
+
};
|
|
@@ -536,7 +536,7 @@ var mapHeaderValues = (header, callback) => {
|
|
|
536
536
|
};
|
|
537
537
|
var setVaryHeaders = (headers, request, { basePath, i18n }) => {
|
|
538
538
|
const netlifyVaryValues = {
|
|
539
|
-
headers: [],
|
|
539
|
+
headers: ["x-nextjs-data"],
|
|
540
540
|
languages: [],
|
|
541
541
|
cookies: ["__prerender_bypass", "__next_preview_data"]
|
|
542
542
|
};
|
|
@@ -553,7 +553,13 @@ var setVaryHeaders = (headers, request, { basePath, i18n }) => {
|
|
|
553
553
|
headers.set(`netlify-vary`, generateNetlifyVaryValues(netlifyVaryValues));
|
|
554
554
|
};
|
|
555
555
|
var fetchBeforeNextPatchedIt = globalThis.fetch;
|
|
556
|
-
var adjustDateHeader = async (
|
|
556
|
+
var adjustDateHeader = async ({
|
|
557
|
+
headers,
|
|
558
|
+
request,
|
|
559
|
+
span,
|
|
560
|
+
tracer,
|
|
561
|
+
requestContext
|
|
562
|
+
}) => {
|
|
557
563
|
const cacheState = headers.get("x-nextjs-cache");
|
|
558
564
|
const isServedFromCache = cacheState === "HIT" || cacheState === "STALE";
|
|
559
565
|
span.setAttributes({
|
|
@@ -564,22 +570,43 @@ var adjustDateHeader = async (headers, request, span, tracer) => {
|
|
|
564
570
|
return;
|
|
565
571
|
}
|
|
566
572
|
const key = new URL(request.url).pathname;
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
573
|
+
let lastModified;
|
|
574
|
+
if (requestContext.responseCacheGetLastModified) {
|
|
575
|
+
lastModified = requestContext.responseCacheGetLastModified;
|
|
576
|
+
} else {
|
|
577
|
+
span.recordException(
|
|
578
|
+
new Error("lastModified not found in requestContext, falling back to trying blobs")
|
|
579
|
+
);
|
|
580
|
+
span.setAttributes({
|
|
581
|
+
severity: "alert",
|
|
582
|
+
warning: true
|
|
583
|
+
});
|
|
584
|
+
const blobKey = await encodeBlobKey(key);
|
|
585
|
+
const blobStore = getDeployStore({ fetch: fetchBeforeNextPatchedIt, consistency: "strong" });
|
|
586
|
+
lastModified = await tracer.startActiveSpan(
|
|
587
|
+
"get cache to calculate date header",
|
|
588
|
+
async (getBlobForDateSpan) => {
|
|
589
|
+
getBlobForDateSpan.setAttributes({
|
|
590
|
+
key,
|
|
591
|
+
blobKey
|
|
592
|
+
});
|
|
593
|
+
const blob = await blobStore.get(blobKey, { type: "json" }) ?? {};
|
|
594
|
+
getBlobForDateSpan.addEvent(blob ? "Cache hit" : "Cache miss");
|
|
595
|
+
getBlobForDateSpan.end();
|
|
596
|
+
return blob.lastModified;
|
|
597
|
+
}
|
|
598
|
+
);
|
|
599
|
+
}
|
|
582
600
|
if (!lastModified) {
|
|
601
|
+
span.recordException(
|
|
602
|
+
new Error(
|
|
603
|
+
"lastModified not found in either requestContext or blobs, date header for cached response is not set"
|
|
604
|
+
)
|
|
605
|
+
);
|
|
606
|
+
span.setAttributes({
|
|
607
|
+
severity: "alert",
|
|
608
|
+
warning: true
|
|
609
|
+
});
|
|
583
610
|
return;
|
|
584
611
|
}
|
|
585
612
|
const lastModifiedDate = new Date(lastModified);
|
|
@@ -589,29 +616,34 @@ var adjustDateHeader = async (headers, request, span, tracer) => {
|
|
|
589
616
|
var setCacheControlHeaders = (headers, request) => {
|
|
590
617
|
const cacheControl = headers.get("cache-control");
|
|
591
618
|
if (cacheControl !== null && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control")) {
|
|
592
|
-
const
|
|
619
|
+
const browserCacheControl = omitHeaderValues(cacheControl, [
|
|
593
620
|
"s-maxage",
|
|
594
621
|
"stale-while-revalidate"
|
|
595
622
|
]);
|
|
596
|
-
const
|
|
597
|
-
|
|
598
|
-
(
|
|
623
|
+
const cdnCacheControl = (
|
|
624
|
+
// if we are serving already stale response, instruct edge to not attempt to cache that response
|
|
625
|
+
headers.get("x-nextjs-cache") === "STALE" ? "public, max-age=0, must-revalidate" : mapHeaderValues(
|
|
626
|
+
cacheControl,
|
|
627
|
+
(value) => value === "stale-while-revalidate" ? "stale-while-revalidate=31536000" : value
|
|
628
|
+
)
|
|
599
629
|
);
|
|
600
|
-
headers.set("cache-control",
|
|
601
|
-
headers.set("netlify-cdn-cache-control",
|
|
630
|
+
headers.set("cache-control", browserCacheControl || "public, max-age=0, must-revalidate");
|
|
631
|
+
headers.set("netlify-cdn-cache-control", cdnCacheControl);
|
|
602
632
|
}
|
|
603
633
|
};
|
|
604
634
|
var setCacheTagsHeaders = (headers, request, manifest) => {
|
|
605
635
|
const path = new URL(request.url).pathname;
|
|
606
636
|
const tags = manifest[path];
|
|
607
|
-
|
|
637
|
+
if (tags !== void 0) {
|
|
638
|
+
headers.set("netlify-cache-tag", tags);
|
|
639
|
+
}
|
|
608
640
|
};
|
|
609
641
|
var NEXT_CACHE_TO_CACHE_STATUS = {
|
|
610
642
|
HIT: `hit`,
|
|
611
643
|
MISS: `fwd=miss`,
|
|
612
644
|
STALE: `hit; fwd=stale`
|
|
613
645
|
};
|
|
614
|
-
var
|
|
646
|
+
var setCacheStatusHeader = (headers) => {
|
|
615
647
|
const nextCache = headers.get("x-nextjs-cache");
|
|
616
648
|
if (typeof nextCache === "string") {
|
|
617
649
|
if (nextCache in NEXT_CACHE_TO_CACHE_STATUS) {
|
|
@@ -627,5 +659,5 @@ export {
|
|
|
627
659
|
adjustDateHeader,
|
|
628
660
|
setCacheControlHeaders,
|
|
629
661
|
setCacheTagsHeaders,
|
|
630
|
-
|
|
662
|
+
setCacheStatusHeader
|
|
631
663
|
};
|