@netlify/plugin-nextjs 5.0.0-beta.8 → 5.0.0-rc.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/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/content/static.js +1 -1
- package/dist/build/functions/edge.js +2 -3
- package/dist/build/functions/server.js +4 -4
- package/dist/build/image-cdn.js +3 -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-WSPFUAK4.js → chunk-FTCARYDZ.js} +6 -6
- package/dist/esm-chunks/{chunk-XIP2W57K.js → chunk-NL5YH5N6.js} +5 -4
- package/dist/esm-chunks/{chunk-IZ2AVCVF.js → chunk-PGQNT7XM.js} +52 -24
- package/dist/esm-chunks/chunk-RL4K4CVH.js +27 -0
- package/dist/esm-chunks/{chunk-N23TUUXK.js → chunk-UTCWWUFW.js} +68 -29
- package/dist/esm-chunks/{chunk-ETPYUOBQ.js → chunk-UX4JCTAE.js} +5 -5
- package/dist/esm-chunks/{chunk-K233JI4O.js → chunk-UYKENJEU.js} +4 -2
- package/dist/esm-chunks/{chunk-ZWFKLYLH.js → chunk-WQIG4U66.js} +5 -4
- package/dist/esm-chunks/chunk-XXBTIYSL.js +7199 -0
- package/dist/esm-chunks/{package-2CI3IXK3.js → package-5SG7C3OT.js} +13 -8
- package/dist/index.js +13 -14
- package/dist/run/config.js +2 -2
- package/dist/run/constants.js +5 -3
- package/dist/run/handlers/cache.cjs +165 -79
- package/dist/run/handlers/request-context.cjs +56 -0
- package/dist/run/handlers/server.js +34 -20
- package/dist/run/handlers/tracing.js +1 -1
- package/dist/run/headers.js +3 -3
- package/dist/run/next.cjs +6 -1
- package/dist/run/revalidate.js +1 -1
- package/edge-runtime/lib/response.ts +25 -21
- package/edge-runtime/lib/util.ts +6 -1
- package/package.json +1 -1
- package/dist/esm-chunks/chunk-EPSI5TTB.js +0 -28
- package/dist/esm-chunks/chunk-WT2HN3M6.js +0 -255
- 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,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
copyStaticContent,
|
|
10
10
|
publishStaticDir,
|
|
11
11
|
unpublishStaticDir
|
|
12
|
-
} from "../../esm-chunks/chunk-
|
|
12
|
+
} from "../../esm-chunks/chunk-WQIG4U66.js";
|
|
13
13
|
import "../../esm-chunks/chunk-VZNKO4OO.js";
|
|
14
14
|
import "../../esm-chunks/chunk-TYCYFZ22.js";
|
|
15
15
|
import "../../esm-chunks/chunk-5JVNISGM.js";
|
|
@@ -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-UX4JCTAE.js";
|
|
11
10
|
import "../../esm-chunks/chunk-VZNKO4OO.js";
|
|
12
|
-
import "../../esm-chunks/chunk-
|
|
11
|
+
import "../../esm-chunks/chunk-PGQNT7XM.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-FTCARYDZ.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-PGQNT7XM.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
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
})();
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
+
generateRegexFromPattern,
|
|
8
9
|
setImageConfig
|
|
9
|
-
} from "../esm-chunks/chunk-
|
|
10
|
+
} from "../esm-chunks/chunk-XXBTIYSL.js";
|
|
10
11
|
import "../esm-chunks/chunk-5JVNISGM.js";
|
|
11
12
|
export {
|
|
13
|
+
generateRegexFromPattern,
|
|
12
14
|
setImageConfig
|
|
13
15
|
};
|
|
@@ -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-PGQNT7XM.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
|
+
};
|
|
@@ -8,13 +8,13 @@ import {
|
|
|
8
8
|
copyNextDependencies,
|
|
9
9
|
copyNextServerCode,
|
|
10
10
|
writeTagsManifest
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import {
|
|
13
|
-
SERVER_HANDLER_NAME
|
|
14
|
-
} from "./chunk-IZ2AVCVF.js";
|
|
11
|
+
} from "./chunk-4J4A5OE2.js";
|
|
15
12
|
import {
|
|
16
13
|
require_out
|
|
17
14
|
} from "./chunk-VZNKO4OO.js";
|
|
15
|
+
import {
|
|
16
|
+
SERVER_HANDLER_NAME
|
|
17
|
+
} from "./chunk-PGQNT7XM.js";
|
|
18
18
|
import {
|
|
19
19
|
__toESM
|
|
20
20
|
} from "./chunk-5JVNISGM.js";
|
|
@@ -27,7 +27,7 @@ var copyHandlerDependencies = async (ctx) => {
|
|
|
27
27
|
const fileList = await (0, import_fast_glob.glob)("dist/**/*", { cwd: ctx.pluginDir });
|
|
28
28
|
await Promise.all(
|
|
29
29
|
[...fileList].map(
|
|
30
|
-
(path) => cp(join(ctx.pluginDir, path), join(ctx.serverHandlerDir, path), {
|
|
30
|
+
(path) => cp(join(ctx.pluginDir, path), join(ctx.serverHandlerDir, ".netlify", path), {
|
|
31
31
|
recursive: true,
|
|
32
32
|
force: true
|
|
33
33
|
})
|
|
@@ -61,7 +61,7 @@ var getHandlerFile = async (ctx) => {
|
|
|
61
61
|
const templatesDir = join(ctx.pluginDir, "dist/build/templates");
|
|
62
62
|
if (ctx.packagePath.length !== 0) {
|
|
63
63
|
const template = await readFile(join(templatesDir, "handler-monorepo.tmpl.js"), "utf-8");
|
|
64
|
-
return template.replaceAll("{{cwd}}",
|
|
64
|
+
return template.replaceAll("{{cwd}}", ctx.lambdaWorkingDirectory).replace("{{nextServerHandler}}", ctx.nextServerHandler);
|
|
65
65
|
}
|
|
66
66
|
return await readFile(join(templatesDir, "handler.tmpl.js"), "utf-8");
|
|
67
67
|
};
|
|
@@ -5,18 +5,19 @@
|
|
|
5
5
|
})();
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
-
PLUGIN_DIR
|
|
9
|
-
|
|
8
|
+
PLUGIN_DIR,
|
|
9
|
+
RUN_CONFIG
|
|
10
|
+
} from "./chunk-UYKENJEU.js";
|
|
10
11
|
|
|
11
12
|
// src/run/config.ts
|
|
12
13
|
import { existsSync } from "node:fs";
|
|
13
14
|
import { readFile } from "node:fs/promises";
|
|
14
15
|
import { join, resolve } from "node:path";
|
|
15
16
|
var getRunConfig = async () => {
|
|
16
|
-
return JSON.parse(await readFile(resolve(
|
|
17
|
+
return JSON.parse(await readFile(resolve(RUN_CONFIG), "utf-8"));
|
|
17
18
|
};
|
|
18
19
|
var setRunConfig = (config) => {
|
|
19
|
-
const cacheHandler = join(PLUGIN_DIR, "dist/run/handlers/cache.cjs");
|
|
20
|
+
const cacheHandler = join(PLUGIN_DIR, ".netlify/dist/run/handlers/cache.cjs");
|
|
20
21
|
if (!existsSync(cacheHandler)) {
|
|
21
22
|
throw new Error(`Cache handler not found at ${cacheHandler}`);
|
|
22
23
|
}
|
|
@@ -4,17 +4,15 @@
|
|
|
4
4
|
return createRequire(import.meta.url);
|
|
5
5
|
})();
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
encodeBlobKey
|
|
9
|
-
} from "./chunk-TYCYFZ22.js";
|
|
10
7
|
|
|
11
8
|
// src/build/plugin-context.ts
|
|
12
9
|
import { readFileSync } from "node:fs";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
10
|
+
import { readFile } from "node:fs/promises";
|
|
11
|
+
import { join, relative, resolve } from "node:path";
|
|
15
12
|
import { fileURLToPath } from "node:url";
|
|
16
13
|
var MODULE_DIR = fileURLToPath(new URL(".", import.meta.url));
|
|
17
14
|
var PLUGIN_DIR = join(MODULE_DIR, "../..");
|
|
15
|
+
var DEFAULT_PUBLISH_DIR = ".next";
|
|
18
16
|
var SERVER_HANDLER_NAME = "___netlify-server-handler";
|
|
19
17
|
var EDGE_HANDLER_NAME = "___netlify-edge-handler";
|
|
20
18
|
var PluginContext = class {
|
|
@@ -26,9 +24,16 @@ var PluginContext = class {
|
|
|
26
24
|
packageJSON;
|
|
27
25
|
/** Absolute path of the next runtime plugin directory */
|
|
28
26
|
pluginDir = PLUGIN_DIR;
|
|
27
|
+
get relPublishDir() {
|
|
28
|
+
return this.constants.PUBLISH_DIR ?? join(this.packagePath, DEFAULT_PUBLISH_DIR);
|
|
29
|
+
}
|
|
30
|
+
/** Temporary directory for stashing the build output */
|
|
31
|
+
get tempPublishDir() {
|
|
32
|
+
return this.resolve(".netlify/.next");
|
|
33
|
+
}
|
|
29
34
|
/** Absolute path of the publish directory */
|
|
30
35
|
get publishDir() {
|
|
31
|
-
return resolve(this.
|
|
36
|
+
return resolve(this.relPublishDir);
|
|
32
37
|
}
|
|
33
38
|
/**
|
|
34
39
|
* Relative package path in non monorepo setups this is an empty string
|
|
@@ -38,15 +43,38 @@ var PluginContext = class {
|
|
|
38
43
|
get packagePath() {
|
|
39
44
|
return this.constants.PACKAGE_PATH || "";
|
|
40
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* The working directory inside the lambda that is used for monorepos to execute the serverless function
|
|
48
|
+
*/
|
|
49
|
+
get lambdaWorkingDirectory() {
|
|
50
|
+
return join("/var/task", this.distFolder);
|
|
51
|
+
}
|
|
41
52
|
/**
|
|
42
53
|
* Retrieves the root of the `.next/standalone` directory
|
|
43
54
|
*/
|
|
44
55
|
get standaloneRootDir() {
|
|
45
56
|
return join(this.publishDir, "standalone");
|
|
46
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* The resolved relative next dist directory defaults to `.next`,
|
|
60
|
+
* but can be configured through the next.config.js. For monorepos this will include the packagePath
|
|
61
|
+
* If we need just the plain dist dir use the `nextDistDir`
|
|
62
|
+
*/
|
|
63
|
+
get distDir() {
|
|
64
|
+
const dir = this.buildConfig.distDir ?? DEFAULT_PUBLISH_DIR;
|
|
65
|
+
return relative(process.cwd(), resolve(this.packagePath, dir));
|
|
66
|
+
}
|
|
67
|
+
/** The dist folder represents the parent directory of the .next folder or custom distDir */
|
|
68
|
+
get distFolder() {
|
|
69
|
+
return join(this.distDir, "..");
|
|
70
|
+
}
|
|
71
|
+
/** The `.next` folder or what the custom dist dir is set to */
|
|
72
|
+
get nextDistDir() {
|
|
73
|
+
return relative(this.distFolder, this.distDir);
|
|
74
|
+
}
|
|
47
75
|
/** Retrieves the `.next/standalone/` directory monorepo aware */
|
|
48
76
|
get standaloneDir() {
|
|
49
|
-
return join(this.standaloneRootDir, this.
|
|
77
|
+
return join(this.standaloneRootDir, this.distFolder);
|
|
50
78
|
}
|
|
51
79
|
/**
|
|
52
80
|
* Absolute path of the directory that is published and deployed to the Netlify CDN
|
|
@@ -75,10 +103,16 @@ var PluginContext = class {
|
|
|
75
103
|
return join(this.serverFunctionsDir, SERVER_HANDLER_NAME);
|
|
76
104
|
}
|
|
77
105
|
get serverHandlerDir() {
|
|
78
|
-
|
|
106
|
+
if (this.packagePath.length === 0) {
|
|
107
|
+
return this.serverHandlerRootDir;
|
|
108
|
+
}
|
|
109
|
+
return join(this.serverHandlerRootDir, this.distFolder);
|
|
79
110
|
}
|
|
80
111
|
get nextServerHandler() {
|
|
81
|
-
|
|
112
|
+
if (this.packagePath.length !== 0) {
|
|
113
|
+
return join(this.lambdaWorkingDirectory, ".netlify/dist/run/handlers/server.js");
|
|
114
|
+
}
|
|
115
|
+
return "./.netlify/dist/run/handlers/server.js";
|
|
82
116
|
}
|
|
83
117
|
/**
|
|
84
118
|
* Absolute path of the directory containing the files for deno edge functions
|
|
@@ -115,9 +149,16 @@ var PluginContext = class {
|
|
|
115
149
|
await readFile(join(this.publishDir, "server/middleware-manifest.json"), "utf-8")
|
|
116
150
|
);
|
|
117
151
|
}
|
|
152
|
+
// don't make private as it is handy inside testing to override the config
|
|
153
|
+
_buildConfig = null;
|
|
118
154
|
/** Get Next Config from build output **/
|
|
119
|
-
|
|
120
|
-
|
|
155
|
+
get buildConfig() {
|
|
156
|
+
if (!this._buildConfig) {
|
|
157
|
+
this._buildConfig = JSON.parse(
|
|
158
|
+
readFileSync(join(this.publishDir, "required-server-files.json"), "utf-8")
|
|
159
|
+
).config;
|
|
160
|
+
}
|
|
161
|
+
return this._buildConfig;
|
|
121
162
|
}
|
|
122
163
|
/**
|
|
123
164
|
* Get Next.js routes manifest from the build output
|
|
@@ -125,19 +166,6 @@ var PluginContext = class {
|
|
|
125
166
|
async getRoutesManifest() {
|
|
126
167
|
return JSON.parse(await readFile(join(this.publishDir, "routes-manifest.json"), "utf-8"));
|
|
127
168
|
}
|
|
128
|
-
/**
|
|
129
|
-
* Write a cache entry to the blob upload directory.
|
|
130
|
-
*/
|
|
131
|
-
async writeCacheEntry(route, value, filePath) {
|
|
132
|
-
const { mtime } = await stat(filePath);
|
|
133
|
-
const path = join(this.blobDir, await encodeBlobKey(route));
|
|
134
|
-
const entry = JSON.stringify({
|
|
135
|
-
lastModified: mtime.getTime(),
|
|
136
|
-
value
|
|
137
|
-
});
|
|
138
|
-
await mkdir(dirname(path), { recursive: true });
|
|
139
|
-
await writeFile(path, entry, "utf-8");
|
|
140
|
-
}
|
|
141
169
|
/** Fails a build with a message and an optional error */
|
|
142
170
|
failBuild(message, error) {
|
|
143
171
|
return this.utils.build.failBuild(message, error instanceof Error ? { error } : void 0);
|