如何最好地在 Next.js 中导入 "server-only" 代码?
How to best import "server-only" code in Next.js?
在我的索引页的getServerSideProps
函数中,我想使用一个从另一个本地文件导入的函数foo
,它依赖于某个节点库。
所述库在浏览器中不能是 运行,因为它依赖于 "server-only" 模块,例如 fs
或 request
.
我一直在使用以下模式,但想对其进行优化。将 foo
定义为可变以使其在范围内是笨拙的,而且似乎是可以避免的。
let foo;
if (typeof window === "undefined") {
foo = require("../clients/foo");
}
export default function Index({data}) {
...
}
export async function getServerSideProps() {
return {
props: {data: await foo()},
}
}
此处的最佳做法是什么?是否有可能利用 ES6 的动态导入功能?如何动态导入 within getServerSideProps
?
我正在使用 Next.js 版本 9.3.6
。
谢谢。
更新:
似乎 Next.js 自己的动态导入解决方案就是解决这个问题的方法。我仍在测试它,并会在完成后相应地更新此 post。这些文档让我感到很困惑,因为他们提到禁用 SSR 的导入,但反之亦然。
当使用 getServerSideProps
/getStaticProps
Next.js 时,将自动从客户端包中删除所有仅用于服务器的代码。浏览器上没有 运行 服务器代码的风险。
您可以使用 Next.js Code Elimination 工具来验证为客户端捆绑的内容。您会注意到 getServerSideProps
/getStaticProps
和它使用的导入一样被删除。
在 getServerSideProps
/getStaticProps
之外,我找到了 2 个非常相似的解决方案。
依靠死代码消除
在next.config.js
中:
config.plugins.push(
new webpack.DefinePlugin({
'process.env.RUNTIME_ENV': JSON.stringify(isServer ? 'server' : 'browser'),
}),
);
export const addBreadcrumb = (...params: AddBreadcrumbParams) => {
if (process.env.RUNTIME_ENV === 'server') {
return import('./sentryServer').then(({ addBreadcrumb }) => addBreadcrumb(...params));
}
return SentryBrowser.addBreadcrumb(...params);
};
请注意,由于某些原因我不明白,如果您使用 async
await
,或者如果您使用变量来存储 [= 的结果,死代码消除效果不佳18=]。我在 nextjs github.
中创建了 a discussion
告诉 webpack 忽略它
在next.config.js
if (!isServer) {
config.plugins.push(
new webpack.IgnorePlugin({
resourceRegExp: /sentryServer$/,
}),
);
}
在那种情况下,您需要确保永远不会在客户端中导入此文件,否则您会在运行时遇到错误。
在我的索引页的getServerSideProps
函数中,我想使用一个从另一个本地文件导入的函数foo
,它依赖于某个节点库。
所述库在浏览器中不能是 运行,因为它依赖于 "server-only" 模块,例如 fs
或 request
.
我一直在使用以下模式,但想对其进行优化。将 foo
定义为可变以使其在范围内是笨拙的,而且似乎是可以避免的。
let foo;
if (typeof window === "undefined") {
foo = require("../clients/foo");
}
export default function Index({data}) {
...
}
export async function getServerSideProps() {
return {
props: {data: await foo()},
}
}
此处的最佳做法是什么?是否有可能利用 ES6 的动态导入功能?如何动态导入 within getServerSideProps
?
我正在使用 Next.js 版本 9.3.6
。
谢谢。
更新:
似乎 Next.js 自己的动态导入解决方案就是解决这个问题的方法。我仍在测试它,并会在完成后相应地更新此 post。这些文档让我感到很困惑,因为他们提到禁用 SSR 的导入,但反之亦然。
当使用 getServerSideProps
/getStaticProps
Next.js 时,将自动从客户端包中删除所有仅用于服务器的代码。浏览器上没有 运行 服务器代码的风险。
您可以使用 Next.js Code Elimination 工具来验证为客户端捆绑的内容。您会注意到 getServerSideProps
/getStaticProps
和它使用的导入一样被删除。
在 getServerSideProps
/getStaticProps
之外,我找到了 2 个非常相似的解决方案。
依靠死代码消除
在next.config.js
中:
config.plugins.push(
new webpack.DefinePlugin({
'process.env.RUNTIME_ENV': JSON.stringify(isServer ? 'server' : 'browser'),
}),
);
export const addBreadcrumb = (...params: AddBreadcrumbParams) => {
if (process.env.RUNTIME_ENV === 'server') {
return import('./sentryServer').then(({ addBreadcrumb }) => addBreadcrumb(...params));
}
return SentryBrowser.addBreadcrumb(...params);
};
请注意,由于某些原因我不明白,如果您使用 async
await
,或者如果您使用变量来存储 [= 的结果,死代码消除效果不佳18=]。我在 nextjs github.
告诉 webpack 忽略它
在next.config.js
if (!isServer) {
config.plugins.push(
new webpack.IgnorePlugin({
resourceRegExp: /sentryServer$/,
}),
);
}
在那种情况下,您需要确保永远不会在客户端中导入此文件,否则您会在运行时遇到错误。