【问题标题】:NextJS - how to render pages in SSR mode on one environment and Static pages on another environmentNextJS - 如何在一个环境中以 SSR 模式呈现页面,在另一个环境中呈现静态页面
【发布时间】:2021-11-06 22:01:23
【问题描述】:

我有一个环境(我的)上的 Strapi 后端和一个托管在 Vercel 上的 NextJS 前端。 我的客户在 Google Cloud 上拥有相同的 Strapi 后端代码,并且在某处托管了相同的前端代码。 我托管的是预生产环境,我的客户托管的是生产环境。

当我在 NextJS 应用程序的某些页面上激活静态生成时,由于我的 Strapi 后端服务器很小/速度很慢,我达到了 RAM 的限制并且我的后端崩溃了。 我还想为我的预生产环境保留服务器端渲染,因为它在贡献内容时很有用,因为你可以立即看到你的贡献。

我的客户端没有任何 RAM 限制,所以 我正在尝试使用 NODE_ENV 使我的 NextJS 应用程序页面在生产环境中以静态模式构建,并在我的环境中以服务器端渲染模式构建(预生产)

但关键是 NextJS 不允许我这样做:

if (process.env.NODE_ENV === 'production_static') {
  export const getStaticProps = async (ctx) => {...};
} else {
  export const getServerSideProps = async (ctx) => {...};
}

因为导入/导出应该在顶层。 我进行了研究并尝试使用 require() 要求一个或另一个函数,并进行了许多其他测试,但我没有解决方案,除了每次将新版本的代码交付给我的客户进行部署时编辑代码到生产环境...写 getStaticProps 而不是 getServerSideProps...witch 是浪费时间。

是否有使用代码解决此问题的解决方案(我的意思是在一个环境中部署静态,在另一个环境中部署 SSR)?还是我应该考虑升级我的服务器(女巫要花很多钱)?

谢谢!

【问题讨论】:

  • 究竟是什么导致了 RAM 问题?是不是你在 Next.js 应用中要构建的页面太多?
  • 这实际上有两个原因:首先是因为在构建期间 Vercel 向我的后端服务器发送大量请求以查询数据以生成页面。但主要原因是因为 Vercel 女巫在 NextJS getStaticProps + revalidate: XX 上有一个错误。我发现,如果您不在 NextJS 链接上添加 prefetch={false},Vercel 会为页面上存在的链接所针对的每个页面触发新的静态生成,而无需等待重新验证道具的 X 秒。这导致对我的后端服务器的调用如此之多。将 prefetch 设置为 false 我不再有麻烦了。

标签: javascript reactjs ecmascript-6 next.js devops


【解决方案1】:

我认为你可以:
A)
创建 2 个页面,一个带有 getStaticPropsmyPage.js 和一个带有 getServerSideProps (SSR.myPage.js)
next.config.js 内部,您可以根据环境变量处理重定向:

module.exports = {
...
    async redirects() {
        const instancetype = process.env.INSTACE_TYPE
        if (instacetype !== 'production_static') {
            return [
                {
                    source: '/myPage',
                    destination: '/SSR.myPage.js',
                    permanent: true,
                },
            ]
        }
        return []
    }
...
}

B)
而不是使用getServerSideProps 使用getInitialProps(仍然是SSR)这个技巧:

const MygetStaticProps = async (context) => {
  console.log("MygetStaticProps");
  return { props: {} };
};

export const getStaticProps = PROD === "production_static" ? MygetStaticProps : undefined;

if (PROD !== "production_static") {
  console.log("SSR");
  MyPage.getInitialProps = async () => {
    return {
      props: {}
    };
  };
}

所以如果PROD === "production_static" getInitialProps 永远不会被执行,页面将是静态的。

如果PROD !== "production_static" getStaticProps 将未定义(next.js 摇树应该防止导入未使用的代码),并且getInitialProps 将被执行。

【讨论】:

  • 谢谢尼科。解决方案 B 在静态生成时有效。但是当我通过 getInitialProps(激活 SSR 变量)时,没有更多数据传递给我的组件,即使我可以在 getInitialProps 中记录这些数据。在 getInitialProps 以这种方式使用时,我也失去了我的 ctx.router.locale 和 ctx.locale 对象... Finnaly,我不认为解决方案 A 对我来说是一个解决方案,因为如果我在 Vercel 上推送我的代码,那么它将生成页面的静态加 ssr 版本,生成静态版本会使我的后端服务器崩溃。但是谢谢,这是值得探索的想法。
【解决方案2】:

我实际上发现了如何绕过我的问题,例如后端服务器过载。

实际上,Vercel 在与 revalidate: xxx 一起使用 NextJS getStaticProps 时存在一个错误(revalidate 选项允许 NextJS 在数据过时时重新生成页面并交付新的下一个用户的静态页面版本,如果数据发生变化,则在 X 秒后)。

在 Vercel 主机上,如果您不向 NextJS 链接添加 prefetch={false},Vercel 将触发所有目标页面的新静态生成通过您的 NextJS 链接,无需等待您在 getStaticProps 函数的 revalidate 选项中指定的 X 秒,导致对后端服务器的数百或数千次调用以查询数据......这是一个 Vercel 错误。

修复此问题后,我已经能够构建我的网站并在其上导航,而不会使我的后端服务器超载!

【讨论】:

    猜你喜欢
    • 2010-10-13
    • 2011-09-20
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 2011-06-09
    • 2019-10-14
    • 2014-02-09
    • 1970-01-01
    相关资源
    最近更新 更多