Next.js:如何将仅外部客户端的 React 组件动态导入到开发的服务器端渲染应用程序中?

Posted

技术标签:

【中文标题】Next.js:如何将仅外部客户端的 React 组件动态导入到开发的服务器端渲染应用程序中?【英文标题】:Next.js: How to dynamically import external client-side only React components into Server-Side-Rendering apps developed? 【发布时间】:2019-01-16 15:52:33 【问题描述】:

我知道这个问题之前已经被问过多次,但似乎没有一个解决方案有效。

我正在尝试使用仅在 s-s-r 应用程序的客户端呈现的库“react-chat-popup”。(使用 next.js 框架构建)使用此库的正常方法是调用 import Chat from 'react-chat-popup'然后直接渲染为<Chat/>

我为 s-s-r 应用程序找到的解决方案是在动态导入库之前检查 componentDidMount 方法中的 typedef of window !=== 'undefined' 是否正常,因为通常单独导入库已经导致 window is not defined 错误。所以我找到了链接https://github.com/zeit/next.js/issues/2940,它提出了以下建议:

Chat = dynamic(import('react-chat-popup').then(m => 
  const Foo = m;
  Foo.__webpackChunkName = m.__webpackChunkName;
  return Foo;
));

但是,当我这样做时,我的 foo 对象变为空。当我在回调中打印出 m 对象时,我得到 "__webpackChunkName":"react_chat_popup_6445a148970fe64a2d707d15c41abb03" 在这种情况下如何正确导入库并开始使用 <Chat/> 元素?

【问题讨论】:

【参考方案1】:

我已经设法通过首先在顶部声明一个变量来解决这个问题:

let Chat = ''

然后在 componentDidMount 中以这种方式导入:

async componentDidMount()
        let result = await import('react-chat-popup')
        Chat = result.Chat
        this.setState(
            appIsMounted: true
        )
    

最后渲染成这样:

<Nos-s-r>
   this.state.appIsMounted? <Chat/> : null
</Nos-s-r>

【讨论】:

如果需要这样的 hack 才能工作,感觉就像 react-chat-popup 与 s-s-r 一起工作时出现了可怕的错误,但找到解决方案的工作做得很好! 检查我的答案以找到解决此问题的本地方法。【参考方案2】:

Next js 现在有自己的方式进行动态导入,无需 s-s-r。

import dynamic from 'next/dynamic'

const DynamicComponentWithNos-s-r = dynamic(
  () => import('../components/hello3'),
   s-s-r: false 
)

这是他们文档的链接:next js

【讨论】:

【参考方案3】:

您自己提到了解决方案,该组件只能在客户端运行,因此您只能使用条件在客户端上呈现它。执行以下操作只会在客户端呈现组件并解决您的问题:

if (process.browser) 
  // client-side-only code
  <Chat/>

您不必担心如何导入组件,只需 import Chat from 'react-chat-popup' 将它作为任何其他组件,它将被添加到客户端捆绑包(以及服务器端,但它是服务器,所以可以有它,即使它没有被使用)。

这可能值得一读:https://github.com/zeit/next.js/issues/2473

【讨论】:

嗨,我明白你的意思。但如果我只是按照正常情况执行import Chat from 'react-chat-popup',我会收到'window is not defined' 错误,因此我还需要有条件地进行导入(当它的客户端时)。问题是当我尝试按上述条件进行导入时,它不起作用 你试过我上面的代码了吗?如果你没有调用组件,它不应该执行任何东西,除非他们在库端做了一些奇怪的代码。 是的,我已经尝试过代码。事实上,我已经尝试完全删除 &lt;Chat/&gt; 元素,只保留 import 语句,它仍然会触发 window not defined 错误。

以上是关于Next.js:如何将仅外部客户端的 React 组件动态导入到开发的服务器端渲染应用程序中?的主要内容,如果未能解决你的问题,请参考以下文章

如何正确配置 Next.js 作为前端和 Express 应用作为后端?

Heroku 将 Next.js React 客户端应用程序 http 重定向到 https

Next.Js 带有样式组件的 React 应用程序。警告:道具 `className` 不匹配。服务器:“x” 客户端:“y”

Next.js 中的客户端初始化与静态 HTML 导出

如何在 Next.js 中加载外部图像?

Next.js 具有 React 钩子和 localStorage 的持久状态