调试模式
可以通过设置环境变量 OPEN_NEXT_DEBUG=true 以调试模式执行 OpenNext。
这将向控制台输出 大量 额外日志。这还会禁用 esbuild 中的压缩,并向输出添加源地图。这可能导致代码大小达到生产构建的 2-3 倍。不要在生产环境中启用此功能
OPEN_NEXT_DEBUG=true npx open-next@latest build找不到模块 next
你可能会在 CloudWatch 日志中遇到此错误:Cannot find module 'next'。很可能你处于一个 monorepo 中,并且有多个 lock 文件。只需确保在项目根目录下只有一个 lock 文件。
减小 bundle 大小
Next 可能会错误地将某些依赖项包含在 bundle 中。要移除它们,你可以在 next.config.js 中使用此配置:
outputFileTracingExcludes: { // 或在 Next < 15 上使用 experimental.outputFileTracingExcludes
"*": ["node_modules/the-unwanted-package"],
},除非绝对必要,否则也不应将 sharp 添加为依赖项,图像优化已经拥有自己的 sharp 版本。默认情况下,OpenNext 排除以下包:
caniuse-litesharp@imgtypescriptnext/dist/compiled/babelnext/dist/compiled/babel-packagesnext/dist/compiled/amphtml-validator
移除 sourcemaps
Source maps 可能会大幅增加 bundle 大小,将它们从 standalone 输出中排除可能是值得的。 例如,Sentry 不会移除服务器端 sourcemaps,只移除客户端的,即使 "deleteSourcemapsAfterUpload" 为 true。查看 Sentry 源代码 (opens in a new tab)。
你可以类似地排除 sourcemaps:
outputFileTracingExcludes: {
"*": [
'./**/*.js.map',
'./**/*.mjs.map',
'./**/*.cjs.map'
],
},修补 ISR 的 fetch 行为。仅适用于 next@13.5.1+
如果你在应用中使用 ISR 和 fetch,可能会遇到一个导致 revalidate 值不一致的 bug。 问题在于它使用页面中所有 fetch 调用的最低 revalidate 值进行重新验证,不管它们各自的值如何。要修复此 bug,你需要使用以下代码片段修改根布局组件中的 fetch 函数
export default function RootLayout() {
const asyncStorage = require('next/dist/client/components/static-generation-async-storage.external');
//@ts-ignore
const staticStore =
(fetch as any).__nextGetStaticStore?.() ||
asyncStorage.staticGenerationAsyncStorage;
const store = staticStore.getStore();
store.isOnDemandRevalidate =
store.isOnDemandRevalidate && !(process.env.OPEN_NEXT_ISR === 'true');
return <>...</>;
}页面刷新和直接 URL 访问时路由上的 Access Denied 错误
如果你正在刷新动态/静态路由或直接从 URL 进入该路由。例如此路由:
/profile/[userId]/[id],并且你在 XML 中收到 Access Denied 错误:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>R4E6T9G2Q1S0Z5X8</RequestId>
<HostId>S7h9F3g2T0z5K8d6A2s1W4x3C7v8B9m2L0j3K4i7H8g9F0r3A5q8w9E8r7t6Y5h4U3i2O1p0</HostId>
</Error>当客户端通过 NextJS <Link> 组件导航时,这也可能发生在 app router 中。
问题可能是你的 public 目录中有一个文件夹或文件,其名称与你的路由重叠。在这种情况下,你应该将其重命名为其他名称。
cannot find module './chunks/xxxx.js' 错误
instrumentation.ts 中的动态导入将在运行时导致此错误。移除动态导入以解决。
Sentry 服务器端设置
Sentry 文档推荐的配置在 instrumentation.ts 中使用动态导入,这会导致上述错误。
这是一个可以解决错误的可用 Sentry 配置:
instrumentation.ts
import * as Sentry from "@sentry/nextjs";
import { initSentry } from "../sentry.server.config";
export const onRequestError = Sentry.captureRequestError;
export async function register() {
initSentry(process.env.NEXT_RUNTIME as "nodejs" | "edge");
}sentry.server.config.ts
import * as Sentry from "@sentry/nextjs";
export const initSentry = (runtime: "nodejs" | "edge") => {
Sentry.init({
dsn: "https://...",
//...配置的其余部分
});
};在 AWS Lambda 中流式传输时响应体为空
我们过去曾遇到当响应体为空时,AWS Lambda 中的流式传输挂起的问题。
我们目前在 OpenNext 中有一个变通方法,即将环境变量 OPEN_NEXT_FORCE_NON_EMPTY_RESPONSE 设置为 true。
这将向流中写入一些内容以确保其不为空。
Yarn Plug'n'Play manifest 禁止在此处导入 "xxx",因为它未列为此包的依赖项
此错误通常通过移除仓库中的所有 yarn 文件来解决。你还应该查看 package.json,看看是否将 yarn 设置为 packageManager。移除它将解决问题。
如果你使用 yarn,有一个变通方法 在此处 (opens in a new tab)。
如果你没有使用 yarn 却看到 yarn 相关错误,可以通过运行 corepack disable 或将 nvm 更新到 0.40.2 来解决。
我的 bundle 中缺少文件/依赖项
有时你的服务器函数 bundle 中可能会缺少文件。例如可能是 sentry.server.config.ts。它可以是任何文件或目录,也接受通配符。在 Next 中有一个选项可以包含未被 tracing 拾取的文件。
它叫做 outputFileTracingIncludes。以下是在 next.config.ts 中如何使用它的示例:
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* 这里的配置选项 */
outputFileTracingIncludes: {
"*": ["sentry.server.config.ts"],
// 也可以是通配符模式
"/api/*": ["node_modules/.prisma/client/**/*"],
},
};
export default nextConfig;这将把文件复制到 .open-next/server-functions/default/sentry.server.config.ts,或者在本例中复制到每个分割的函数。
要了解更多关于 outputFileTracingIncludes 的信息,你可以参考 Next.js 文档 (opens in a new tab)。
它也适用于 OpenNext 中的函数分割。如果你的键对应于特定路由(即:api/test),它将仅包含在该路由的函数 bundle 中。
然而,使用 * 作为键将其包含在每个函数 bundle 中。这是一个带有函数分割的示例:
// open-next.config.ts
import type { OpenNextConfig } from "@opennextjs/aws/types/open-next";
const config = {
default: {},
functions: {
extraFunction: {
patterns: ["api/test"],
// 这是将在此函数中使用的路由
routes: ["app/api/test/route"],
override: {
wrapper: "aws-lambda-streaming",
},
},
},
} satisfies OpenNextConfig;
// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
outputFileTracingIncludes: {
// 这些文件将仅复制到 extraFunction bundle
"/api/test": ["sentry.config.ts", "node_modules/.prisma/client/**/*"],
},
};它也适用于 monorepo。假设你的 Next 应用在 packages/web 中,文件将被写入:packages/web/.open-next/server-functions/default/packages/web/*