reactjs Nextjs生产应用上的页面刷新分隔样式

jyztefdp  于 2023-02-12  发布在  React
关注(0)|答案(7)|浏览(171)

我有一个用Nextjs建立的网站,打破页面刷新或当用户访问网站直接到一个特定的路径,而不是根路由样式。例如https://vinnieography.web.app/contacts(网站链接,如果它看起来不错,尝试刷新,看看)
该网站托管在Firebase Functions上,使用Nextjs和Ant design components

刷新前的网站屏幕截图

刷新后的网站屏幕截图(注意缺少导航)

导航并没有完全消失,但它变成了一个移动的导航的图标没有显示,但你得到一个下拉导航链接时,悬停在导航区。

我的下一个.config.js

const withCss = require('@zeit/next-css')

module.exports = withCss({
  webpack: (config, { isServer }) => {
    if (isServer) {
      const antStyles = /antd\/.*?\/style\/css.*?/
      const origExternals = [...config.externals]
      config.externals = [
        (context, request, callback) => {
          if (request.match(antStyles)) return callback()
          if (typeof origExternals[0] === 'function') {
            origExternals[0](context, request, callback)
          } else {
            callback()
          }
        },
        ...(typeof origExternals[0] === 'function' ? [] : origExternals),
      ]

      config.module.rules.unshift({
        test: antStyles,
        use: 'null-loader',
      })
    }

    // Fixes npm packages that depend on `fs` module
    config.node = {
      fs: 'empty'
    }

    return config
  },
  distDir: "../../dist/client"
})

Nextjs、React和Antd的版本

"antd": "^3.24.2",
"next": "^9.0.2",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"@zeit/next-css": "^1.0.1",
t98cgbkg

t98cgbkg1#

如果按照Material-UI NextJS示例中的建议修改应用程序没有帮助,您可以延迟加载组件。这样,您将强制它仅在加载客户端后创建样式。
禁用组件SSR的指南:https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr

import dynamic from 'next/dynamic'

export const ComponentWithNoSSR = dynamic(() => import('./Component'), {
  ssr: false,
})

但是,请记住,组件将失去SSR的所有特权。

fsi0uk1n

fsi0uk1n2#

我在使用带有MaterialUI的NextJS 9.4时遇到了这个问题。
每当样式被破坏时,我在控制台中收到此警告
警告:属性className不匹配。服务器:“多箱根多箱根5”客户端:跨度中的“MuiBox-root MuiBox-root-1”(由Styled(MuiBox)创建)

我就是这么搞定的。
我们需要定制document.js和定制app.js,如MaterialUI NextJS example中所述
从此处复制_document.js_app.jshttps://github.com/mui-org/material-ui/tree/master/examples/nextjs/pages

pages文件夹

https://github.com/mui-org/material-ui/tree/master/examples/nextjs/src复制theme.js并将其放在某个位置,然后更新_document.js_app.js中的导入链接
现在样式应该起作用了。

rseugnpd

rseugnpd3#

TLDR:您无法对Next.js使用基于移动的断点的条件呈现,因为服务器端呈现无法访问浏览器的维度。这解释了刷新时的视觉失真。使用服务器端呈现检测断点的唯一可靠方法是使用CSS媒体查询隐藏/取消隐藏移动组件。
根据此blog
服务器既不能识别窗口也不能识别文档,这意味着设备,换句话说,不能检测强制属性(如客户端的视区尺寸)-因此它需要通过某种方式来推断它们,这意味着一种非常有限和不准确的响应方式。
例如,假设我们有一个使用matchMedia的应用程序(正如你可能知道的,这是一个Web API,它位于窗口的顶部)来根据视口的尺寸有条件地呈现组件。你希望服务器在没有窗口的情况下如何呈现标记,即使它是假设的多边形填充的,维度呢?2一旦初始呈现包含了一个有条件地受断点影响的响应组件,它将如何响应?
简单地说,这可能会导致服务器错误地呈现应用程序,最终导致部分水合来修补不匹配(即潜在的bug?)

ngynwnxp

ngynwnxp4#

为了可靠地执行服务器端渲染并让客户端包正常运行,你需要使用我们的babel插件。它通过给每个样式化组件添加一个确定性ID来防止校验和不匹配。参考工具文档了解更多信息。

{
 "plugins": [
   [
     "babel-plugin-styled-components",
    {
     "ssr": false
    }
  ]
 ]
}
bqjvbblv

bqjvbblv5#

使用动态导入ssr:false导入组件将解决此问题

import dynamic from 'next/dynamic'

const DynamicComponentWithNoSSR = dynamic(
  () => import('../components/hello3'),
  { ssr: false }
)
f1tvaqid

f1tvaqid6#

这是因为服务器端呈现在呈现页面之前并不获取样式。样式化组件文档非常简短地提到了这一点,很容易被忽略。我们实际上要做的是将服务器端呈现的样式注入到头部,这样它就可以正确地呈现页面及其样式。Next.js中有你需要的文件,可以实现这一点。在Next中。你可以找到_document.js
我在使用样式化组件时遇到过类似的问题,将样式化组件注册到_document. js中就解决了这个问题。

k2fxgqgv

k2fxgqgv7#

我也遇到过同样的问题。但是我必须导入多个组件,然后根据条件返回。这是我的方法。我使用。then,因为动态是一个承诺。

import React, { useState, useEffect } from 'react';
import useDataStore from 'store';

const DynamicComponent = ({ componentName }) => {
  const [Component, setComponent] = useState(null);

  useEffect(() => {
    import(`./modules/${componentName}`)
      .then((mod) => {
        setComponent(mod.default);
      })
      .catch((error) => {
        console.error(error);
      });
  }, [componentName]);

  return Component ? <Component /> : <div>Loading...</div>;
};

function Rules() {
  const selectedTab = useDataStore((state) => state.selectedTab);

  let componentName;
  if (selectedTab === 'steak') {
    componentName = 'steak';
  } else if (selectedTab === 'mutton') {
    componentName = 'mutton';
  } else(selectedTab === 'default') {
    componentName = 'default';
  }

  return <DynamicComponent componentName={componentName} />;
}

export default Rules;

相关问题