@opennextjs/aws 3.1.6 → 3.2.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/README.md +27 -22
- package/dist/adapters/binary.js +2 -0
- package/dist/adapters/cache.d.ts +4 -2
- package/dist/adapters/cache.js +14 -8
- package/dist/adapters/config/util.d.ts +2 -2
- package/dist/adapters/image-optimization-adapter.d.ts +2 -2
- package/dist/adapters/middleware.js +5 -52
- package/dist/adapters/plugins/image-optimization/image-optimization.d.ts +7 -4
- package/dist/adapters/plugins/image-optimization/image-optimization.js +2 -3
- package/dist/adapters/plugins/image-optimization/image-optimization.replacement.d.ts +3 -0
- package/dist/adapters/plugins/image-optimization/image-optimization.replacement.js +4 -7
- package/dist/adapters/warmer-function.js +2 -67
- package/dist/build/buildNextApp.d.ts +3 -0
- package/dist/build/buildNextApp.js +19 -0
- package/dist/build/bundleNextServer.js +2 -2
- package/dist/build/compileCache.d.ts +9 -0
- package/dist/build/compileCache.js +30 -0
- package/dist/build/compileConfig.d.ts +17 -3
- package/dist/build/compileConfig.js +56 -34
- package/dist/build/compileTagCacheProvider.d.ts +2 -0
- package/dist/build/compileTagCacheProvider.js +26 -0
- package/dist/build/copyTracedFiles.js +2 -2
- package/dist/build/createAssets.d.ts +11 -0
- package/dist/build/createAssets.js +161 -0
- package/dist/build/createImageOptimizationBundle.d.ts +2 -0
- package/dist/build/createImageOptimizationBundle.js +82 -0
- package/dist/build/createMiddleware.d.ts +10 -0
- package/dist/build/createMiddleware.js +47 -0
- package/dist/build/createRevalidationBundle.d.ts +2 -0
- package/dist/build/createRevalidationBundle.js +35 -0
- package/dist/build/createServerBundle.d.ts +2 -2
- package/dist/build/createServerBundle.js +35 -39
- package/dist/build/createWarmerBundle.d.ts +2 -0
- package/dist/build/createWarmerBundle.js +44 -0
- package/dist/build/edge/createEdgeBundle.d.ts +6 -8
- package/dist/build/edge/createEdgeBundle.js +11 -15
- package/dist/build/helper.d.ts +22 -5
- package/dist/build/helper.js +42 -11
- package/dist/build/installDeps.d.ts +2 -0
- package/dist/build/installDeps.js +46 -0
- package/dist/build/utils.d.ts +5 -0
- package/dist/build/utils.js +22 -0
- package/dist/build/validateConfig.d.ts +1 -1
- package/dist/build.d.ts +0 -4
- package/dist/build.js +26 -486
- package/dist/core/createGenericHandler.js +5 -5
- package/dist/core/createMainHandler.d.ts +3 -3
- package/dist/core/createMainHandler.js +5 -5
- package/dist/core/requestHandler.d.ts +2 -2
- package/dist/core/requestHandler.js +2 -2
- package/dist/core/resolve.d.ts +13 -4
- package/dist/core/resolve.js +30 -5
- package/dist/core/routing/cacheInterceptor.d.ts +1 -1
- package/dist/core/routing/i18n/index.d.ts +1 -1
- package/dist/core/routing/i18n/index.js +3 -0
- package/dist/core/routing/matcher.d.ts +2 -1
- package/dist/core/routing/matcher.js +13 -6
- package/dist/core/routing/middleware.d.ts +6 -2
- package/dist/core/routing/middleware.js +13 -7
- package/dist/core/routing/util.d.ts +3 -2
- package/dist/core/routing/util.js +16 -7
- package/dist/core/routingHandler.d.ts +1 -1
- package/dist/core/routingHandler.js +1 -1
- package/dist/helpers/withCloudflare.d.ts +1 -1
- package/dist/helpers/withSST.d.ts +1 -1
- package/dist/http/openNextResponse.d.ts +10 -2
- package/dist/http/openNextResponse.js +27 -0
- package/dist/http/request.d.ts +1 -0
- package/dist/http/util.d.ts +1 -1
- package/dist/{converters → overrides/converters}/aws-apigw-v1.d.ts +1 -1
- package/dist/{converters → overrides/converters}/aws-apigw-v1.js +2 -2
- package/dist/{converters → overrides/converters}/aws-apigw-v2.d.ts +1 -1
- package/dist/{converters → overrides/converters}/aws-apigw-v2.js +4 -4
- package/dist/{converters → overrides/converters}/aws-cloudfront.d.ts +1 -1
- package/dist/{converters → overrides/converters}/aws-cloudfront.js +6 -7
- package/dist/{converters → overrides/converters}/dummy.d.ts +1 -1
- package/dist/overrides/converters/edge.d.ts +9 -0
- package/dist/{converters → overrides/converters}/edge.js +6 -3
- package/dist/{converters → overrides/converters}/node.d.ts +1 -1
- package/dist/{converters → overrides/converters}/node.js +1 -1
- package/dist/overrides/converters/sqs-revalidate.d.ts +4 -0
- package/dist/overrides/imageLoader/dummy.d.ts +3 -0
- package/dist/overrides/imageLoader/dummy.js +8 -0
- package/dist/overrides/imageLoader/host.d.ts +1 -1
- package/dist/overrides/imageLoader/s3.d.ts +1 -1
- package/dist/overrides/incrementalCache/dummy.d.ts +3 -0
- package/dist/overrides/incrementalCache/dummy.js +13 -0
- package/dist/{cache/incremental → overrides/incrementalCache}/s3-lite.d.ts +1 -1
- package/dist/{cache/incremental → overrides/incrementalCache}/s3.d.ts +1 -1
- package/dist/{cache/incremental → overrides/incrementalCache}/types.d.ts +1 -1
- package/dist/overrides/originResolver/dummy.d.ts +3 -0
- package/dist/overrides/originResolver/dummy.js +7 -0
- package/dist/overrides/originResolver/pattern-env.d.ts +3 -0
- package/dist/overrides/originResolver/pattern-env.js +39 -0
- package/dist/overrides/queue/dummy.d.ts +3 -0
- package/dist/overrides/queue/dummy.js +7 -0
- package/dist/{queue → overrides/queue}/sqs-lite.d.ts +1 -1
- package/dist/{queue → overrides/queue}/sqs-lite.js +3 -3
- package/dist/{queue → overrides/queue}/sqs.d.ts +1 -1
- package/dist/{queue → overrides/queue}/sqs.js +1 -1
- package/dist/overrides/tagCache/dummy.d.ts +3 -0
- package/dist/overrides/tagCache/dummy.js +17 -0
- package/dist/{cache/tag → overrides/tagCache}/dynamodb-lite.d.ts +1 -1
- package/dist/{cache/tag → overrides/tagCache}/dynamodb-lite.js +1 -1
- package/dist/{cache/tag → overrides/tagCache}/dynamodb.d.ts +1 -1
- package/dist/{cache/tag → overrides/tagCache}/dynamodb.js +1 -1
- package/dist/overrides/warmer/aws-lambda.d.ts +3 -0
- package/dist/overrides/warmer/aws-lambda.js +59 -0
- package/dist/overrides/warmer/dummy.d.ts +3 -0
- package/dist/overrides/warmer/dummy.js +7 -0
- package/dist/overrides/wrappers/aws-lambda-streaming.d.ts +7 -0
- package/dist/{wrappers → overrides/wrappers}/aws-lambda-streaming.js +1 -1
- package/dist/overrides/wrappers/aws-lambda.d.ts +7 -0
- package/dist/{wrappers → overrides/wrappers}/cloudflare.d.ts +2 -2
- package/dist/{wrappers → overrides/wrappers}/cloudflare.js +1 -1
- package/dist/overrides/wrappers/dummy.d.ts +7 -0
- package/dist/overrides/wrappers/dummy.js +6 -0
- package/dist/overrides/wrappers/node.d.ts +7 -0
- package/dist/{wrappers → overrides/wrappers}/node.js +1 -1
- package/dist/plugins/edge.d.ts +5 -4
- package/dist/plugins/edge.js +27 -29
- package/dist/plugins/replacement.d.ts +2 -2
- package/dist/plugins/replacement.js +4 -5
- package/dist/plugins/resolve.d.ts +4 -2
- package/dist/plugins/resolve.js +32 -20
- package/dist/types/aws-lambda.d.ts +3 -2
- package/dist/{cache/next-types.d.ts → types/cache.d.ts} +1 -0
- package/dist/types/next-types.d.ts +3 -1
- package/dist/types/open-next.d.ts +44 -13
- package/package.json +2 -2
- package/dist/adapters/plugins/without-routing/requestHandler.d.ts +0 -2
- package/dist/adapters/plugins/without-routing/requestHandler.js +0 -10
- package/dist/converters/edge.d.ts +0 -6
- package/dist/converters/sqs-revalidate.d.ts +0 -4
- package/dist/wrappers/aws-lambda-streaming.d.ts +0 -7
- package/dist/wrappers/aws-lambda.d.ts +0 -7
- package/dist/wrappers/node.d.ts +0 -7
- /package/dist/{converters → overrides/converters}/dummy.js +0 -0
- /package/dist/{converters → overrides/converters}/sqs-revalidate.js +0 -0
- /package/dist/{converters → overrides/converters}/utils.d.ts +0 -0
- /package/dist/{converters → overrides/converters}/utils.js +0 -0
- /package/dist/{cache/incremental → overrides/incrementalCache}/s3-lite.js +0 -0
- /package/dist/{cache/incremental → overrides/incrementalCache}/s3.js +0 -0
- /package/dist/{cache/incremental → overrides/incrementalCache}/types.js +0 -0
- /package/dist/{queue → overrides/queue}/types.d.ts +0 -0
- /package/dist/{cache/tag → overrides/queue}/types.js +0 -0
- /package/dist/{cache/tag → overrides/tagCache}/constants.d.ts +0 -0
- /package/dist/{cache/tag → overrides/tagCache}/constants.js +0 -0
- /package/dist/{cache/tag → overrides/tagCache}/types.d.ts +0 -0
- /package/dist/{queue → overrides/tagCache}/types.js +0 -0
- /package/dist/{wrappers → overrides/wrappers}/aws-lambda.js +0 -0
- /package/dist/{cache/next-types.js → types/cache.js} +0 -0
|
@@ -1,19 +1,53 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { buildSync } from "esbuild";
|
|
4
5
|
import logger from "../logger.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import { validateConfig } from "./validateConfig.js";
|
|
7
|
+
/**
|
|
8
|
+
* Compiles the OpenNext configuration.
|
|
9
|
+
*
|
|
10
|
+
* The configuration is always compiled for Node.js and for the edge only if needed.
|
|
11
|
+
*
|
|
12
|
+
* @param baseDir Directory where to look for the configuration.
|
|
13
|
+
* @param openNextConfigPath Override the default configuration when provided. Relative to baseDir.
|
|
14
|
+
* @param nodeExternals Externals for the Node.js compilation.
|
|
15
|
+
* @return The configuration and the build directory.
|
|
16
|
+
*/
|
|
17
|
+
export async function compileOpenNextConfig(baseDir, openNextConfigPath, nodeExternals) {
|
|
18
|
+
const sourcePath = path.join(baseDir, openNextConfigPath ?? "open-next.config.ts");
|
|
19
|
+
const buildDir = fs.mkdtempSync(path.join(os.tmpdir(), "open-next-tmp"));
|
|
20
|
+
let configPath = compileOpenNextConfigNode(sourcePath, buildDir, nodeExternals ? nodeExternals.split(",") : []);
|
|
21
|
+
// On Windows, we need to use file:// protocol to load the config file using import()
|
|
22
|
+
if (process.platform === "win32")
|
|
23
|
+
configPath = `file://${configPath}`;
|
|
24
|
+
const config = (await import(configPath)).default;
|
|
25
|
+
if (!config || !config.default) {
|
|
26
|
+
logger.error(`config.default cannot be empty, it should be at least {}, see more info here: https://opennext.js.org/config#configuration-file`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
validateConfig(config);
|
|
30
|
+
// We need to check if the config uses the edge runtime at any point
|
|
31
|
+
// If it does, we need to compile it with the edge runtime
|
|
32
|
+
const usesEdgeRuntime = config.middleware?.external ||
|
|
33
|
+
Object.values(config.functions || {}).some((fn) => fn.runtime === "edge");
|
|
34
|
+
if (!usesEdgeRuntime) {
|
|
35
|
+
logger.debug("No edge runtime found in the open-next.config.ts. Using default config.");
|
|
36
|
+
//Nothing to do here
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
compileOpenNextConfigEdge(sourcePath, buildDir, config.edgeExternals ?? []);
|
|
40
|
+
}
|
|
41
|
+
return { config, buildDir };
|
|
42
|
+
}
|
|
43
|
+
export function compileOpenNextConfigNode(sourcePath, outputDir, externals) {
|
|
44
|
+
const outputPath = path.join(outputDir, "open-next.config.mjs");
|
|
45
|
+
logger.debug("Compiling open-next.config.ts for Node.", outputPath);
|
|
8
46
|
//Check if open-next.config.ts exists
|
|
9
47
|
if (!fs.existsSync(sourcePath)) {
|
|
10
48
|
//Create a simple open-next.config.mjs file
|
|
11
49
|
logger.debug("Cannot find open-next.config.ts. Using default config.");
|
|
12
|
-
fs.writeFileSync(outputPath,
|
|
13
|
-
"var config = { default: { } };",
|
|
14
|
-
"var open_next_config_default = config;",
|
|
15
|
-
"export { open_next_config_default as default };",
|
|
16
|
-
].join("\n"));
|
|
50
|
+
fs.writeFileSync(outputPath, "export default { default: { } };");
|
|
17
51
|
}
|
|
18
52
|
else {
|
|
19
53
|
buildSync({
|
|
@@ -22,7 +56,7 @@ export function compileOpenNextConfigNode(tempDir, openNextConfigPath, nodeExter
|
|
|
22
56
|
bundle: true,
|
|
23
57
|
format: "esm",
|
|
24
58
|
target: ["node18"],
|
|
25
|
-
external:
|
|
59
|
+
external: externals,
|
|
26
60
|
platform: "node",
|
|
27
61
|
banner: {
|
|
28
62
|
js: [
|
|
@@ -36,29 +70,17 @@ export function compileOpenNextConfigNode(tempDir, openNextConfigPath, nodeExter
|
|
|
36
70
|
}
|
|
37
71
|
return outputPath;
|
|
38
72
|
}
|
|
39
|
-
export function compileOpenNextConfigEdge(
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
buildSync({
|
|
53
|
-
entryPoints: [sourcePath],
|
|
54
|
-
outfile: outputPath,
|
|
55
|
-
bundle: true,
|
|
56
|
-
format: "esm",
|
|
57
|
-
target: ["es2020"],
|
|
58
|
-
conditions: ["worker", "browser"],
|
|
59
|
-
platform: "browser",
|
|
60
|
-
external: config.edgeExternals ?? [],
|
|
61
|
-
});
|
|
62
|
-
logger.info("Compiled open-next.config.ts for edge runtime.");
|
|
63
|
-
}
|
|
73
|
+
export function compileOpenNextConfigEdge(sourcePath, outputDir, externals) {
|
|
74
|
+
const outputPath = path.join(outputDir, "open-next.config.edge.mjs");
|
|
75
|
+
logger.debug("Compiling open-next.config.ts for edge runtime.", outputPath);
|
|
76
|
+
buildSync({
|
|
77
|
+
entryPoints: [sourcePath],
|
|
78
|
+
outfile: outputPath,
|
|
79
|
+
bundle: true,
|
|
80
|
+
format: "esm",
|
|
81
|
+
target: ["es2020"],
|
|
82
|
+
conditions: ["worker", "browser"],
|
|
83
|
+
platform: "browser",
|
|
84
|
+
external: externals,
|
|
85
|
+
});
|
|
64
86
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { openNextResolvePlugin } from "../plugins/resolve.js";
|
|
3
|
+
import * as buildHelper from "./helper.js";
|
|
4
|
+
import { installDependencies } from "./installDeps.js";
|
|
5
|
+
export async function compileTagCacheProvider(options) {
|
|
6
|
+
const providerPath = path.join(options.outputDir, "dynamodb-provider");
|
|
7
|
+
const overrides = options.config.initializationFunction?.override;
|
|
8
|
+
await buildHelper.esbuildAsync({
|
|
9
|
+
external: ["@aws-sdk/client-dynamodb"],
|
|
10
|
+
entryPoints: [
|
|
11
|
+
path.join(options.openNextDistDir, "adapters", "dynamo-provider.js"),
|
|
12
|
+
],
|
|
13
|
+
outfile: path.join(providerPath, "index.mjs"),
|
|
14
|
+
target: ["node18"],
|
|
15
|
+
plugins: [
|
|
16
|
+
openNextResolvePlugin({
|
|
17
|
+
fnName: "initializationFunction",
|
|
18
|
+
overrides: {
|
|
19
|
+
converter: overrides?.converter ?? "dummy",
|
|
20
|
+
wrapper: overrides?.wrapper,
|
|
21
|
+
},
|
|
22
|
+
}),
|
|
23
|
+
],
|
|
24
|
+
}, options);
|
|
25
|
+
installDependencies(providerPath, options.config.initializationFunction?.install);
|
|
26
|
+
}
|
|
@@ -54,7 +54,7 @@ export async function copyTracedFiles(buildOutputPath, packagePath, outputDir, r
|
|
|
54
54
|
throw new Error(`
|
|
55
55
|
--------------------------------------------------------------------------------
|
|
56
56
|
${pagePath} cannot use the edge runtime.
|
|
57
|
-
OpenNext requires edge runtime function to be defined in a separate function.
|
|
57
|
+
OpenNext requires edge runtime function to be defined in a separate function.
|
|
58
58
|
See the docs for more information on how to bundle edge runtime functions.
|
|
59
59
|
--------------------------------------------------------------------------------
|
|
60
60
|
`);
|
|
@@ -71,7 +71,7 @@ File ${fullFilePath} does not exist
|
|
|
71
71
|
extractFiles(requiredFiles.files, path.join(standaloneNextDir, dir)).forEach((f) => {
|
|
72
72
|
filesToCopy.set(f, f.replace(standaloneDir, outputDir));
|
|
73
73
|
});
|
|
74
|
-
if (!existsSync(path.join(standaloneNextDir,
|
|
74
|
+
if (!existsSync(path.join(standaloneNextDir, fullFilePath))) {
|
|
75
75
|
throw new Error(`This error should only happen for static 404 and 500 page from page router. Report this if that's not the case.,
|
|
76
76
|
File ${fullFilePath} does not exist`);
|
|
77
77
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as buildHelper from "./helper.js";
|
|
2
|
+
export declare function createStaticAssets(options: buildHelper.BuildOptions): void;
|
|
3
|
+
/**
|
|
4
|
+
* Create the cache assets.
|
|
5
|
+
*
|
|
6
|
+
* @param options Build options.
|
|
7
|
+
* @returns Whether tag cache is used.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createCacheAssets(options: buildHelper.BuildOptions): {
|
|
10
|
+
useTagCache: boolean;
|
|
11
|
+
};
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { isBinaryContentType } from "../adapters/binary.js";
|
|
4
|
+
import logger from "../logger.js";
|
|
5
|
+
import * as buildHelper from "./helper.js";
|
|
6
|
+
export function createStaticAssets(options) {
|
|
7
|
+
logger.info(`Bundling static assets...`);
|
|
8
|
+
const { appBuildOutputPath, appPublicPath, outputDir, appPath } = options;
|
|
9
|
+
// Create output folder
|
|
10
|
+
const outputPath = path.join(outputDir, "assets");
|
|
11
|
+
fs.mkdirSync(outputPath, { recursive: true });
|
|
12
|
+
// Next.js outputs assets into multiple files. Copy into the same directory.
|
|
13
|
+
// Copy over:
|
|
14
|
+
// - .next/BUILD_ID => _next/BUILD_ID
|
|
15
|
+
// - .next/static => _next/static
|
|
16
|
+
// - public/* => *
|
|
17
|
+
// - app/favicon.ico or src/app/favicon.ico => favicon.ico
|
|
18
|
+
fs.copyFileSync(path.join(appBuildOutputPath, ".next/BUILD_ID"), path.join(outputPath, "BUILD_ID"));
|
|
19
|
+
fs.cpSync(path.join(appBuildOutputPath, ".next/static"), path.join(outputPath, "_next", "static"), { recursive: true });
|
|
20
|
+
if (fs.existsSync(appPublicPath)) {
|
|
21
|
+
fs.cpSync(appPublicPath, outputPath, { recursive: true });
|
|
22
|
+
}
|
|
23
|
+
const appSrcPath = fs.existsSync(path.join(appPath, "src"))
|
|
24
|
+
? "src/app"
|
|
25
|
+
: "app";
|
|
26
|
+
const faviconPath = path.join(appPath, appSrcPath, "favicon.ico");
|
|
27
|
+
if (fs.existsSync(faviconPath)) {
|
|
28
|
+
fs.copyFileSync(faviconPath, path.join(outputPath, "favicon.ico"));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Create the cache assets.
|
|
33
|
+
*
|
|
34
|
+
* @param options Build options.
|
|
35
|
+
* @returns Whether tag cache is used.
|
|
36
|
+
*/
|
|
37
|
+
export function createCacheAssets(options) {
|
|
38
|
+
logger.info(`Bundling cache assets...`);
|
|
39
|
+
const { appBuildOutputPath, outputDir } = options;
|
|
40
|
+
const packagePath = path.relative(options.monorepoRoot, appBuildOutputPath);
|
|
41
|
+
const buildId = buildHelper.getBuildId(appBuildOutputPath);
|
|
42
|
+
let useTagCache = false;
|
|
43
|
+
// Copy pages to cache folder
|
|
44
|
+
const dotNextPath = path.join(appBuildOutputPath, ".next/standalone", packagePath);
|
|
45
|
+
const outputPath = path.join(outputDir, "cache", buildId);
|
|
46
|
+
[".next/server/pages", ".next/server/app"]
|
|
47
|
+
.map((dir) => path.join(dotNextPath, dir))
|
|
48
|
+
.filter(fs.existsSync)
|
|
49
|
+
.forEach((dir) => fs.cpSync(dir, outputPath, { recursive: true }));
|
|
50
|
+
// Remove non-cache files
|
|
51
|
+
const htmlPages = buildHelper.getHtmlPages(dotNextPath);
|
|
52
|
+
buildHelper.removeFiles(outputPath, (file) => file.endsWith(".js") ||
|
|
53
|
+
file.endsWith(".js.nft.json") ||
|
|
54
|
+
(file.endsWith(".html") && htmlPages.has(file)));
|
|
55
|
+
// Merge cache files into a single file
|
|
56
|
+
const cacheFilesPath = {};
|
|
57
|
+
buildHelper.traverseFiles(outputPath, () => true, (filepath) => {
|
|
58
|
+
const ext = path.extname(filepath);
|
|
59
|
+
switch (ext) {
|
|
60
|
+
case ".meta":
|
|
61
|
+
case ".html":
|
|
62
|
+
case ".json":
|
|
63
|
+
case ".body":
|
|
64
|
+
case ".rsc":
|
|
65
|
+
const newFilePath = filepath
|
|
66
|
+
.substring(0, filepath.length - ext.length)
|
|
67
|
+
.replace(/\.prefetch$/, "") + ".cache";
|
|
68
|
+
cacheFilesPath[newFilePath] = {
|
|
69
|
+
[ext.slice(1)]: filepath,
|
|
70
|
+
...cacheFilesPath[newFilePath],
|
|
71
|
+
};
|
|
72
|
+
break;
|
|
73
|
+
case ".map":
|
|
74
|
+
break;
|
|
75
|
+
default:
|
|
76
|
+
logger.warn(`Unknown file extension: ${ext}`);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
// Generate cache file
|
|
81
|
+
Object.entries(cacheFilesPath).forEach(([cacheFilePath, files]) => {
|
|
82
|
+
const cacheFileMeta = files.meta
|
|
83
|
+
? JSON.parse(fs.readFileSync(files.meta, "utf8"))
|
|
84
|
+
: undefined;
|
|
85
|
+
const cacheFileContent = {
|
|
86
|
+
type: files.body ? "route" : files.json ? "page" : "app",
|
|
87
|
+
meta: cacheFileMeta,
|
|
88
|
+
html: files.html ? fs.readFileSync(files.html, "utf8") : undefined,
|
|
89
|
+
json: files.json
|
|
90
|
+
? JSON.parse(fs.readFileSync(files.json, "utf8"))
|
|
91
|
+
: undefined,
|
|
92
|
+
rsc: files.rsc ? fs.readFileSync(files.rsc, "utf8") : undefined,
|
|
93
|
+
body: files.body
|
|
94
|
+
? fs
|
|
95
|
+
.readFileSync(files.body)
|
|
96
|
+
.toString(isBinaryContentType(cacheFileMeta.headers["content-type"])
|
|
97
|
+
? "base64"
|
|
98
|
+
: "utf8")
|
|
99
|
+
: undefined,
|
|
100
|
+
};
|
|
101
|
+
fs.writeFileSync(cacheFilePath, JSON.stringify(cacheFileContent));
|
|
102
|
+
});
|
|
103
|
+
if (!options.config.dangerous?.disableTagCache) {
|
|
104
|
+
// Generate dynamodb data
|
|
105
|
+
// We need to traverse the cache to find every .meta file
|
|
106
|
+
const metaFiles = [];
|
|
107
|
+
// Compute dynamodb cache data
|
|
108
|
+
// Traverse files inside cache to find all meta files and cache tags associated with them
|
|
109
|
+
buildHelper.traverseFiles(outputPath, (file) => file.endsWith(".meta"), (filePath) => {
|
|
110
|
+
const fileContent = fs.readFileSync(filePath, "utf8");
|
|
111
|
+
const fileData = JSON.parse(fileContent);
|
|
112
|
+
if (fileData.headers?.["x-next-cache-tags"]) {
|
|
113
|
+
fileData.headers["x-next-cache-tags"]
|
|
114
|
+
.split(",")
|
|
115
|
+
.forEach((tag) => {
|
|
116
|
+
// TODO: We should split the tag using getDerivedTags from next.js or maybe use an in house implementation
|
|
117
|
+
metaFiles.push({
|
|
118
|
+
tag: { S: path.posix.join(buildId, tag.trim()) },
|
|
119
|
+
path: {
|
|
120
|
+
S: path.posix.join(buildId, path.relative(outputPath, filePath).replace(".meta", "")),
|
|
121
|
+
},
|
|
122
|
+
// We don't care about the revalidation time here, we just need to make sure it's there
|
|
123
|
+
revalidatedAt: { N: "1" },
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
// Copy fetch-cache to cache folder
|
|
129
|
+
const fetchCachePath = path.join(appBuildOutputPath, ".next/cache/fetch-cache");
|
|
130
|
+
if (fs.existsSync(fetchCachePath)) {
|
|
131
|
+
const fetchOutputPath = path.join(outputDir, "cache", "__fetch", buildId);
|
|
132
|
+
fs.mkdirSync(fetchOutputPath, { recursive: true });
|
|
133
|
+
fs.cpSync(fetchCachePath, fetchOutputPath, { recursive: true });
|
|
134
|
+
buildHelper.traverseFiles(fetchCachePath, () => true, (filepath) => {
|
|
135
|
+
const fileContent = fs.readFileSync(filepath, "utf8");
|
|
136
|
+
const fileData = JSON.parse(fileContent);
|
|
137
|
+
fileData?.tags?.forEach((tag) => {
|
|
138
|
+
metaFiles.push({
|
|
139
|
+
tag: { S: path.posix.join(buildId, tag) },
|
|
140
|
+
path: {
|
|
141
|
+
S: path.posix.join(buildId, path.relative(fetchCachePath, filepath)),
|
|
142
|
+
},
|
|
143
|
+
revalidatedAt: { N: "1" },
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (metaFiles.length > 0) {
|
|
149
|
+
useTagCache = true;
|
|
150
|
+
const providerPath = path.join(outputDir, "dynamodb-provider");
|
|
151
|
+
//Copy open-next.config.mjs into the bundle
|
|
152
|
+
fs.mkdirSync(providerPath, { recursive: true });
|
|
153
|
+
buildHelper.copyOpenNextConfig(options.buildDir, providerPath);
|
|
154
|
+
// TODO: check if metafiles doesn't contain duplicates
|
|
155
|
+
fs.writeFileSync(path.join(providerPath, "dynamodb-cache.json"), JSON.stringify(metaFiles));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// We need to remove files later because we need the metafiles for dynamodb tags cache
|
|
159
|
+
buildHelper.removeFiles(outputPath, (file) => !file.endsWith(".cache"));
|
|
160
|
+
return { useTagCache };
|
|
161
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import logger from "../logger.js";
|
|
5
|
+
import { openNextReplacementPlugin } from "../plugins/replacement.js";
|
|
6
|
+
import { openNextResolvePlugin } from "../plugins/resolve.js";
|
|
7
|
+
import * as buildHelper from "./helper.js";
|
|
8
|
+
import { installDependencies } from "./installDeps.js";
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
export async function createImageOptimizationBundle(options) {
|
|
11
|
+
logger.info(`Bundling image optimization function...`);
|
|
12
|
+
const { appBuildOutputPath, config, outputDir } = options;
|
|
13
|
+
// Create output folder
|
|
14
|
+
const outputPath = path.join(outputDir, "image-optimization-function");
|
|
15
|
+
fs.mkdirSync(outputPath, { recursive: true });
|
|
16
|
+
// Copy open-next.config.mjs into the bundle
|
|
17
|
+
buildHelper.copyOpenNextConfig(options.buildDir, outputPath);
|
|
18
|
+
const plugins = [
|
|
19
|
+
openNextResolvePlugin({
|
|
20
|
+
fnName: "imageOptimization",
|
|
21
|
+
overrides: {
|
|
22
|
+
converter: config.imageOptimization?.override?.converter,
|
|
23
|
+
wrapper: config.imageOptimization?.override?.wrapper,
|
|
24
|
+
imageLoader: config.imageOptimization?.loader,
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
|
+
];
|
|
28
|
+
if (buildHelper.compareSemver(options.nextVersion, "14.1.1") >= 0) {
|
|
29
|
+
plugins.push(openNextReplacementPlugin({
|
|
30
|
+
name: "opennext-14.1.1-image-optimization",
|
|
31
|
+
target: /plugins(\/|\\)image-optimization(\/|\\)image-optimization\.js/g,
|
|
32
|
+
replacements: [
|
|
33
|
+
require.resolve("../adapters/plugins/image-optimization/image-optimization.replacement.js"),
|
|
34
|
+
],
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
// Build Lambda code (1st pass)
|
|
38
|
+
// note: bundle in OpenNext package b/c the adapter relies on the
|
|
39
|
+
// "@aws-sdk/client-s3" package which is not a dependency in user's
|
|
40
|
+
// Next.js app.
|
|
41
|
+
await buildHelper.esbuildAsync({
|
|
42
|
+
entryPoints: [
|
|
43
|
+
path.join(options.openNextDistDir, "adapters", "image-optimization-adapter.js"),
|
|
44
|
+
],
|
|
45
|
+
external: ["sharp", "next"],
|
|
46
|
+
outfile: path.join(outputPath, "index.mjs"),
|
|
47
|
+
plugins,
|
|
48
|
+
}, options);
|
|
49
|
+
// Build Lambda code (2nd pass)
|
|
50
|
+
// note: bundle in user's Next.js app again b/c the adapter relies on the
|
|
51
|
+
// "next" package. And the "next" package from user's app should
|
|
52
|
+
// be used. We also set @opentelemetry/api as external because it seems to be
|
|
53
|
+
// required by Next 15 even though it's not used.
|
|
54
|
+
buildHelper.esbuildSync({
|
|
55
|
+
entryPoints: [path.join(outputPath, "index.mjs")],
|
|
56
|
+
external: ["sharp", "@opentelemetry/api"],
|
|
57
|
+
allowOverwrite: true,
|
|
58
|
+
outfile: path.join(outputPath, "index.mjs"),
|
|
59
|
+
banner: {
|
|
60
|
+
js: [
|
|
61
|
+
"import { createRequire as topLevelCreateRequire } from 'module';",
|
|
62
|
+
"const require = topLevelCreateRequire(import.meta.url);",
|
|
63
|
+
"import bannerUrl from 'url';",
|
|
64
|
+
"const __dirname = bannerUrl.fileURLToPath(new URL('.', import.meta.url));",
|
|
65
|
+
].join("\n"),
|
|
66
|
+
},
|
|
67
|
+
}, options);
|
|
68
|
+
// Copy over .next/required-server-files.json file and BUILD_ID
|
|
69
|
+
fs.mkdirSync(path.join(outputPath, ".next"));
|
|
70
|
+
fs.copyFileSync(path.join(appBuildOutputPath, ".next/required-server-files.json"), path.join(outputPath, ".next/required-server-files.json"));
|
|
71
|
+
fs.copyFileSync(path.join(appBuildOutputPath, ".next/BUILD_ID"), path.join(outputPath, ".next/BUILD_ID"));
|
|
72
|
+
// Sharp provides pre-build binaries for all platforms. https://github.com/lovell/sharp/blob/main/docs/install.md#cross-platform
|
|
73
|
+
// Target should be same as used by Lambda, see https://github.com/sst/sst/blob/ca6f763fdfddd099ce2260202d0ce48c72e211ea/packages/sst/src/constructs/NextjsSite.ts#L114
|
|
74
|
+
// For SHARP_IGNORE_GLOBAL_LIBVIPS see: https://github.com/lovell/sharp/blob/main/docs/install.md#aws-lambda
|
|
75
|
+
const sharpVersion = process.env.SHARP_VERSION ?? "0.32.6";
|
|
76
|
+
installDependencies(outputPath, config.imageOptimization?.install ?? {
|
|
77
|
+
packages: [`sharp@${sharpVersion}`],
|
|
78
|
+
arch: "arm64",
|
|
79
|
+
nodeVersion: "18",
|
|
80
|
+
libc: "glibc",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as buildHelper from "./helper.js";
|
|
2
|
+
/**
|
|
3
|
+
* Compiles the middleware bundle.
|
|
4
|
+
*
|
|
5
|
+
* @param options Build Options.
|
|
6
|
+
* @param forceOnlyBuildOnce force to build only once.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createMiddleware(options: buildHelper.BuildOptions, { forceOnlyBuildOnce }?: {
|
|
9
|
+
forceOnlyBuildOnce?: boolean | undefined;
|
|
10
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import logger from "../logger.js";
|
|
4
|
+
import { buildEdgeBundle } from "./edge/createEdgeBundle.js";
|
|
5
|
+
import * as buildHelper from "./helper.js";
|
|
6
|
+
import { installDependencies } from "./installDeps.js";
|
|
7
|
+
/**
|
|
8
|
+
* Compiles the middleware bundle.
|
|
9
|
+
*
|
|
10
|
+
* @param options Build Options.
|
|
11
|
+
* @param forceOnlyBuildOnce force to build only once.
|
|
12
|
+
*/
|
|
13
|
+
export async function createMiddleware(options, { forceOnlyBuildOnce = false } = {}) {
|
|
14
|
+
logger.info(`Bundling middleware function...`);
|
|
15
|
+
const { appBuildOutputPath, config, outputDir } = options;
|
|
16
|
+
// Get middleware manifest
|
|
17
|
+
const middlewareManifest = JSON.parse(fs.readFileSync(path.join(appBuildOutputPath, ".next/server/middleware-manifest.json"), "utf8"));
|
|
18
|
+
const middlewareInfo = middlewareManifest.middleware["/"];
|
|
19
|
+
if (config.middleware?.external) {
|
|
20
|
+
const outputPath = path.join(outputDir, "middleware");
|
|
21
|
+
fs.mkdirSync(outputPath, { recursive: true });
|
|
22
|
+
// Copy open-next.config.mjs
|
|
23
|
+
buildHelper.copyOpenNextConfig(options.buildDir, outputPath, config.middleware.override?.wrapper === "cloudflare");
|
|
24
|
+
// Bundle middleware
|
|
25
|
+
await buildEdgeBundle({
|
|
26
|
+
entrypoint: path.join(options.openNextDistDir, "adapters", "middleware.js"),
|
|
27
|
+
outfile: path.join(outputPath, "handler.mjs"),
|
|
28
|
+
middlewareInfo,
|
|
29
|
+
options,
|
|
30
|
+
overrides: config.middleware?.override,
|
|
31
|
+
defaultConverter: "aws-cloudfront",
|
|
32
|
+
includeCache: config.dangerous?.enableCacheInterception,
|
|
33
|
+
additionalExternals: config.edgeExternals,
|
|
34
|
+
onlyBuildOnce: forceOnlyBuildOnce === true,
|
|
35
|
+
});
|
|
36
|
+
installDependencies(outputPath, config.middleware?.install);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
await buildEdgeBundle({
|
|
40
|
+
entrypoint: path.join(options.openNextDistDir, "core", "edgeFunctionHandler.js"),
|
|
41
|
+
outfile: path.join(options.buildDir, "middleware.mjs"),
|
|
42
|
+
middlewareInfo,
|
|
43
|
+
options,
|
|
44
|
+
onlyBuildOnce: true,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import logger from "../logger.js";
|
|
4
|
+
import { openNextResolvePlugin } from "../plugins/resolve.js";
|
|
5
|
+
import * as buildHelper from "./helper.js";
|
|
6
|
+
import { installDependencies } from "./installDeps.js";
|
|
7
|
+
export async function createRevalidationBundle(options) {
|
|
8
|
+
logger.info(`Bundling revalidation function...`);
|
|
9
|
+
const { appBuildOutputPath, config, outputDir } = options;
|
|
10
|
+
// Create output folder
|
|
11
|
+
const outputPath = path.join(outputDir, "revalidation-function");
|
|
12
|
+
fs.mkdirSync(outputPath, { recursive: true });
|
|
13
|
+
//Copy open-next.config.mjs into the bundle
|
|
14
|
+
buildHelper.copyOpenNextConfig(options.buildDir, outputPath);
|
|
15
|
+
// Build Lambda code
|
|
16
|
+
await buildHelper.esbuildAsync({
|
|
17
|
+
external: ["next", "styled-jsx", "react"],
|
|
18
|
+
entryPoints: [
|
|
19
|
+
path.join(options.openNextDistDir, "adapters", "revalidate.js"),
|
|
20
|
+
],
|
|
21
|
+
outfile: path.join(outputPath, "index.mjs"),
|
|
22
|
+
plugins: [
|
|
23
|
+
openNextResolvePlugin({
|
|
24
|
+
fnName: "revalidate",
|
|
25
|
+
overrides: {
|
|
26
|
+
converter: config.revalidate?.override?.converter ?? "sqs-revalidate",
|
|
27
|
+
wrapper: config.revalidate?.override?.wrapper,
|
|
28
|
+
},
|
|
29
|
+
}),
|
|
30
|
+
],
|
|
31
|
+
}, options);
|
|
32
|
+
installDependencies(outputPath, config.revalidate?.install);
|
|
33
|
+
// Copy over .next/prerender-manifest.json file
|
|
34
|
+
fs.copyFileSync(path.join(appBuildOutputPath, ".next", "prerender-manifest.json"), path.join(outputPath, "prerender-manifest.json"));
|
|
35
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
export declare function createServerBundle(options: BuildOptions): Promise<void>;
|
|
1
|
+
import * as buildHelper from "./helper.js";
|
|
2
|
+
export declare function createServerBundle(options: buildHelper.BuildOptions): Promise<void>;
|