reactjs 基于请求域的服务器和客户端上的Next.js全局变量

8zzbczxx  于 2023-02-08  发布在  React
关注(0)|答案(2)|浏览(186)

我正在做一个Next.js多站点范围的项目,我需要创建一组全局变量用于客户端和服务器端(SSR期间)。
到目前为止,我来到下面的解决方案.
这是我的自定义应用程序的外观:

import App from 'next/app'
import multisite from '@utils/multisite';
import MultisiteProvider from '@components/multisite/MultisiteProvider';

function MyApp({
  Component,
  site,
  pageProps
}) {
  // Will add site props to every page
  const props = { ...pageProps, site };
  return (
    // Provider will enable a hook to get site props on any child component
    <MultisiteProvider site={ site } >
      <Component { ...props }/>
    </MultisiteProvider>
  )
}

MyApp.getInitialProps = async(appContext) => {
  // getInitialProps executes on every page access, even on client when using "next/link"

  const appProps = await App.getInitialProps(appContext);
  let host;
  if (appContext.ctx.req) {
    // Get host from request during SSR
    host = appContext.ctx.req.headers.host;
  } else {
    // Get host from window on client
    host = window.location.host;
  }

  return {
    ...appProps,
    site: await multisite.resolveSiteProps(host)
  };
}

export default MyApp;

我希望避免使用getInitialProps,因为它应该在没有静态生成的页面中禁用自动静态优化(这是我的情况)。
每个站点的变量位于根文件夹下的“sites”目录中,如下所示:

/sites
--/siteone.com.us.json
--/siteone.com.br.json
--/sitetwo.com.us.json

并且有一个函数用于根据当前请求域加载正确的文件。

const resolveSiteProps = async(host) => {
  const domain = normalizeDomain(host);
  const site = await
  import (
    /* webpackChunkName: "site-prefs" */
    /* webpackMode: "lazy" */
    `../sites/${domain}`
  );
  return {
    ...site.default,
    domain
  };
}

如果我能在SSR期间解析这些变量一次,并在客户端使用它们,那就太好了。
我在寻找一些有帮助和优雅的想法来解决这个案件。有什么想法吗?

j7dteeu8

j7dteeu81#

我只是很快地尝试了这个解决方案,但这至少在理论上应该是可行的,但这是一个不同的方法。我们使用基于主机的重写,但问题稍有不同。此外,我们确实有一个类似的解决方案,你最初发布的决定品牌基于请求主机。
如果每个站点都有不同的路径,然后根据主机在next.config.js中使用重写,会怎么样?
步骤:
1.为页面中的每个站点添加子文件夹,例如pages/siteone和pages/sitetwo
1.根据站点主机添加重写,如下所示

async rewrites() {
{
        source: '/:path*',
        destination: '/siteone/:path',
        has: [
          {
            type: 'host',
            value: 'siteone.com.us',
          },
        ],
      },
}

当然,这样做的代价是必须拥有每个站点的所有页面,但是您可以共享大部分代码,所以希望这不是问题。
注意:这可能不是一个功能完整的示例,但至少它为您提供了一个提示,告诉您在Next.js中重写可能会有什么结果。
https://nextjs.org/docs/api-reference/next.config.js/rewrites

xlpyo6sf

xlpyo6sf2#

主要有两种方法可以做到这一点:

*在页面文件夹中创建动态_sites/[site]路由,然后使用rewrites规范化您的URL。

您可以在这里找到完整的实施:https://github.com/vercel/next.js/discussions/12848#discussioncomment-1551776
缺点:

  • 你将必须明确地包括你的域名列表在getStaticProps在所有的网页你想静态生成.
  • 下一个useRouter中的pathname将总是包括前缀_sites/[site]
  • 根据个人经验_sites/[site]前缀有时会出现实际的网站网址,并导致错误。
    *从您的主分支中分支,并单独部署每个分支。(推荐)

创建.env文件并添加NEXT_PUBLIC_DOMAIN=my-domain,然后从main创建一个新的生产分支,并将变量更改为:NEXT_PUBLIC_DOMAIN=my-second-domain。你可以在你的应用程序中的任何地方访问这个变量,如文档中所述
缺点:

  • 您必须手动将您的main分支合并到您为每个域创建的其他分支。如果您有许多域,此解决方案将无法扩展。

注意:你不能使用_middleware进行静态优化。2原因是静态文件是在构建时创建的,并且不能确定哪个域将发出请求。

相关问题