Nextjs生产应用程序上的页面刷新中断样式

时间:2020-02-04 15:24:46

标签: reactjs next.js antd

我有一个使用Nextjs构建的网站,该网站在刷新页面时或当用户直接访问特定路径而不是根路径访问网站时会破坏样式。例如https://vinnieography.web.app/contacts(如果网站链接正常,请尝试刷新并查看)

该网站托管在Firebase Functions上,并使用Nextjs和Ant design components

刷新前的网站截图

Screenshot of the site before a refresh

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

导航并没有完全消失,但它变成了一个移动导航,其图标未显示,但是当您在导航区域中徘徊时,您会看到一个带有导航链接的下拉菜单。

Screenshot of the site after a refresh

我的next.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",

Here is a link to the complete repo

5 个答案:

答案 0 :(得分:4)

我在使用带有 MaterialUI 的 NextJS 9.4 时遇到了这个问题。

每当样式损坏时,我都会在控制台中收到此警告

<块引用>

警告:道具 className 不匹配。服务器:“MuiBox-root MuiBox-root-5" 客户端:"MuiBox-root MuiBox-root-1" 跨度(由 Styled(MuiBox) 创建)

enter image description here

我就是这样解决的。

我们需要 MaterialUI NextJS example 中提到的自定义 document.js 和自定义 app.js

从这里复制 _document.js_app.js https://github.com/mui-org/material-ui/tree/master/examples/nextjs/pages

enter image description here

pages 文件夹

enter image description here

https://github.com/mui-org/material-ui/tree/master/examples/nextjs/src 复制 theme.js 并将其放置在某处并更新 _document.js_app.js 中的导入链接

样式现在应该可以工作了。

答案 1 :(得分:2)

如果按照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的所有特权。

答案 2 :(得分:1)

<块引用>

为了可靠地执行服务器端渲染并让客户端包顺利启动,您需要使用我们的 babel 插件。它通过向每个样式组件添加确定性 ID 来防止校验和不匹配。有关详细信息,请参阅工具 documentation

CREATE TABLE t1(empid INT, salary INT, deptid INT);
INSERT INTO t1 VALUES(1,1000,1);
INSERT INTO t1 VALUES(2,500,3);
INSERT INTO t1 VALUES(3,1500,2);
INSERT INTO t1 VALUES(4,5000,2);
INSERT INTO t1 VALUES(5,3000,8);
INSERT INTO t1 VALUES(8,2000,5);
INSERT INTO t1 VALUES(7, 3500,1);
INSERT INTO t1 VALUES(9,3000,2);

答案 3 :(得分:0)

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

import dynamic from 'next/dynamic'

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

答案 4 :(得分:0)

TLDR:您不能在 Next.js 中使用基于移动断点的条件渲染,因为服务器端渲染无法访问浏览器的尺寸。这解释了刷新时的视觉失真。通过服务器端渲染检测断点的唯一可靠方法是使用 CSS 媒体查询来隐藏/取消隐藏移动组件。

根据此blog

<块引用>

服务器不识别窗口和文档。换句话说,这意味着设备无法检测强制性属性(例如客户端的视口尺寸) - 因此它需要以某种方式推断它们,这意味着一种非常有限且不准确的响应方式。

例如,假设我们有一个使用 matchMedia 的应用程序 (您可能知道,这是一个 Web API,它位于 thewindow) 根据视口有条件地渲染组件 方面。您希望服务器如何呈现标记 没有窗户,即使它以某种方式假设为polyfill, 尺寸呢?一旦初始它会如何响应 渲染包含一个响应组件,有条件地受 断点?

简单地说——这可能会导致服务器渲染我们的应用程序 错误地,最终导致部分水合作用 不匹配(即潜在的错误?)。