@opennextjs/aws 3.6.2 → 3.6.3
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 +2 -0
- package/dist/adapters/config/index.d.ts +1 -0
- package/dist/adapters/config/index.js +2 -2
- package/dist/adapters/config/util.d.ts +1 -1
- package/dist/build/copyTracedFiles.d.ts +2 -2
- package/dist/core/routing/matcher.js +5 -1
- package/dist/core/routing/routeMatcher.d.ts +0 -1
- package/dist/core/routing/routeMatcher.js +29 -4
- package/dist/core/routingHandler.js +11 -9
- package/dist/overrides/imageLoader/fs-dev.js +5 -1
- package/dist/overrides/wrappers/express-dev.js +4 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -96,6 +96,8 @@ To run `OpenNext` locally:
|
|
|
96
96
|
path/to/opennextjs-aws/packages/open-next/dist/index.js build
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
There is also a way to run OpenNext locally. You can read a guide about it [here](https://opennext.js.org/aws/contribute/local_run). Its mostly used for development/debugging purposes.
|
|
100
|
+
|
|
99
101
|
### Coldstart
|
|
100
102
|
|
|
101
103
|
OpenNext provide you with a warmer function that can be used to reduce cold start.
|
|
@@ -23,6 +23,7 @@ export declare const RoutesManifest: {
|
|
|
23
23
|
};
|
|
24
24
|
export declare const ConfigHeaders: import("../../types/next-types").Header[] | undefined;
|
|
25
25
|
export declare const PrerenderManifest: import("../../types/next-types").PrerenderManifest;
|
|
26
|
+
export declare const PagesManifest: Record<string, string>;
|
|
26
27
|
export declare const AppPathsManifestKeys: string[];
|
|
27
28
|
export declare const MiddlewareManifest: import("../../types/next-types").MiddlewareManifest;
|
|
28
29
|
export declare const AppPathsManifest: Record<string, string>;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { debug } from "../logger";
|
|
3
|
-
import { loadAppPathRoutesManifest, loadAppPathsManifest, loadAppPathsManifestKeys, loadBuildId, loadConfig, loadConfigHeaders, loadFunctionsConfigManifest, loadHtmlPages, loadMiddlewareManifest, loadPrerenderManifest, loadRoutesManifest, } from "./util.js";
|
|
3
|
+
import { loadAppPathRoutesManifest, loadAppPathsManifest, loadAppPathsManifestKeys, loadBuildId, loadConfig, loadConfigHeaders, loadFunctionsConfigManifest, loadHtmlPages, loadMiddlewareManifest, loadPagesManifest, loadPrerenderManifest, loadRoutesManifest, } from "./util.js";
|
|
4
4
|
export const NEXT_DIR = path.join(__dirname, ".next");
|
|
5
5
|
export const OPEN_NEXT_DIR = path.join(__dirname, ".open-next");
|
|
6
6
|
debug({ NEXT_DIR, OPEN_NEXT_DIR });
|
|
7
|
-
//TODO: inject these values at build time
|
|
8
7
|
export const NextConfig = /* @__PURE__ */ loadConfig(NEXT_DIR);
|
|
9
8
|
export const BuildId = /* @__PURE__ */ loadBuildId(NEXT_DIR);
|
|
10
9
|
export const HtmlPages = /* @__PURE__ */ loadHtmlPages(NEXT_DIR);
|
|
@@ -13,6 +12,7 @@ export const RoutesManifest = /* @__PURE__ */ loadRoutesManifest(NEXT_DIR);
|
|
|
13
12
|
export const ConfigHeaders = /* @__PURE__ */ loadConfigHeaders(NEXT_DIR);
|
|
14
13
|
export const PrerenderManifest =
|
|
15
14
|
/* @__PURE__ */ loadPrerenderManifest(NEXT_DIR);
|
|
15
|
+
export const PagesManifest = /* @__PURE__ */ loadPagesManifest(NEXT_DIR);
|
|
16
16
|
export const AppPathsManifestKeys =
|
|
17
17
|
/* @__PURE__ */ loadAppPathsManifestKeys(NEXT_DIR);
|
|
18
18
|
export const MiddlewareManifest =
|
|
@@ -2,7 +2,7 @@ import type { FunctionsConfigManifest, MiddlewareManifest, NextConfig, Prerender
|
|
|
2
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
|
-
export declare function loadPagesManifest(nextDir: string):
|
|
5
|
+
export declare function loadPagesManifest(nextDir: string): Record<string, string>;
|
|
6
6
|
export declare function loadHtmlPages(nextDir: string): string[];
|
|
7
7
|
export declare function loadPublicAssets(openNextDir: string): PublicFiles;
|
|
8
8
|
export declare function loadRoutesManifest(nextDir: string): {
|
|
@@ -10,7 +10,7 @@ export declare function getManifests(nextDir: string): {
|
|
|
10
10
|
buildId: string;
|
|
11
11
|
config: import("../types/next-types.js").NextConfig;
|
|
12
12
|
prerenderManifest: import("../types/next-types.js").PrerenderManifest;
|
|
13
|
-
pagesManifest:
|
|
13
|
+
pagesManifest: Record<string, string>;
|
|
14
14
|
appPathsManifest: Record<string, string>;
|
|
15
15
|
middlewareManifest: import("../types/next-types.js").MiddlewareManifest;
|
|
16
16
|
functionsConfigManifest: import("../types/next-types.js").FunctionsConfigManifest;
|
|
@@ -22,7 +22,7 @@ export declare function copyTracedFiles({ buildOutputPath, packagePath, outputDi
|
|
|
22
22
|
buildId: string;
|
|
23
23
|
config: import("../types/next-types.js").NextConfig;
|
|
24
24
|
prerenderManifest: import("../types/next-types.js").PrerenderManifest;
|
|
25
|
-
pagesManifest:
|
|
25
|
+
pagesManifest: Record<string, string>;
|
|
26
26
|
appPathsManifest: Record<string, string>;
|
|
27
27
|
middlewareManifest: import("../types/next-types.js").MiddlewareManifest;
|
|
28
28
|
functionsConfigManifest: import("../types/next-types.js").FunctionsConfigManifest;
|
|
@@ -302,7 +302,11 @@ export function handleFallbackFalse(internalEvent, prerenderManifest) {
|
|
|
302
302
|
? rawPath
|
|
303
303
|
: `/${NextConfig.i18n?.defaultLocale}${rawPath}`;
|
|
304
304
|
// We need to remove the trailing slash if it exists
|
|
305
|
-
if (
|
|
305
|
+
if (
|
|
306
|
+
// Not if localizedPath is "/" tho, because that would not make it find `isPregenerated` below since it would be try to match an empty string.
|
|
307
|
+
localizedPath !== "/" &&
|
|
308
|
+
NextConfig.trailingSlash &&
|
|
309
|
+
localizedPath.endsWith("/")) {
|
|
306
310
|
localizedPath = localizedPath.slice(0, -1);
|
|
307
311
|
}
|
|
308
312
|
const matchedStaticRoute = staticRouteMatcher(localizedPath);
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { AppPathRoutesManifest, RoutesManifest } from "../../adapters/config/index";
|
|
1
|
+
import { AppPathRoutesManifest, PagesManifest, RoutesManifest, } from "../../adapters/config/index";
|
|
2
2
|
// Add the locale prefix to the regex so we correctly match the rawPath
|
|
3
3
|
const optionalLocalePrefixRegex = `^/(?:${RoutesManifest.locales.map((locale) => `${locale}/?`).join("|")})?`;
|
|
4
4
|
// Add the basepath prefix to the regex so we correctly match the rawPath
|
|
5
5
|
const optionalBasepathPrefixRegex = RoutesManifest.basePath
|
|
6
6
|
? `^${RoutesManifest.basePath}/?`
|
|
7
7
|
: "^/";
|
|
8
|
-
// Add the basePath prefix to the api routes
|
|
9
|
-
export const apiPrefix = `${RoutesManifest.basePath ?? ""}/api`;
|
|
10
8
|
const optionalPrefix = optionalLocalePrefixRegex.replace("^/", optionalBasepathPrefixRegex);
|
|
11
9
|
function routeMatcher(routeDefinitions) {
|
|
12
10
|
const regexp = routeDefinitions.map((route) => ({
|
|
@@ -41,5 +39,32 @@ function routeMatcher(routeDefinitions) {
|
|
|
41
39
|
});
|
|
42
40
|
};
|
|
43
41
|
}
|
|
44
|
-
export const staticRouteMatcher = routeMatcher(
|
|
42
|
+
export const staticRouteMatcher = routeMatcher([
|
|
43
|
+
...RoutesManifest.routes.static,
|
|
44
|
+
...getStaticAPIRoutes(),
|
|
45
|
+
]);
|
|
45
46
|
export const dynamicRouteMatcher = routeMatcher(RoutesManifest.routes.dynamic);
|
|
47
|
+
/**
|
|
48
|
+
* Returns static API routes for both app and pages router cause Next will filter them out in staticRoutes in `routes-manifest.json`.
|
|
49
|
+
* We also need to filter out page files that are under `app/api/*` as those would not be present in the routes manifest either.
|
|
50
|
+
* This line from Next.js skips it:
|
|
51
|
+
* https://github.com/vercel/next.js/blob/ded56f952154a40dcfe53bdb38c73174e9eca9e5/packages/next/src/build/index.ts#L1299
|
|
52
|
+
*
|
|
53
|
+
* Without it handleFallbackFalse will 404 on static API routes if there is a catch-all route on root level.
|
|
54
|
+
*/
|
|
55
|
+
function getStaticAPIRoutes() {
|
|
56
|
+
const createRouteDefinition = (route) => ({
|
|
57
|
+
page: route,
|
|
58
|
+
regex: `^${route}(?:/)?$`,
|
|
59
|
+
});
|
|
60
|
+
const dynamicRoutePages = new Set(RoutesManifest.routes.dynamic.map(({ page }) => page));
|
|
61
|
+
const pagesStaticAPIRoutes = Object.keys(PagesManifest)
|
|
62
|
+
.filter((route) => route.startsWith("/api/") && !dynamicRoutePages.has(route))
|
|
63
|
+
.map(createRouteDefinition);
|
|
64
|
+
// We filter out both static API and page routes from the app paths manifest
|
|
65
|
+
const appPathsStaticAPIRoutes = Object.values(AppPathRoutesManifest)
|
|
66
|
+
.filter((route) => route.startsWith("/api/") ||
|
|
67
|
+
(route === "/api" && !dynamicRoutePages.has(route)))
|
|
68
|
+
.map(createRouteDefinition);
|
|
69
|
+
return [...pagesStaticAPIRoutes, ...appPathsStaticAPIRoutes];
|
|
70
|
+
}
|
|
@@ -4,7 +4,7 @@ import { cacheInterceptor } from "./routing/cacheInterceptor";
|
|
|
4
4
|
import { detectLocale } from "./routing/i18n";
|
|
5
5
|
import { fixDataPage, getNextConfigHeaders, handleFallbackFalse, handleRedirects, handleRewrites, } from "./routing/matcher";
|
|
6
6
|
import { handleMiddleware } from "./routing/middleware";
|
|
7
|
-
import {
|
|
7
|
+
import { dynamicRouteMatcher, staticRouteMatcher, } from "./routing/routeMatcher";
|
|
8
8
|
import { constructNextUrl } from "./routing/util";
|
|
9
9
|
export const MIDDLEWARE_HEADER_PREFIX = "x-middleware-response-";
|
|
10
10
|
export const MIDDLEWARE_HEADER_PREFIX_LEN = MIDDLEWARE_HEADER_PREFIX.length;
|
|
@@ -55,6 +55,9 @@ export default async function routingHandler(event) {
|
|
|
55
55
|
}
|
|
56
56
|
const redirect = handleRedirects(internalEvent, RoutesManifest.redirects);
|
|
57
57
|
if (redirect) {
|
|
58
|
+
// We need to encode the value in the Location header to make sure it is valid according to RFC
|
|
59
|
+
// https://stackoverflow.com/a/7654605/16587222
|
|
60
|
+
redirect.headers.Location = new URL(redirect.headers.Location).href;
|
|
58
61
|
debug("redirect", redirect);
|
|
59
62
|
return redirect;
|
|
60
63
|
}
|
|
@@ -85,9 +88,14 @@ export default async function routingHandler(event) {
|
|
|
85
88
|
internalEvent = afterRewrites.internalEvent;
|
|
86
89
|
isExternalRewrite = afterRewrites.isExternalRewrite;
|
|
87
90
|
}
|
|
91
|
+
let isISR = false;
|
|
88
92
|
// We want to run this just before the dynamic route check
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
// We can skip it if its an external rewrite
|
|
94
|
+
if (!isExternalRewrite) {
|
|
95
|
+
const fallbackResult = handleFallbackFalse(internalEvent, PrerenderManifest);
|
|
96
|
+
internalEvent = fallbackResult.event;
|
|
97
|
+
isISR = fallbackResult.isISR;
|
|
98
|
+
}
|
|
91
99
|
const foundDynamicRoute = dynamicRouteMatcher(internalEvent.rawPath);
|
|
92
100
|
const isDynamicRoute = !isExternalRewrite && foundDynamicRoute.length > 0;
|
|
93
101
|
if (!(isDynamicRoute || isStaticRoute || isExternalRewrite)) {
|
|
@@ -96,17 +104,11 @@ export default async function routingHandler(event) {
|
|
|
96
104
|
internalEvent = fallbackRewrites.internalEvent;
|
|
97
105
|
isExternalRewrite = fallbackRewrites.isExternalRewrite;
|
|
98
106
|
}
|
|
99
|
-
// Api routes are not present in the routes manifest except if they're not behind /api
|
|
100
|
-
// /api even if it's a page route doesn't get generated in the manifest
|
|
101
|
-
// Ideally we would need to properly check api routes here
|
|
102
|
-
const isApiRoute = internalEvent.rawPath === apiPrefix ||
|
|
103
|
-
internalEvent.rawPath.startsWith(`${apiPrefix}/`);
|
|
104
107
|
const isNextImageRoute = internalEvent.rawPath.startsWith("/_next/image");
|
|
105
108
|
const isRouteFoundBeforeAllRewrites = isStaticRoute || isDynamicRoute || isExternalRewrite;
|
|
106
109
|
// If we still haven't found a route, we show the 404 page
|
|
107
110
|
// We need to ensure that rewrites are applied before showing the 404 page
|
|
108
111
|
if (!(isRouteFoundBeforeAllRewrites ||
|
|
109
|
-
isApiRoute ||
|
|
110
112
|
isNextImageRoute ||
|
|
111
113
|
// We need to check again once all rewrites have been applied
|
|
112
114
|
staticRouteMatcher(internalEvent.rawPath).length > 0 ||
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { NextConfig } from "../../adapters/config/index";
|
|
3
4
|
import { getMonorepoRelativePath } from "../../utils/normalize-path";
|
|
4
5
|
export default {
|
|
5
6
|
name: "fs-dev",
|
|
6
7
|
load: async (url) => {
|
|
7
|
-
const
|
|
8
|
+
const urlWithoutBasePath = NextConfig.basePath
|
|
9
|
+
? url.slice(NextConfig.basePath.length)
|
|
10
|
+
: url;
|
|
11
|
+
const imagePath = path.join(getMonorepoRelativePath(), "assets", urlWithoutBasePath);
|
|
8
12
|
const body = fs.createReadStream(imagePath);
|
|
9
13
|
const contentType = url.endsWith(".png") ? "image/png" : "image/jpeg";
|
|
10
14
|
return {
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import express from "express";
|
|
3
|
+
import { NextConfig } from "../../adapters/config/index";
|
|
3
4
|
import { getMonorepoRelativePath } from "../../utils/normalize-path";
|
|
4
5
|
const wrapper = async (handler, converter) => {
|
|
5
6
|
const app = express();
|
|
6
7
|
// To serve static assets
|
|
7
|
-
|
|
8
|
+
const basePath = NextConfig.basePath ?? "";
|
|
9
|
+
app.use(basePath, express.static(path.join(getMonorepoRelativePath(), "assets")));
|
|
8
10
|
const imageHandlerPath = path.join(getMonorepoRelativePath(), "image-optimization-function/index.mjs");
|
|
9
11
|
const imageHandler = await import(imageHandlerPath).then((m) => m.handler);
|
|
10
|
-
app.all("/_next/image
|
|
12
|
+
app.all(`${NextConfig.basePath ?? ""}/_next/image`, async (req, res) => {
|
|
11
13
|
const internalEvent = await converter.convertFrom(req);
|
|
12
14
|
const streamCreator = {
|
|
13
15
|
writeHeaders: (prelude) => {
|