@opennextjs/aws 3.1.6 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -22
- package/dist/adapters/binary.js +2 -0
- package/dist/adapters/cache.d.ts +3 -2
- package/dist/adapters/cache.js +2 -2
- 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/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 +79 -0
- package/dist/build/createMiddleware.d.ts +10 -0
- package/dist/build/createMiddleware.js +55 -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 +27 -26
- package/dist/build/createWarmerBundle.d.ts +2 -0
- package/dist/build/createWarmerBundle.js +44 -0
- package/dist/build/edge/createEdgeBundle.d.ts +3 -3
- package/dist/build/edge/createEdgeBundle.js +3 -5
- 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 +36 -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/createMainHandler.d.ts +3 -3
- package/dist/core/requestHandler.d.ts +2 -2
- package/dist/core/requestHandler.js +1 -1
- 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 +1 -1
- package/dist/core/routing/middleware.d.ts +6 -2
- package/dist/core/routing/middleware.js +7 -4
- package/dist/core/routing/util.d.ts +3 -2
- package/dist/core/routing/util.js +9 -3
- package/dist/core/routingHandler.d.ts +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 +6 -0
- package/dist/{converters → overrides/converters}/edge.js +1 -1
- 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/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 +2 -2
- package/dist/plugins/replacement.d.ts +1 -1
- 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 +39 -13
- package/package.json +2 -2
- 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/{wrappers → overrides/wrappers}/cloudflare.js +0 -0
- /package/dist/{cache/next-types.js → types/cache.js} +0 -0
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<a href="https://
|
|
2
|
+
<a href="https://opennext.js.org">
|
|
3
3
|
<picture>
|
|
4
4
|
<source media="(prefers-color-scheme: dark)" srcset="docs/public/logo-dark.svg">
|
|
5
5
|
<img alt="OpenNext" src="docs/public/logo-light.svg" width="300" />
|
|
@@ -7,22 +7,23 @@
|
|
|
7
7
|
</a>
|
|
8
8
|
</p>
|
|
9
9
|
<p align="center">
|
|
10
|
-
<a href="https://
|
|
11
|
-
<a href="https://www.npmjs.com/package/
|
|
10
|
+
<a href="https://discord.gg/opennextjs"><img alt="Discord" src="https://img.shields.io/discord/1283128968140161065?style=flat-square" /></a>
|
|
11
|
+
<a href="https://www.npmjs.com/package/@opennextjs/aws"><img alt="npm" src="https://img.shields.io/npm/v/@opennextjs/aws.svg?style=flat-square" /></a>
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
<
|
|
17
|
-
<a href="https://
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
<h1 align="center">
|
|
17
|
+
<a href="https://opennext.js.org/aws">Docs</a>
|
|
18
|
+
</h1>
|
|
19
|
+
|
|
20
|
+
## Description
|
|
20
21
|
|
|
21
|
-
OpenNext takes the Next.js build output and converts it into
|
|
22
|
+
OpenNext takes the Next.js build output and converts it into packages that can be deployed across a variety of environments. Natively OpenNext has support for AWS Lambda, and classic Node.js Server.
|
|
22
23
|
|
|
23
24
|
## Features
|
|
24
25
|
|
|
25
|
-
OpenNext aims to support all Next.js 14 features. Some features are work in progress.
|
|
26
|
+
OpenNext aims to support all Next.js 14 features. Some features are work in progress. If you are running into any problems make sure to check the [docs](https://opennext.js.org/aws) first before you open a [new issue](/issues/new) or visit our [Discord](https://discord.gg/opennextjs) to let us know!
|
|
26
27
|
|
|
27
28
|
- [x] App & Pages Router
|
|
28
29
|
- [x] API routes
|
|
@@ -31,32 +32,30 @@ OpenNext aims to support all Next.js 14 features. Some features are work in prog
|
|
|
31
32
|
- [x] Server-side rendering (SSR)
|
|
32
33
|
- [x] Incremental static regeneration (ISR)
|
|
33
34
|
- [x] Middleware
|
|
35
|
+
- [x] Server actions
|
|
34
36
|
- [x] Image optimization
|
|
35
37
|
- [x] [NextAuth.js](https://next-auth.js.org)
|
|
36
38
|
- [x] Running at edge
|
|
37
|
-
- [x]
|
|
39
|
+
- [x] [Almost no coldstart (*)](#coldstart)
|
|
38
40
|
|
|
39
41
|
## Who is using OpenNext?
|
|
40
42
|
|
|
41
43
|
[Gymshark UK](https://uk.gymshark.com), [Udacity](https://engineering.udacity.com/deploying-next-js-on-the-edge-with-sst-is-sst-the-game-changer-its-claimed-to-be-1f05a0abc27c), [TUDN](https://www.tudn.com), [NHS England](https://github.com/nhs-england-tools/terraform-aws-opennext)
|
|
42
44
|
|
|
45
|
+
## Configuration
|
|
43
46
|
|
|
47
|
+
### Configuration file
|
|
44
48
|
|
|
45
|
-
|
|
49
|
+
For personalisation you need to create a file `open-next.config.ts` at the same place as your `next.config.js`, and export a default object that satisfies the `OpenNextConfig` interface. It is possible to not have an open-next.config.ts file, the default configuration will then be applied automatically.
|
|
46
50
|
|
|
47
|
-
|
|
51
|
+
### Debug mode
|
|
48
52
|
|
|
49
|
-
|
|
53
|
+
OpenNext can be executed in debug mode by setting the environment variable `OPEN_NEXT_DEBUG=true` before your build.
|
|
50
54
|
|
|
51
|
-
|
|
55
|
+
This will output A LOT of additional logs to the console. This also disable minifying in esbuild, and add source maps to the output. This can result in code that might be up to 2-3X larger than the production build. Do **not** enable this in production.
|
|
52
56
|
|
|
53
|
-
|
|
57
|
+
You can read more about the configuration in the [docs](https://opennext.js.org/aws/config)
|
|
54
58
|
|
|
55
|
-
### Environment variables
|
|
56
|
-
|
|
57
|
-
- AWS_SDK_DYNAMODB_MAX_ATTEMPTS: The maximum number of times requests that encounter retryable failures should be attempted for DynamoDB. Defaults to 3.
|
|
58
|
-
- AWS_SDK_S3_MAX_ATTEMPTS: The maximum number of times requests that encounter retryable failures should be attempted for S3. Defaults to 3.
|
|
59
|
-
- DYNAMO_BATCH_WRITE_COMMAND_CONCURRENCY: The number of concurrent batch write commands to DynamoDB. Defaults to 4 in an effort to leave plenty of DynamoDB write request capacity for the production load.
|
|
60
59
|
|
|
61
60
|
## Contribute
|
|
62
61
|
|
|
@@ -65,7 +64,7 @@ To run `OpenNext` locally:
|
|
|
65
64
|
1. Clone this repository.
|
|
66
65
|
1. Build `open-next`:
|
|
67
66
|
```bash
|
|
68
|
-
cd open-next
|
|
67
|
+
cd packages/open-next
|
|
69
68
|
pnpm build
|
|
70
69
|
```
|
|
71
70
|
1. Run `open-next` in watch mode:
|
|
@@ -78,6 +77,12 @@ To run `OpenNext` locally:
|
|
|
78
77
|
path/to/open-next/packages/open-next/dist/index.js build
|
|
79
78
|
```
|
|
80
79
|
|
|
80
|
+
### Coldstart
|
|
81
|
+
|
|
82
|
+
OpenNext provide you with a warmer function that can be used to reduce cold start.
|
|
83
|
+
|
|
84
|
+
On Lambda, there are multiple scenarios where a lambda will trigger a cold start even if you have some warmed instance. For example if you have more requests than warm instances you'll get a cold start. Also NextJs lazy load the routes, so even if you hit a warm instance, this specific route might not have been loaded yet.
|
|
85
|
+
|
|
81
86
|
## Acknowledgements
|
|
82
87
|
|
|
83
88
|
We are grateful for the projects that inspired OpenNext and the amazing tools and libraries developed by the community:
|
|
@@ -91,4 +96,4 @@ Special shoutout to [@khuezy](https://github.com/khuezy) and [@conico974](https:
|
|
|
91
96
|
|
|
92
97
|
---
|
|
93
98
|
|
|
94
|
-
Maintained by [SST](https://sst.dev). Join our community: [Discord](https://
|
|
99
|
+
Maintained by [SST](https://sst.dev). Join our community: [Discord](https://discord.gg/opennextjs) | [YouTube](https://www.youtube.com/c/sst-dev) | [Twitter](https://twitter.com/SST_dev)
|
package/dist/adapters/binary.js
CHANGED
package/dist/adapters/cache.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
|
|
3
|
-
import {
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import type { IncrementalCache } from "../overrides/incrementalCache/types.js";
|
|
4
|
+
import type { TagCache } from "../overrides/tagCache/types.js";
|
|
4
5
|
interface CachedFetchValue {
|
|
5
6
|
kind: "FETCH";
|
|
6
7
|
data: {
|
package/dist/adapters/cache.js
CHANGED
|
@@ -219,9 +219,9 @@ export default class S3Cache {
|
|
|
219
219
|
// Write derivedTags to dynamodb
|
|
220
220
|
// If we use an in house version of getDerivedTags in build we should use it here instead of next's one
|
|
221
221
|
const derivedTags = data?.kind === "FETCH"
|
|
222
|
-
? ctx?.tags ?? data?.data?.tags ?? [] // before version 14 next.js used data?.data?.tags so we keep it for backward compatibility
|
|
222
|
+
? (ctx?.tags ?? data?.data?.tags ?? []) // before version 14 next.js used data?.data?.tags so we keep it for backward compatibility
|
|
223
223
|
: data?.kind === "PAGE"
|
|
224
|
-
? data.headers?.["x-next-cache-tags"]?.split(",") ?? []
|
|
224
|
+
? (data.headers?.["x-next-cache-tags"]?.split(",") ?? [])
|
|
225
225
|
: [];
|
|
226
226
|
debug("derivedTags", derivedTags);
|
|
227
227
|
// Get all tags stored in dynamodb for the given key
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { MiddlewareManifest, NextConfig, PrerenderManifest } from "../../types/next-types";
|
|
2
|
-
import { PublicFiles } from "../../build";
|
|
1
|
+
import type { MiddlewareManifest, NextConfig, PrerenderManifest } from "../../types/next-types";
|
|
2
|
+
import type { PublicFiles } from "../../build";
|
|
3
3
|
export declare function loadConfig(nextDir: string): NextConfig;
|
|
4
4
|
export declare function loadBuildId(nextDir: string): string;
|
|
5
5
|
export declare function loadHtmlPages(nextDir: string): string[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StreamCreator } from "../http/openNextResponse.js";
|
|
2
|
-
import { InternalEvent, InternalResult } from "../types/open-next.js";
|
|
1
|
+
import type { StreamCreator } from "../http/openNextResponse.js";
|
|
2
|
+
import type { InternalEvent, InternalResult } from "../types/open-next.js";
|
|
3
3
|
export declare const handler: (...args: any[]) => any;
|
|
4
4
|
export declare function defaultHandler(event: InternalEvent, streamCreator?: StreamCreator): Promise<InternalResult>;
|
|
@@ -1,55 +1,10 @@
|
|
|
1
|
-
import { debug
|
|
1
|
+
import { debug } from "../adapters/logger";
|
|
2
2
|
import { createGenericHandler } from "../core/createGenericHandler";
|
|
3
|
-
import { resolveIncrementalCache, resolveQueue, resolveTagCache, } from "../core/resolve";
|
|
3
|
+
import { resolveIncrementalCache, resolveOriginResolver, resolveQueue, resolveTagCache, } from "../core/resolve";
|
|
4
4
|
import routingHandler from "../core/routingHandler";
|
|
5
|
-
const resolveOriginResolver = () => {
|
|
6
|
-
const openNextParams = globalThis.openNextConfig.middleware;
|
|
7
|
-
if (typeof openNextParams?.originResolver === "function") {
|
|
8
|
-
return openNextParams.originResolver();
|
|
9
|
-
}
|
|
10
|
-
else {
|
|
11
|
-
return Promise.resolve({
|
|
12
|
-
name: "env",
|
|
13
|
-
resolve: async (_path) => {
|
|
14
|
-
try {
|
|
15
|
-
const origin = JSON.parse(process.env.OPEN_NEXT_ORIGIN ?? "{}");
|
|
16
|
-
for (const [key, value] of Object.entries(globalThis.openNextConfig.functions ?? {}).filter(([key]) => key !== "default")) {
|
|
17
|
-
if (value.patterns.some((pattern) => {
|
|
18
|
-
// Convert cloudfront pattern to regex
|
|
19
|
-
return new RegExp(
|
|
20
|
-
// transform glob pattern to regex
|
|
21
|
-
"/" +
|
|
22
|
-
pattern
|
|
23
|
-
.replace(/\*\*/g, "(.*)")
|
|
24
|
-
.replace(/\*/g, "([^/]*)")
|
|
25
|
-
.replace(/\//g, "\\/")
|
|
26
|
-
.replace(/\?/g, ".")).test(_path);
|
|
27
|
-
})) {
|
|
28
|
-
debug("Using origin", key, value.patterns);
|
|
29
|
-
return origin[key];
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
if (_path.startsWith("/_next/image") && origin["imageOptimizer"]) {
|
|
33
|
-
debug("Using origin", "imageOptimizer", _path);
|
|
34
|
-
return origin["imageOptimizer"];
|
|
35
|
-
}
|
|
36
|
-
if (origin["default"]) {
|
|
37
|
-
debug("Using default origin", origin["default"], _path);
|
|
38
|
-
return origin["default"];
|
|
39
|
-
}
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
catch (e) {
|
|
43
|
-
error("Error while resolving origin", e);
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
5
|
globalThis.internalFetch = fetch;
|
|
51
6
|
const defaultHandler = async (internalEvent) => {
|
|
52
|
-
const originResolver = await resolveOriginResolver();
|
|
7
|
+
const originResolver = await resolveOriginResolver(globalThis.openNextConfig.middleware?.originResolver);
|
|
53
8
|
//#override includeCacheInMiddleware
|
|
54
9
|
globalThis.tagCache = await resolveTagCache(globalThis.openNextConfig.middleware?.override?.tagCache);
|
|
55
10
|
globalThis.queue = await resolveQueue(globalThis.openNextConfig.middleware?.override?.queue);
|
|
@@ -70,10 +25,8 @@ const defaultHandler = async (internalEvent) => {
|
|
|
70
25
|
isISR: result.isISR,
|
|
71
26
|
};
|
|
72
27
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return result;
|
|
76
|
-
}
|
|
28
|
+
debug("Middleware response", result);
|
|
29
|
+
return result;
|
|
77
30
|
};
|
|
78
31
|
export const handler = await createGenericHandler({
|
|
79
32
|
handler: defaultHandler,
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
/// <reference types="node" />
|
|
4
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
5
|
+
import type { APIGatewayProxyEventHeaders } from "aws-lambda";
|
|
6
|
+
import type { NextConfig } from "next/dist/server/config-shared";
|
|
7
|
+
import type { NextUrlWithParsedQuery } from "next/dist/server/request-meta";
|
|
7
8
|
export declare function optimizeImage(headers: APIGatewayProxyEventHeaders, imageParams: any, nextConfig: NextConfig, handleRequest: (newReq: IncomingMessage, newRes: ServerResponse, newParsedUrl: NextUrlWithParsedQuery) => Promise<void>): Promise<{
|
|
8
9
|
buffer: Buffer;
|
|
9
10
|
contentType: string;
|
|
10
11
|
maxAge: number;
|
|
12
|
+
etag: string;
|
|
13
|
+
upstreamEtag: string;
|
|
11
14
|
}>;
|
|
@@ -3,10 +3,9 @@ import { imageOptimizer } from "next/dist/server/image-optimizer";
|
|
|
3
3
|
import { debug } from "../../logger.js";
|
|
4
4
|
//#override optimizeImage
|
|
5
5
|
export async function optimizeImage(headers, imageParams, nextConfig, handleRequest) {
|
|
6
|
-
const result = await imageOptimizer(
|
|
7
|
-
// @ts-ignore
|
|
8
|
-
{ headers }, {}, // res object is not necessary as it's not actually used.
|
|
6
|
+
const result = await imageOptimizer({ headers }, {}, // res object is not necessary as it's not actually used.
|
|
9
7
|
imageParams, nextConfig, false, // not in dev mode
|
|
8
|
+
// @ts-expect-error - This file is used only for Next 14.1 and below. Typing is correct for these versions.
|
|
10
9
|
handleRequest);
|
|
11
10
|
debug("optimized result", result);
|
|
12
11
|
return result;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
|
+
/// <reference types="node" />
|
|
3
4
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
4
5
|
import type { APIGatewayProxyEventHeaders } from "aws-lambda";
|
|
5
6
|
import type { NextConfig } from "next/dist/server/config-shared";
|
|
@@ -8,4 +9,6 @@ export declare function optimizeImage(headers: APIGatewayProxyEventHeaders, imag
|
|
|
8
9
|
buffer: Buffer;
|
|
9
10
|
contentType: string;
|
|
10
11
|
maxAge: number;
|
|
12
|
+
etag: string;
|
|
13
|
+
upstreamEtag: string;
|
|
11
14
|
}>;
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
//#override imports
|
|
2
|
-
import {
|
|
3
|
-
// @ts-ignore
|
|
4
|
-
fetchExternalImage,
|
|
5
|
-
// @ts-ignore
|
|
6
|
-
fetchInternalImage, imageOptimizer, } from "next/dist/server/image-optimizer";
|
|
2
|
+
import { fetchExternalImage, fetchInternalImage, imageOptimizer, } from "next/dist/server/image-optimizer";
|
|
7
3
|
import { debug } from "../../logger.js";
|
|
8
4
|
//#override optimizeImage
|
|
9
5
|
export async function optimizeImage(headers, imageParams, nextConfig, handleRequest) {
|
|
@@ -11,11 +7,12 @@ export async function optimizeImage(headers, imageParams, nextConfig, handleRequ
|
|
|
11
7
|
const imageUpstream = isAbsolute
|
|
12
8
|
? await fetchExternalImage(href)
|
|
13
9
|
: await fetchInternalImage(href,
|
|
14
|
-
// @ts-
|
|
10
|
+
// @ts-expect-error - It is supposed to be an IncomingMessage object, but only the headers are used.
|
|
15
11
|
{ headers }, {}, // res object is not necessary as it's not actually used.
|
|
16
12
|
handleRequest);
|
|
13
|
+
const result = await imageOptimizer(imageUpstream, imageParams,
|
|
17
14
|
// @ts-ignore
|
|
18
|
-
|
|
15
|
+
nextConfig, false);
|
|
19
16
|
debug("optimized result", result);
|
|
20
17
|
return result;
|
|
21
18
|
}
|
|
@@ -1,78 +1,13 @@
|
|
|
1
1
|
import { createGenericHandler } from "../core/createGenericHandler.js";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveWarmerInvoke } from "../core/resolve.js";
|
|
3
3
|
import { generateUniqueId } from "./util.js";
|
|
4
|
-
const resolveWarmerInvoke = async () => {
|
|
5
|
-
const openNextParams = globalThis.openNextConfig.warmer;
|
|
6
|
-
if (typeof openNextParams?.invokeFunction === "function") {
|
|
7
|
-
return await openNextParams.invokeFunction();
|
|
8
|
-
}
|
|
9
|
-
else {
|
|
10
|
-
return Promise.resolve({
|
|
11
|
-
name: "aws-invoke",
|
|
12
|
-
invoke: async (warmerId) => {
|
|
13
|
-
const { InvokeCommand, LambdaClient } = await import("@aws-sdk/client-lambda");
|
|
14
|
-
const lambda = new LambdaClient({});
|
|
15
|
-
const warmParams = JSON.parse(process.env.WARM_PARAMS);
|
|
16
|
-
for (const warmParam of warmParams) {
|
|
17
|
-
const { concurrency: CONCURRENCY, function: FUNCTION_NAME } = warmParam;
|
|
18
|
-
debug({
|
|
19
|
-
event: "warmer invoked",
|
|
20
|
-
functionName: FUNCTION_NAME,
|
|
21
|
-
concurrency: CONCURRENCY,
|
|
22
|
-
warmerId,
|
|
23
|
-
});
|
|
24
|
-
const ret = await Promise.all(Array.from({ length: CONCURRENCY }, (_v, i) => i).map((i) => {
|
|
25
|
-
try {
|
|
26
|
-
return lambda.send(new InvokeCommand({
|
|
27
|
-
FunctionName: FUNCTION_NAME,
|
|
28
|
-
InvocationType: "RequestResponse",
|
|
29
|
-
Payload: Buffer.from(JSON.stringify({
|
|
30
|
-
type: "warmer",
|
|
31
|
-
warmerId,
|
|
32
|
-
index: i,
|
|
33
|
-
concurrency: CONCURRENCY,
|
|
34
|
-
delay: 75,
|
|
35
|
-
})),
|
|
36
|
-
}));
|
|
37
|
-
}
|
|
38
|
-
catch (e) {
|
|
39
|
-
error(`failed to warm up #${i}`, e);
|
|
40
|
-
// ignore error
|
|
41
|
-
}
|
|
42
|
-
}));
|
|
43
|
-
// Print status
|
|
44
|
-
const warmedServerIds = ret
|
|
45
|
-
.map((r, i) => {
|
|
46
|
-
if (r?.StatusCode !== 200 || !r?.Payload) {
|
|
47
|
-
error(`failed to warm up #${i}:`, r?.Payload?.toString());
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
const payload = JSON.parse(Buffer.from(r.Payload).toString());
|
|
51
|
-
return {
|
|
52
|
-
statusCode: r.StatusCode,
|
|
53
|
-
payload,
|
|
54
|
-
type: "warmer",
|
|
55
|
-
};
|
|
56
|
-
})
|
|
57
|
-
.filter((r) => !!r);
|
|
58
|
-
debug({
|
|
59
|
-
event: "warmer result",
|
|
60
|
-
sent: CONCURRENCY,
|
|
61
|
-
success: warmedServerIds.length,
|
|
62
|
-
uniqueServersWarmed: [...new Set(warmedServerIds)].length,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
4
|
export const handler = await createGenericHandler({
|
|
70
5
|
handler: defaultHandler,
|
|
71
6
|
type: "warmer",
|
|
72
7
|
});
|
|
73
8
|
async function defaultHandler() {
|
|
74
9
|
const warmerId = `warmer-${generateUniqueId()}`;
|
|
75
|
-
const invokeFn = await resolveWarmerInvoke();
|
|
10
|
+
const invokeFn = await resolveWarmerInvoke(globalThis.openNextConfig.warmer?.invokeFunction);
|
|
76
11
|
await invokeFn.invoke(warmerId);
|
|
77
12
|
return {
|
|
78
13
|
type: "warmer",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import cp from "node:child_process";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export function setStandaloneBuildMode(options) {
|
|
4
|
+
// Equivalent to setting `output: "standalone"` in next.config.js
|
|
5
|
+
process.env.NEXT_PRIVATE_STANDALONE = "true";
|
|
6
|
+
// Equivalent to setting `experimental.outputFileTracingRoot` in next.config.js
|
|
7
|
+
process.env.NEXT_PRIVATE_OUTPUT_TRACE_ROOT = options.monorepoRoot;
|
|
8
|
+
}
|
|
9
|
+
export function buildNextjsApp(options) {
|
|
10
|
+
const { config, packager } = options;
|
|
11
|
+
const command = config.buildCommand ??
|
|
12
|
+
(["bun", "npm"].includes(packager)
|
|
13
|
+
? `${packager} run build`
|
|
14
|
+
: `${packager} build`);
|
|
15
|
+
cp.execSync(command, {
|
|
16
|
+
stdio: "inherit",
|
|
17
|
+
cwd: path.dirname(options.appPackageJsonPath),
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createRequire
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
2
|
import { build } from "esbuild";
|
|
3
3
|
import path from "path";
|
|
4
4
|
const externals = [
|
|
@@ -36,7 +36,7 @@ const externals = [
|
|
|
36
36
|
"next/dist/compiled/next-server",
|
|
37
37
|
];
|
|
38
38
|
export async function bundleNextServer(outputDir, appPath) {
|
|
39
|
-
const require =
|
|
39
|
+
const require = createRequire(`${appPath}/package.json`);
|
|
40
40
|
const entrypoint = require.resolve("next/dist/esm/server/next-server.js");
|
|
41
41
|
await build({
|
|
42
42
|
entryPoints: [entrypoint],
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as buildHelper from "./helper.js";
|
|
2
|
+
/**
|
|
3
|
+
* Compiles the cache adapter.
|
|
4
|
+
*
|
|
5
|
+
* @param options Build options.
|
|
6
|
+
* @param format Output format.
|
|
7
|
+
* @returns The path to the compiled file.
|
|
8
|
+
*/
|
|
9
|
+
export declare function compileCache(options: buildHelper.BuildOptions, format?: "cjs" | "esm"): string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import * as buildHelper from "./helper.js";
|
|
3
|
+
/**
|
|
4
|
+
* Compiles the cache adapter.
|
|
5
|
+
*
|
|
6
|
+
* @param options Build options.
|
|
7
|
+
* @param format Output format.
|
|
8
|
+
* @returns The path to the compiled file.
|
|
9
|
+
*/
|
|
10
|
+
export function compileCache(options, format = "cjs") {
|
|
11
|
+
const { config } = options;
|
|
12
|
+
const ext = format === "cjs" ? "cjs" : "mjs";
|
|
13
|
+
const outFile = path.join(options.buildDir, `cache.${ext}`);
|
|
14
|
+
const isAfter15 = buildHelper.compareSemver(options.nextVersion, "15.0.0") >= 0;
|
|
15
|
+
buildHelper.esbuildSync({
|
|
16
|
+
external: ["next", "styled-jsx", "react", "@aws-sdk/*"],
|
|
17
|
+
entryPoints: [path.join(options.openNextDistDir, "adapters", "cache.js")],
|
|
18
|
+
outfile: outFile,
|
|
19
|
+
target: ["node18"],
|
|
20
|
+
format,
|
|
21
|
+
banner: {
|
|
22
|
+
js: [
|
|
23
|
+
`globalThis.disableIncrementalCache = ${config.dangerous?.disableIncrementalCache ?? false};`,
|
|
24
|
+
`globalThis.disableDynamoDBCache = ${config.dangerous?.disableTagCache ?? false};`,
|
|
25
|
+
`globalThis.isNextAfter15 = ${isAfter15};`,
|
|
26
|
+
].join(""),
|
|
27
|
+
},
|
|
28
|
+
}, options);
|
|
29
|
+
return outFile;
|
|
30
|
+
}
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
-
import { OpenNextConfig } from "../types/open-next.js";
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { OpenNextConfig } from "../types/open-next.js";
|
|
2
|
+
/**
|
|
3
|
+
* Compiles the OpenNext configuration.
|
|
4
|
+
*
|
|
5
|
+
* The configuration is always compiled for Node.js and for the edge only if needed.
|
|
6
|
+
*
|
|
7
|
+
* @param baseDir Directory where to look for the configuration.
|
|
8
|
+
* @param openNextConfigPath Override the default configuration when provided. Relative to baseDir.
|
|
9
|
+
* @param nodeExternals Externals for the Node.js compilation.
|
|
10
|
+
* @return The configuration and the build directory.
|
|
11
|
+
*/
|
|
12
|
+
export declare function compileOpenNextConfig(baseDir: string, openNextConfigPath?: string, nodeExternals?: string): Promise<{
|
|
13
|
+
config: OpenNextConfig;
|
|
14
|
+
buildDir: string;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function compileOpenNextConfigNode(sourcePath: string, outputDir: string, externals: string[]): string;
|
|
17
|
+
export declare function compileOpenNextConfigEdge(sourcePath: string, outputDir: string, externals: string[]): void;
|
|
@@ -1,19 +1,52 @@
|
|
|
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");
|
|
8
45
|
//Check if open-next.config.ts exists
|
|
9
46
|
if (!fs.existsSync(sourcePath)) {
|
|
10
47
|
//Create a simple open-next.config.mjs file
|
|
11
48
|
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"));
|
|
49
|
+
fs.writeFileSync(outputPath, "export default { default: { } };");
|
|
17
50
|
}
|
|
18
51
|
else {
|
|
19
52
|
buildSync({
|
|
@@ -22,7 +55,7 @@ export function compileOpenNextConfigNode(tempDir, openNextConfigPath, nodeExter
|
|
|
22
55
|
bundle: true,
|
|
23
56
|
format: "esm",
|
|
24
57
|
target: ["node18"],
|
|
25
|
-
external:
|
|
58
|
+
external: externals,
|
|
26
59
|
platform: "node",
|
|
27
60
|
banner: {
|
|
28
61
|
js: [
|
|
@@ -36,29 +69,18 @@ export function compileOpenNextConfigNode(tempDir, openNextConfigPath, nodeExter
|
|
|
36
69
|
}
|
|
37
70
|
return outputPath;
|
|
38
71
|
}
|
|
39
|
-
export function compileOpenNextConfigEdge(
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
}
|
|
72
|
+
export function compileOpenNextConfigEdge(sourcePath, outputDir, externals) {
|
|
73
|
+
const outputPath = path.join(outputDir, "open-next.config.edge.mjs");
|
|
74
|
+
logger.info("Compiling open-next.config.ts for edge runtime.", outputPath);
|
|
75
|
+
buildSync({
|
|
76
|
+
entryPoints: [sourcePath],
|
|
77
|
+
outfile: outputPath,
|
|
78
|
+
bundle: true,
|
|
79
|
+
format: "esm",
|
|
80
|
+
target: ["es2020"],
|
|
81
|
+
conditions: ["worker", "browser"],
|
|
82
|
+
platform: "browser",
|
|
83
|
+
external: externals,
|
|
84
|
+
});
|
|
85
|
+
logger.info("Compiled open-next.config.ts for edge runtime.");
|
|
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
|
+
}
|