@opennextjs/aws 3.5.3 → 3.5.5

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.
@@ -6,10 +6,14 @@ import type { OpenNextConfig } from "../types/open-next.js";
6
6
  *
7
7
  * @param baseDir Directory where to look for the configuration.
8
8
  * @param openNextConfigPath Override the default configuration when provided. Relative to baseDir.
9
- * @param nodeExternals Externals for the Node.js compilation.
9
+ * @param nodeExternals Coma separated list of Externals for the Node.js compilation.
10
+ * @param compileEdge Force compiling for the edge runtime when true
10
11
  * @return The configuration and the build directory.
11
12
  */
12
- export declare function compileOpenNextConfig(baseDir: string, openNextConfigPath?: string, nodeExternals?: string): Promise<{
13
+ export declare function compileOpenNextConfig(baseDir: string, openNextConfigPath?: string, { nodeExternals, compileEdge }?: {
14
+ nodeExternals?: string | undefined;
15
+ compileEdge?: boolean | undefined;
16
+ }): Promise<{
13
17
  config: OpenNextConfig;
14
18
  buildDir: string;
15
19
  }>;
@@ -11,13 +11,14 @@ import { validateConfig } from "./validateConfig.js";
11
11
  *
12
12
  * @param baseDir Directory where to look for the configuration.
13
13
  * @param openNextConfigPath Override the default configuration when provided. Relative to baseDir.
14
- * @param nodeExternals Externals for the Node.js compilation.
14
+ * @param nodeExternals Coma separated list of Externals for the Node.js compilation.
15
+ * @param compileEdge Force compiling for the edge runtime when true
15
16
  * @return The configuration and the build directory.
16
17
  */
17
- export async function compileOpenNextConfig(baseDir, openNextConfigPath, nodeExternals) {
18
+ export async function compileOpenNextConfig(baseDir, openNextConfigPath, { nodeExternals = "", compileEdge = false } = {}) {
18
19
  const sourcePath = path.join(baseDir, openNextConfigPath ?? "open-next.config.ts");
19
20
  const buildDir = fs.mkdtempSync(path.join(os.tmpdir(), "open-next-tmp"));
20
- let configPath = compileOpenNextConfigNode(sourcePath, buildDir, nodeExternals ? nodeExternals.split(",") : []);
21
+ let configPath = compileOpenNextConfigNode(sourcePath, buildDir, nodeExternals.split(","));
21
22
  // On Windows, we need to use file:// protocol to load the config file using import()
22
23
  if (process.platform === "win32")
23
24
  configPath = `file://${configPath}`;
@@ -31,12 +32,12 @@ export async function compileOpenNextConfig(baseDir, openNextConfigPath, nodeExt
31
32
  // If it does, we need to compile it with the edge runtime
32
33
  const usesEdgeRuntime = (config.middleware?.external && config.middleware.runtime !== "node") ||
33
34
  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
35
+ if (usesEdgeRuntime || compileEdge) {
36
+ compileOpenNextConfigEdge(sourcePath, buildDir, config.edgeExternals ?? []);
37
37
  }
38
38
  else {
39
- compileOpenNextConfigEdge(sourcePath, buildDir, config.edgeExternals ?? []);
39
+ // Skip compiling for the edge runtime.
40
+ logger.debug("No edge runtime found in the open-next.config.ts. Using default config.");
40
41
  }
41
42
  return { config, buildDir };
42
43
  }
@@ -55,12 +55,12 @@ export async function copyTracedFiles({ buildOutputPath, packagePath, outputDir,
55
55
  });
56
56
  }
57
57
  // create directory for pages
58
- if (existsSync(path.join(standaloneServerDir, "pages"))) {
58
+ if (existsSync(path.join(standaloneNextDir, "server/pages"))) {
59
59
  mkdirSync(path.join(outputNextDir, "server/pages"), {
60
60
  recursive: true,
61
61
  });
62
62
  }
63
- if (existsSync(path.join(standaloneServerDir, "app"))) {
63
+ if (existsSync(path.join(standaloneNextDir, "server/app"))) {
64
64
  mkdirSync(path.join(outputNextDir, "server/app"), {
65
65
  recursive: true,
66
66
  });
@@ -210,7 +210,7 @@ File ${fullFilePath} does not exist
210
210
  // Maybe even move this to s3 directly
211
211
  if (hasPageDir) {
212
212
  // First we get truly static files - i.e. pages without getStaticProps
213
- const staticFiles = Object.values(JSON.parse(readFileSync(path.join(standaloneServerDir, "pages-manifest.json"), "utf8")));
213
+ const staticFiles = Object.values(loadPagesManifest(standaloneNextDir));
214
214
  // Then we need to get all fallback: true dynamic routes html
215
215
  const prerenderManifest = loadPrerenderManifest(standaloneNextDir);
216
216
  const config = loadConfig(standaloneNextDir);
@@ -58,6 +58,7 @@ export async function createMiddleware(options, { forceOnlyBuildOnce = false } =
58
58
  outfile: path.join(options.buildDir, "middleware.mjs"),
59
59
  middlewareInfo: edgeMiddlewareInfo,
60
60
  options,
61
+ overrides: config.default.override,
61
62
  onlyBuildOnce: true,
62
63
  name: "middleware",
63
64
  });
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { loadMiddlewareManifest } from "../adapters/config/util.js";
3
4
  import logger from "../logger.js";
4
5
  import { minifyAll } from "../minimize-js.js";
5
6
  import { ContentUpdater } from "../plugins/content-updater.js";
@@ -9,7 +10,7 @@ import { getCrossPlatformPathRegex } from "../utils/regex.js";
9
10
  import { bundleNextServer } from "./bundleNextServer.js";
10
11
  import { compileCache } from "./compileCache.js";
11
12
  import { copyTracedFiles } from "./copyTracedFiles.js";
12
- import { generateEdgeBundle } from "./edge/createEdgeBundle.js";
13
+ import { copyMiddlewareResources, generateEdgeBundle, } from "./edge/createEdgeBundle.js";
13
14
  import * as buildHelper from "./helper.js";
14
15
  import { installDependencies } from "./installDeps.js";
15
16
  import { applyCodePatches } from "./patch/codePatcher.js";
@@ -82,25 +83,28 @@ async function generateBundle(name, options, fnOptions, codeCustomization) {
82
83
  // `.next/standalone/package/path` (ie. `.next`, `server.js`).
83
84
  // We need to output the handler file inside the package path.
84
85
  const packagePath = buildHelper.getPackagePath(options);
85
- fs.mkdirSync(path.join(outputPath, packagePath), { recursive: true });
86
+ const outPackagePath = path.join(outputPath, packagePath);
87
+ fs.mkdirSync(outPackagePath, { recursive: true });
86
88
  const ext = fnOptions.runtime === "deno" ? "mjs" : "cjs";
87
- fs.copyFileSync(path.join(options.buildDir, `cache.${ext}`), path.join(outputPath, packagePath, "cache.cjs"));
89
+ fs.copyFileSync(path.join(options.buildDir, `cache.${ext}`), path.join(outPackagePath, "cache.cjs"));
88
90
  if (fnOptions.runtime === "deno") {
89
91
  addDenoJson(outputPath, packagePath);
90
92
  }
91
93
  // Bundle next server if necessary
92
94
  const isBundled = fnOptions.experimentalBundledNextServer ?? false;
93
95
  if (isBundled) {
94
- await bundleNextServer(path.join(outputPath, packagePath), appPath, {
96
+ await bundleNextServer(outPackagePath, appPath, {
95
97
  minify: options.minify,
96
98
  });
97
99
  }
98
100
  // Copy middleware
99
101
  if (!config.middleware?.external) {
100
- fs.copyFileSync(path.join(options.buildDir, "middleware.mjs"), path.join(outputPath, packagePath, "middleware.mjs"));
102
+ fs.copyFileSync(path.join(options.buildDir, "middleware.mjs"), path.join(outPackagePath, "middleware.mjs"));
103
+ const middlewareManifest = loadMiddlewareManifest(path.join(options.appBuildOutputPath, ".next"));
104
+ copyMiddlewareResources(options, middlewareManifest.middleware["/"], outPackagePath);
101
105
  }
102
106
  // Copy open-next.config.mjs
103
- buildHelper.copyOpenNextConfig(options.buildDir, path.join(outputPath, packagePath));
107
+ buildHelper.copyOpenNextConfig(options.buildDir, outPackagePath);
104
108
  // Copy env files
105
109
  buildHelper.copyEnvFile(appBuildOutputPath, packagePath, outputPath);
106
110
  // Copy all necessary traced files
@@ -233,7 +237,7 @@ function addMonorepoEntrypoint(outputPath, packagePath) {
233
237
  // that re-exports the real handler.
234
238
  // Always use posix path for import path
235
239
  const packagePosixPath = packagePath.split(path.sep).join(path.posix.sep);
236
- fs.writeFileSync(path.join(outputPath, "index.mjs"), `export * from "./${packagePosixPath}/index.mjs";`);
240
+ fs.writeFileSync(path.join(outputPath, "index.mjs"), `export { handler } from "./${packagePosixPath}/index.mjs";`);
237
241
  }
238
242
  async function minifyServerBundle(outputDir) {
239
243
  logger.info("Minimizing server function...");
@@ -23,4 +23,8 @@ interface BuildEdgeBundleOptions {
23
23
  }
24
24
  export declare function buildEdgeBundle({ middlewareInfo, entrypoint, outfile, options, defaultConverter, overrides, additionalInject, includeCache, additionalExternals, onlyBuildOnce, name, additionalPlugins: additionalPluginsFn, }: BuildEdgeBundleOptions): Promise<void>;
25
25
  export declare function generateEdgeBundle(name: string, options: BuildOptions, fnOptions: SplittedFunctionOptions, additionalPlugins?: (contentUpdater: ContentUpdater) => Plugin[]): Promise<void>;
26
+ /**
27
+ * Copy wasm files and assets into the destDir.
28
+ */
29
+ export declare function copyMiddlewareResources(options: BuildOptions, middlewareInfo: MiddlewareInfo | undefined, destDir: string): void;
26
30
  export {};
@@ -13,7 +13,7 @@ import { getCrossPlatformPathRegex } from "../../utils/regex.js";
13
13
  import { isEdgeRuntime } from "../helper.js";
14
14
  import { copyOpenNextConfig, esbuildAsync } from "../helper.js";
15
15
  export async function buildEdgeBundle({ middlewareInfo, entrypoint, outfile, options, defaultConverter, overrides, additionalInject, includeCache, additionalExternals, onlyBuildOnce, name, additionalPlugins: additionalPluginsFn, }) {
16
- const isInCloudfare = await isEdgeRuntime(overrides);
16
+ const isInCloudflare = await isEdgeRuntime(overrides);
17
17
  function override(target) {
18
18
  return typeof overrides?.[target] === "string"
19
19
  ? overrides[target]
@@ -56,7 +56,7 @@ export async function buildEdgeBundle({ middlewareInfo, entrypoint, outfile, opt
56
56
  openNextEdgePlugins({
57
57
  middlewareInfo,
58
58
  nextDir: path.join(options.appBuildOutputPath, ".next"),
59
- isInCloudfare,
59
+ isInCloudflare,
60
60
  }),
61
61
  ...additionalPlugins,
62
62
  // The content updater plugin must be the last plugin
@@ -97,7 +97,7 @@ Object.defineProperty = function(o, p, a) {
97
97
  return defaultDefineProperty(o, p, a);
98
98
  };
99
99
 
100
- ${isInCloudfare
100
+ ${isInCloudflare
101
101
  ? ""
102
102
  : `
103
103
  const require = (await import("node:module")).createRequire(import.meta.url);
@@ -141,18 +141,7 @@ export async function generateEdgeBundle(name, options, fnOptions, additionalPlu
141
141
  throw new Error("Only one function is supported for now");
142
142
  }
143
143
  const middlewareInfo = functions[0];
144
- //Copy wasm files
145
- const wasmFiles = middlewareInfo.wasm;
146
- mkdirSync(path.join(outputDir, "wasm"), { recursive: true });
147
- for (const wasmFile of wasmFiles) {
148
- fs.copyFileSync(path.join(buildOutputDotNextDir, wasmFile.filePath), path.join(outputDir, `wasm/${wasmFile.name}.wasm`));
149
- }
150
- // Copy assets
151
- const assets = middlewareInfo.assets;
152
- mkdirSync(path.join(outputDir, "assets"), { recursive: true });
153
- for (const asset of assets) {
154
- fs.copyFileSync(path.join(buildOutputDotNextDir, asset.filePath), path.join(outputDir, `assets/${asset.name}`));
155
- }
144
+ copyMiddlewareResources(options, middlewareInfo, outputDir);
156
145
  await buildEdgeBundle({
157
146
  middlewareInfo,
158
147
  entrypoint: path.join(options.openNextDistDir, "adapters/edge-adapter.js"),
@@ -164,3 +153,16 @@ export async function generateEdgeBundle(name, options, fnOptions, additionalPlu
164
153
  additionalPlugins,
165
154
  });
166
155
  }
156
+ /**
157
+ * Copy wasm files and assets into the destDir.
158
+ */
159
+ export function copyMiddlewareResources(options, middlewareInfo, destDir) {
160
+ mkdirSync(path.join(destDir, "wasm"), { recursive: true });
161
+ for (const file of middlewareInfo?.wasm ?? []) {
162
+ fs.copyFileSync(path.join(options.appBuildOutputPath, ".next", file.filePath), path.join(destDir, `wasm/${file.name}.wasm`));
163
+ }
164
+ mkdirSync(path.join(destDir, "assets"), { recursive: true });
165
+ for (const file of middlewareInfo?.assets ?? []) {
166
+ fs.copyFileSync(path.join(options.appBuildOutputPath, ".next", file.filePath), path.join(destDir, `assets/${file.name}`));
167
+ }
168
+ }
@@ -317,7 +317,7 @@ export async function isEdgeRuntime(overrides) {
317
317
  return false;
318
318
  }
319
319
  if (typeof overrides.wrapper === "string") {
320
- return ["cloudflare-edge", "cloudflare"].includes(overrides.wrapper);
320
+ return ["cloudflare-edge", "cloudflare", "cloudflare-node"].includes(overrides.wrapper);
321
321
  }
322
322
  return (await overrides?.wrapper?.())?.edgeRuntime;
323
323
  }
package/dist/build.js CHANGED
@@ -17,7 +17,7 @@ export async function build(openNextConfigPath, nodeExternals) {
17
17
  showWarningOnWindows();
18
18
  const baseDir = process.cwd();
19
19
  const openNextDistDir = url.fileURLToPath(new URL(".", import.meta.url));
20
- const { config, buildDir } = await compileOpenNextConfig(baseDir, openNextConfigPath, nodeExternals);
20
+ const { config, buildDir } = await compileOpenNextConfig(baseDir, openNextConfigPath, { nodeExternals });
21
21
  // Initialize options
22
22
  const options = buildHelper.normalizeOptions(config, openNextDistDir, buildDir);
23
23
  logger.setLevel(options.debug ? "debug" : "info");
@@ -2,7 +2,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
2
2
  import { IncomingMessage } from "../http/index.js";
3
3
  import { runWithOpenNextRequestContext } from "../utils/promise";
4
4
  import { NextConfig } from "../adapters/config/index";
5
- import { debug, error, warn } from "../adapters/logger";
5
+ import { debug, error } from "../adapters/logger";
6
6
  import { patchAsyncStorage } from "./patchAsyncStorage";
7
7
  import { constructNextUrl, convertRes, convertToQuery, createServerResponse, } from "./routing/util";
8
8
  import routingHandler, { INTERNAL_HEADER_INITIAL_URL, INTERNAL_HEADER_RESOLVED_ROUTES, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_HEADER_PREFIX_LEN, } from "./routingHandler";
@@ -39,12 +39,7 @@ export async function openNextHandler(internalEvent, options) {
39
39
  ...internalHeaders,
40
40
  };
41
41
  //#override withRouting
42
- try {
43
- routingResult = await routingHandler(internalEvent);
44
- }
45
- catch (e) {
46
- warn("Routing failed.", e);
47
- }
42
+ routingResult = await routingHandler(internalEvent);
48
43
  //#endOverride
49
44
  const headers = "type" in routingResult
50
45
  ? routingResult.headers
@@ -1,4 +1,4 @@
1
- import { FunctionsConfigManifest, MiddlewareManifest, NextConfig, } from "../../adapters/config/index.js";
1
+ import { FunctionsConfigManifest, MiddlewareManifest, NextConfig, PrerenderManifest, } from "../../adapters/config/index.js";
2
2
  import { emptyReadableStream } from "../../utils/stream.js";
3
3
  import { localizePath } from "./i18n/index.js";
4
4
  //NOTE: we should try to avoid importing stuff from next as much as possible
@@ -24,7 +24,11 @@ function defaultMiddlewareLoader() {
24
24
  export async function handleMiddleware(internalEvent, middlewareLoader = defaultMiddlewareLoader) {
25
25
  const headers = internalEvent.headers;
26
26
  // We bypass the middleware if the request is internal
27
- if (headers["x-isr"])
27
+ // We should only do that if the request has the correct `x-prerender-revalidate` header
28
+ // The `x-prerender-revalidate` header is set at build time and should be safe to trust
29
+ if (headers["x-isr"] &&
30
+ headers["x-prerender-revalidate"] ===
31
+ PrerenderManifest.preview.previewModeId)
28
32
  return internalEvent;
29
33
  // We only need the normalizedPath to check if the middleware should run
30
34
  const normalizedPath = localizePath(internalEvent);
@@ -113,13 +117,11 @@ export async function handleMiddleware(internalEvent, middlewareLoader = default
113
117
  // If the middleware returned a Rewrite, set the `url` to the pathname of the rewrite
114
118
  // NOTE: the header was added to `req` from above
115
119
  const rewriteUrl = responseHeaders.get("x-middleware-rewrite");
116
- let rewritten = false;
117
120
  let isExternalRewrite = false;
118
121
  let middlewareQueryString = internalEvent.query;
119
122
  let newUrl = internalEvent.url;
120
123
  if (rewriteUrl) {
121
124
  newUrl = rewriteUrl;
122
- rewritten = true;
123
125
  // If not a string, it should probably throw
124
126
  if (isExternal(newUrl, internalEvent.headers.host)) {
125
127
  isExternalRewrite = true;
@@ -202,7 +202,9 @@ export function fixCacheHeaderForHtmlPages(internalEvent, headers) {
202
202
  const localizedPath = localizePath(internalEvent);
203
203
  // WORKAROUND: `NextServer` does not set cache headers for HTML pages
204
204
  // https://opennext.js.org/aws/v2/advanced/workaround#workaround-nextserver-does-not-set-cache-headers-for-html-pages
205
- if (HtmlPages.includes(localizedPath)) {
205
+ // Requests containing an `x-middleware-prefetch` header must not be cached
206
+ if (HtmlPages.includes(localizedPath) &&
207
+ !internalEvent.headers["x-middleware-prefetch"]) {
206
208
  headers[CommonHeaders.CACHE_CONTROL] =
207
209
  "public, max-age=0, s-maxage=31536000, must-revalidate";
208
210
  }
@@ -1,5 +1,5 @@
1
1
  import { BuildId, ConfigHeaders, NextConfig, PrerenderManifest, RoutesManifest, } from "../adapters/config/index";
2
- import { debug } from "../adapters/logger";
2
+ import { debug, error } from "../adapters/logger";
3
3
  import { cacheInterceptor } from "./routing/cacheInterceptor";
4
4
  import { detectLocale } from "./routing/i18n";
5
5
  import { fixDataPage, getNextConfigHeaders, handleFallbackFalse, handleRedirects, handleRewrites, } from "./routing/matcher";
@@ -32,121 +32,149 @@ function applyMiddlewareHeaders(eventHeaders, middlewareHeaders, setPrefix = tru
32
32
  });
33
33
  }
34
34
  export default async function routingHandler(event) {
35
- // Add Next geo headers
36
- for (const [openNextGeoName, nextGeoName] of Object.entries(geoHeaderToNextHeader)) {
37
- const value = event.headers[openNextGeoName];
38
- if (value) {
39
- event.headers[nextGeoName] = value;
35
+ try {
36
+ // Add Next geo headers
37
+ for (const [openNextGeoName, nextGeoName] of Object.entries(geoHeaderToNextHeader)) {
38
+ const value = event.headers[openNextGeoName];
39
+ if (value) {
40
+ event.headers[nextGeoName] = value;
41
+ }
40
42
  }
41
- }
42
- // First we remove internal headers
43
- // We don't want to allow users to set these headers
44
- for (const key of Object.keys(event.headers)) {
45
- if (key.startsWith(INTERNAL_HEADER_PREFIX) ||
46
- key.startsWith(MIDDLEWARE_HEADER_PREFIX)) {
47
- delete event.headers[key];
43
+ // First we remove internal headers
44
+ // We don't want to allow users to set these headers
45
+ for (const key of Object.keys(event.headers)) {
46
+ if (key.startsWith(INTERNAL_HEADER_PREFIX) ||
47
+ key.startsWith(MIDDLEWARE_HEADER_PREFIX)) {
48
+ delete event.headers[key];
49
+ }
48
50
  }
49
- }
50
- const nextHeaders = getNextConfigHeaders(event, ConfigHeaders);
51
- let internalEvent = fixDataPage(event, BuildId);
52
- if ("statusCode" in internalEvent) {
53
- return internalEvent;
54
- }
55
- const redirect = handleRedirects(internalEvent, RoutesManifest.redirects);
56
- if (redirect) {
57
- debug("redirect", redirect);
58
- return redirect;
59
- }
60
- const eventOrResult = await handleMiddleware(internalEvent);
61
- const isResult = "statusCode" in eventOrResult;
62
- if (isResult) {
63
- return eventOrResult;
64
- }
65
- const middlewareResponseHeaders = eventOrResult.responseHeaders;
66
- let isExternalRewrite = eventOrResult.isExternalRewrite ?? false;
67
- // internalEvent is `InternalEvent | MiddlewareEvent`
68
- internalEvent = eventOrResult;
69
- if (!isExternalRewrite) {
70
- // First rewrite to be applied
71
- const beforeRewrites = handleRewrites(internalEvent, RoutesManifest.rewrites.beforeFiles);
72
- internalEvent = beforeRewrites.internalEvent;
73
- isExternalRewrite = beforeRewrites.isExternalRewrite;
74
- }
75
- const foundStaticRoute = staticRouteMatcher(internalEvent.rawPath);
76
- const isStaticRoute = !isExternalRewrite && foundStaticRoute.length > 0;
77
- if (!(isStaticRoute || isExternalRewrite)) {
78
- // Second rewrite to be applied
79
- const afterRewrites = handleRewrites(internalEvent, RoutesManifest.rewrites.afterFiles);
80
- internalEvent = afterRewrites.internalEvent;
81
- isExternalRewrite = afterRewrites.isExternalRewrite;
82
- }
83
- // We want to run this just before the dynamic route check
84
- const { event: fallbackEvent, isISR } = handleFallbackFalse(internalEvent, PrerenderManifest);
85
- internalEvent = fallbackEvent;
86
- const foundDynamicRoute = dynamicRouteMatcher(internalEvent.rawPath);
87
- const isDynamicRoute = !isExternalRewrite && foundDynamicRoute.length > 0;
88
- if (!(isDynamicRoute || isStaticRoute || isExternalRewrite)) {
89
- // Fallback rewrite to be applied
90
- const fallbackRewrites = handleRewrites(internalEvent, RoutesManifest.rewrites.fallback);
91
- internalEvent = fallbackRewrites.internalEvent;
92
- isExternalRewrite = fallbackRewrites.isExternalRewrite;
93
- }
94
- // Api routes are not present in the routes manifest except if they're not behind /api
95
- // /api even if it's a page route doesn't get generated in the manifest
96
- // Ideally we would need to properly check api routes here
97
- const isApiRoute = internalEvent.rawPath === apiPrefix ||
98
- internalEvent.rawPath.startsWith(`${apiPrefix}/`);
99
- const isNextImageRoute = internalEvent.rawPath.startsWith("/_next/image");
100
- const isRouteFoundBeforeAllRewrites = isStaticRoute || isDynamicRoute || isExternalRewrite;
101
- // If we still haven't found a route, we show the 404 page
102
- // We need to ensure that rewrites are applied before showing the 404 page
103
- if (!(isRouteFoundBeforeAllRewrites ||
104
- isApiRoute ||
105
- isNextImageRoute ||
106
- // We need to check again once all rewrites have been applied
107
- staticRouteMatcher(internalEvent.rawPath).length > 0 ||
108
- dynamicRouteMatcher(internalEvent.rawPath).length > 0)) {
109
- internalEvent = {
110
- ...internalEvent,
111
- rawPath: "/404",
112
- url: constructNextUrl(internalEvent.url, "/404"),
113
- headers: {
114
- ...internalEvent.headers,
115
- "x-middleware-response-cache-control": "private, no-cache, no-store, max-age=0, must-revalidate",
116
- },
117
- };
118
- }
119
- if (globalThis.openNextConfig.dangerous?.enableCacheInterception &&
120
- !("statusCode" in internalEvent)) {
121
- debug("Cache interception enabled");
122
- internalEvent = await cacheInterceptor(internalEvent);
51
+ const nextHeaders = getNextConfigHeaders(event, ConfigHeaders);
52
+ let internalEvent = fixDataPage(event, BuildId);
123
53
  if ("statusCode" in internalEvent) {
124
- applyMiddlewareHeaders(internalEvent.headers, {
125
- ...middlewareResponseHeaders,
126
- ...nextHeaders,
127
- }, false);
128
54
  return internalEvent;
129
55
  }
56
+ const redirect = handleRedirects(internalEvent, RoutesManifest.redirects);
57
+ if (redirect) {
58
+ debug("redirect", redirect);
59
+ return redirect;
60
+ }
61
+ const eventOrResult = await handleMiddleware(internalEvent);
62
+ const isResult = "statusCode" in eventOrResult;
63
+ if (isResult) {
64
+ return eventOrResult;
65
+ }
66
+ const middlewareResponseHeaders = eventOrResult.responseHeaders;
67
+ let isExternalRewrite = eventOrResult.isExternalRewrite ?? false;
68
+ // internalEvent is `InternalEvent | MiddlewareEvent`
69
+ internalEvent = eventOrResult;
70
+ if (!isExternalRewrite) {
71
+ // First rewrite to be applied
72
+ const beforeRewrites = handleRewrites(internalEvent, RoutesManifest.rewrites.beforeFiles);
73
+ internalEvent = beforeRewrites.internalEvent;
74
+ isExternalRewrite = beforeRewrites.isExternalRewrite;
75
+ }
76
+ const foundStaticRoute = staticRouteMatcher(internalEvent.rawPath);
77
+ const isStaticRoute = !isExternalRewrite && foundStaticRoute.length > 0;
78
+ if (!(isStaticRoute || isExternalRewrite)) {
79
+ // Second rewrite to be applied
80
+ const afterRewrites = handleRewrites(internalEvent, RoutesManifest.rewrites.afterFiles);
81
+ internalEvent = afterRewrites.internalEvent;
82
+ isExternalRewrite = afterRewrites.isExternalRewrite;
83
+ }
84
+ // We want to run this just before the dynamic route check
85
+ const { event: fallbackEvent, isISR } = handleFallbackFalse(internalEvent, PrerenderManifest);
86
+ internalEvent = fallbackEvent;
87
+ const foundDynamicRoute = dynamicRouteMatcher(internalEvent.rawPath);
88
+ const isDynamicRoute = !isExternalRewrite && foundDynamicRoute.length > 0;
89
+ if (!(isDynamicRoute || isStaticRoute || isExternalRewrite)) {
90
+ // Fallback rewrite to be applied
91
+ const fallbackRewrites = handleRewrites(internalEvent, RoutesManifest.rewrites.fallback);
92
+ internalEvent = fallbackRewrites.internalEvent;
93
+ isExternalRewrite = fallbackRewrites.isExternalRewrite;
94
+ }
95
+ // Api routes are not present in the routes manifest except if they're not behind /api
96
+ // /api even if it's a page route doesn't get generated in the manifest
97
+ // Ideally we would need to properly check api routes here
98
+ const isApiRoute = internalEvent.rawPath === apiPrefix ||
99
+ internalEvent.rawPath.startsWith(`${apiPrefix}/`);
100
+ const isNextImageRoute = internalEvent.rawPath.startsWith("/_next/image");
101
+ const isRouteFoundBeforeAllRewrites = isStaticRoute || isDynamicRoute || isExternalRewrite;
102
+ // If we still haven't found a route, we show the 404 page
103
+ // We need to ensure that rewrites are applied before showing the 404 page
104
+ if (!(isRouteFoundBeforeAllRewrites ||
105
+ isApiRoute ||
106
+ isNextImageRoute ||
107
+ // We need to check again once all rewrites have been applied
108
+ staticRouteMatcher(internalEvent.rawPath).length > 0 ||
109
+ dynamicRouteMatcher(internalEvent.rawPath).length > 0)) {
110
+ internalEvent = {
111
+ ...internalEvent,
112
+ rawPath: "/404",
113
+ url: constructNextUrl(internalEvent.url, "/404"),
114
+ headers: {
115
+ ...internalEvent.headers,
116
+ "x-middleware-response-cache-control": "private, no-cache, no-store, max-age=0, must-revalidate",
117
+ },
118
+ };
119
+ }
120
+ if (globalThis.openNextConfig.dangerous?.enableCacheInterception &&
121
+ !("statusCode" in internalEvent)) {
122
+ debug("Cache interception enabled");
123
+ internalEvent = await cacheInterceptor(internalEvent);
124
+ if ("statusCode" in internalEvent) {
125
+ applyMiddlewareHeaders(internalEvent.headers, {
126
+ ...middlewareResponseHeaders,
127
+ ...nextHeaders,
128
+ }, false);
129
+ return internalEvent;
130
+ }
131
+ }
132
+ // We apply the headers from the middleware response last
133
+ applyMiddlewareHeaders(internalEvent.headers, {
134
+ ...middlewareResponseHeaders,
135
+ ...nextHeaders,
136
+ });
137
+ const resolvedRoutes = [
138
+ ...foundStaticRoute,
139
+ ...foundDynamicRoute,
140
+ ];
141
+ debug("resolvedRoutes", resolvedRoutes);
142
+ return {
143
+ internalEvent,
144
+ isExternalRewrite,
145
+ origin: false,
146
+ isISR,
147
+ resolvedRoutes,
148
+ initialURL: event.url,
149
+ locale: NextConfig.i18n
150
+ ? detectLocale(internalEvent, NextConfig.i18n)
151
+ : undefined,
152
+ };
153
+ }
154
+ catch (e) {
155
+ error("Error in routingHandler", e);
156
+ // In case of an error, we want to return the 500 page from Next.js
157
+ return {
158
+ internalEvent: {
159
+ type: "core",
160
+ method: "GET",
161
+ rawPath: "/500",
162
+ url: constructNextUrl(event.url, "/500"),
163
+ headers: {
164
+ ...event.headers,
165
+ },
166
+ query: event.query,
167
+ cookies: event.cookies,
168
+ remoteAddress: event.remoteAddress,
169
+ },
170
+ isExternalRewrite: false,
171
+ origin: false,
172
+ isISR: false,
173
+ resolvedRoutes: [],
174
+ initialURL: event.url,
175
+ locale: NextConfig.i18n
176
+ ? detectLocale(event, NextConfig.i18n)
177
+ : undefined,
178
+ };
130
179
  }
131
- // We apply the headers from the middleware response last
132
- applyMiddlewareHeaders(internalEvent.headers, {
133
- ...middlewareResponseHeaders,
134
- ...nextHeaders,
135
- });
136
- const resolvedRoutes = [
137
- ...foundStaticRoute,
138
- ...foundDynamicRoute,
139
- ];
140
- debug("resolvedRoutes", resolvedRoutes);
141
- return {
142
- internalEvent,
143
- isExternalRewrite,
144
- origin: false,
145
- isISR,
146
- resolvedRoutes,
147
- initialURL: event.url,
148
- locale: NextConfig.i18n
149
- ? detectLocale(internalEvent, NextConfig.i18n)
150
- : undefined,
151
- };
152
180
  }
@@ -8,7 +8,6 @@ const wrapper = async (handler, converter) => {
8
8
  res.setHeader("Set-Cookie", prelude.cookies);
9
9
  res.writeHead(prelude.statusCode, prelude.headers);
10
10
  res.flushHeaders();
11
- res.uncork();
12
11
  return res;
13
12
  },
14
13
  };
@@ -3,12 +3,12 @@ import type { MiddlewareInfo } from "../types/next-types.js";
3
3
  export interface IPluginSettings {
4
4
  nextDir: string;
5
5
  middlewareInfo?: MiddlewareInfo;
6
- isInCloudfare?: boolean;
6
+ isInCloudflare?: boolean;
7
7
  }
8
8
  /**
9
9
  * @param opts.nextDir - The path to the .next directory
10
10
  * @param opts.middlewareInfo - Information about the middleware
11
- * @param opts.isInCloudfare - Whether the code runs on the cloudflare runtime
11
+ * @param opts.isInCloudflare - Whether the code runs on the cloudflare runtime
12
12
  * @returns
13
13
  */
14
- export declare function openNextEdgePlugins({ nextDir, middlewareInfo, isInCloudfare, }: IPluginSettings): Plugin;
14
+ export declare function openNextEdgePlugins({ nextDir, middlewareInfo, isInCloudflare, }: IPluginSettings): Plugin;
@@ -7,10 +7,10 @@ import { getCrossPlatformPathRegex } from "../utils/regex.js";
7
7
  /**
8
8
  * @param opts.nextDir - The path to the .next directory
9
9
  * @param opts.middlewareInfo - Information about the middleware
10
- * @param opts.isInCloudfare - Whether the code runs on the cloudflare runtime
10
+ * @param opts.isInCloudflare - Whether the code runs on the cloudflare runtime
11
11
  * @returns
12
12
  */
13
- export function openNextEdgePlugins({ nextDir, middlewareInfo, isInCloudfare, }) {
13
+ export function openNextEdgePlugins({ nextDir, middlewareInfo, isInCloudflare, }) {
14
14
  const entryFiles = middlewareInfo?.files.map((file) => path.join(nextDir, file)) ?? [];
15
15
  const routes = middlewareInfo
16
16
  ? [
@@ -54,7 +54,7 @@ globalThis._ENTRIES = {};
54
54
  globalThis.self = globalThis;
55
55
  globalThis._ROUTES = ${JSON.stringify(routes)};
56
56
 
57
- ${isInCloudfare
57
+ ${isInCloudflare
58
58
  ? ""
59
59
  : `
60
60
  import {readFileSync} from "node:fs";
@@ -97,11 +97,7 @@ if (!globalThis.URLPattern) {
97
97
  await import("urlpattern-polyfill");
98
98
  }
99
99
  `}
100
- ${wasmFiles
101
- .map((file) => isInCloudfare
102
- ? `import ${file.name} from './wasm/${file.name}.wasm';`
103
- : `const ${file.name} = readFileSync(path.join(__dirname,'/wasm/${file.name}.wasm'));`)
104
- .join("\n")}
100
+ ${importWasm(wasmFiles, { isInCloudflare })}
105
101
  ${entryFiles.map((file) => `require("${file}");`).join("\n")}
106
102
  ${contents}
107
103
  `;
@@ -153,3 +149,17 @@ ${contents}
153
149
  },
154
150
  };
155
151
  }
152
+ function importWasm(files, { isInCloudflare }) {
153
+ return files
154
+ .map(({ name }) => {
155
+ if (isInCloudflare) {
156
+ // As `.next/server/src/middleware.js` references the name,
157
+ // using `import ${name} from '...'` would cause ESBuild to rename the import.
158
+ // We use `globalThis.${name}` to make sure `middleware.js` reference name will match.
159
+ return `import __onw_${name}__ from './wasm/${name}.wasm'
160
+ globalThis.${name} = __onw_${name}__`;
161
+ }
162
+ return `const ${name} = readFileSync(path.join(__dirname,'/wasm/${name}.wasm'));`;
163
+ })
164
+ .join("\n");
165
+ }
@@ -152,6 +152,9 @@ export interface PrerenderManifest {
152
152
  dataRouteRegex: string;
153
153
  };
154
154
  };
155
+ preview: {
156
+ previewModeId: string;
157
+ };
155
158
  }
156
159
  export type Options = {
157
160
  internalEvent: InternalEvent;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "access": "public"
4
4
  },
5
5
  "name": "@opennextjs/aws",
6
- "version": "3.5.3",
6
+ "version": "3.5.5",
7
7
  "bin": {
8
8
  "open-next": "./dist/index.js"
9
9
  },