Next.js: 热重载时覆盖样式组件

创建于 2018-03-28  ·  27评论  ·  资料来源: vercel/next.js

  • [x] 我已经搜索了这个存储库的问题,并相信这不是重复的。

预期行为


我的页面包含这个非常基本的代码:

import React from 'react'
import styled from 'styled-components'

const Title = styled.h1`
  color: pink;
  font-size: 50px;
`

export default () => <Title>My page</Title>

当我刷新页面时,我希望标题为粉红色

当前行为


第一次构建页面时,标题确实显示为粉红色。 当我刷新页面时,不再尊重粉红色。
如果我将代码中的颜色更改为其他颜色,并保存文件,则页面将更新。 但同样,刷新后,更改再次丢失。 我不知道是什么导致了这种情况。 任何帮助表示赞赏。

您的环境


| 科技 | 版本 |
|---------|---------|
| 下一个 | 最新 |
| 节点 | |
| 操作系统 | 拱|
| 浏览器 | 维瓦尔第 |

good first issue

最有用的评论

也有这个问题

编辑(解决方案):

此问题与未正确设置 babel 配置有关。 如果您查看带有样式组件的 NextJS 的官方示例,您会注意到它们有一个.babelrc文件,其中包含:

{
    "presets": ["next/babel"],
    "plugins": [["styled-components", { "ssr": true }]]
}

然后你必须将此插件添加到你的package.json文件中的 devDependencies

"devDependencies": {
    "babel-plugin-styled-components": "^1.8.0"
},

然后运行你的安装命令, yarn installnpm install ,然后你就可以开始了!

PS:确保只为您的本地主机开发工作打开一个选项卡!

所有27条评论

我有相同的错误,但设置不同。 我有一个带有两个文件夹的 monorepo:

  • app ,与我的 next.js 应用程序
  • ui ,我的“ui 库”使用样式组件

我在一个示例 repo 中有它: https :

例如,当我更新 ui 文件夹中的背景颜色并保存文件时,页面会更新。
但是,如果我刷新页面,更新就会丢失。

这与<head>样式表的注入顺序有关吗?

@ianregister没有, <head>中的注入顺序没有关系

问题是服务器和客户端不会为样式表呈现相同的代码

我有同样的错误,它不仅在样式上。 热重载将获取更改,但刷新浏览器不会。 我必须再次运行服务器(节点 server.js)才能获取最新更新。 我正在使用[email protected] ,反应 16.3 并为服务器表达。

@lucleray ,试试这个:

确保你有babel-plugin-styled-components作为依赖,并在你的 package.json 中告诉 babel 你正在做服务器端渲染。

认为这只是您面临的配置问题。

包.json
```json
“巴别塔”:{
“环境”:{
“发展”: {
“预设”:[“下一个/巴别塔”],
“插件”:[
[
“样式组件”,
{
“ssr”:真的,
“显示名称”:真
}
]
]
},
“生产”: {
“预设”:[“下一个/巴别塔”],
“插件”:[
[
“样式组件”,
{
“ssr”:真的,
“显示名称”:假
}
]
]
}
}
}

@tvthatsme我在 ui 库和应用程序本身中都添加了babel-plugin-styled-components ,但我仍然遇到同样的问题。

你可以在这里查看:
https://github.com/lucleray/ssr-ui-library/blob/master/app/.babelrc
https://github.com/lucleray/ssr-ui-library/blob/master/ui/.babelrc

我不确定它是配置(webpack 配置),还是某个地方的错误。

有类似的问题,对组件(非样式相关)的任何编辑都会导致错误“警告:道具className不匹配。服务器:”在随后的硬页面上新鲜。 需要重新启动服务器才能消失。

@sea129你能解决吗?

大声笑,这里有同样的问题。 @valeeum你能解决吗?

我对这个问题做了一些研究,我认为它可能是某种“webpack 缓存”的链接。

我使用这里的代码作为问题的示例: https :

app使用 Next.js 并且依赖于ui 。 我正在使用 yarn 的工作区来链接它们,但它可能是一个更简单的yarn link

在服务器端,bundle 不包含ui模块并将其视为external (因为它在 node_modules 中)。
在客户端,捆绑包包含ui模块。

它在.next/static (客户端)包中看起来像这样:

/***/ "../ui/bundle.js":
/*!***********************!*\
  !*** ../ui/bundle.js ***!
  \***********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, '__esModule', { value: true });

function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }

var styled = _interopDefault(__webpack_require__(/*! styled-components */ "../node_modules/styled-components/dist/styled-components.browser.esm.js"));

const UiButton = styled.button`
  background: black;
`;

exports.UiButton = UiButton;


/***/ }),

另一方面,在.next/server (服务器端)包中,它看起来像这样:

/***/ "@monorepo/ui":
/*!*******************************!*\
  !*** external "@monorepo/ui" ***!
  \*******************************/
/*! no static exports found */
/***/ (function(module, exports) {

module.exports = require("@monorepo/ui");

/***/ }),

奇怪的是module.exports = require("@monorepo/ui")应该解析为ui包并且工作正常。 但它似乎已被缓存并且无法解析为实际的ui包。

例如,如果我将ui按钮的背景颜色更改为蓝色。 热重载器正确更新页面。 但是,如果我刷新,则页面会以旧颜色(在我的示例中为绿色)呈现在服务器端。 就好像服务器端包没有解析@monorepo/ui依赖项以进入实际包,而是使用它的缓存版本。


它通过配置 webpack 将@monorepo/ui不作为外部依赖并将其捆绑在服务器端包中来解决它,如下所示: https :

我还是想知道发生了什么🤔

require有一个内置缓存( require.cache ),这是 node_modules 依赖项的预期行为,因为我们不会在服务器上的 node_modules 内捆绑任何东西(为了编译速度)。

好吧,这是有道理的。

所以问题是热重载器不会在服务器端重新加载外部依赖项中的代码更改,对吗?

在我分享的示例中,我希望我的代码更改在开发模式下同时加载到客户端(实际情况)和服务器端(情况并非如此)。

所以问题是热重载器不会在服务器端重新加载外部依赖项中的代码更改,对吗?

确切地说,我们只从 require.cache 中删除完整路径。

你认为我如何解决这个@timneutkens

我应该从外部依赖项中删除@monorepo/ui以便将其捆绑在服务器端包中吗? 那行得通,但既然我已经在转译它,那么只需要它不是更好吗?

它可能就像使用https://github.com/martpie/next-plugin-transpile-modules来启用模块编译一样简单。

@timneutkens为什么关闭? 最新版本仍然存在这个问题

还是有这个问题

我也有这个问题

这里也一样

也有这个问题

编辑(解决方案):

此问题与未正确设置 babel 配置有关。 如果您查看带有样式组件的 NextJS 的官方示例,您会注意到它们有一个.babelrc文件,其中包含:

{
    "presets": ["next/babel"],
    "plugins": [["styled-components", { "ssr": true }]]
}

然后你必须将此插件添加到你的package.json文件中的 devDependencies

"devDependencies": {
    "babel-plugin-styled-components": "^1.8.0"
},

然后运行你的安装命令, yarn installnpm install ,然后你就可以开始了!

PS:确保只为您的本地主机开发工作打开一个选项卡!

好的人。 这是解决方案。 在目录的根目录中创建一个 _document.js 并添加它。

import Document, { Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'

class MyDocument extends Document {
  static getInitialProps ({ renderPage }) {
    const sheet = new ServerStyleSheet()
    const page = renderPage(App => props => sheet.collectStyles(<App {...props} />))
    const styleTags = sheet.getStyleElement()
    return { ...page, styleTags }
  }

  render () {
    return (
      <html>
        <Head>
          <title>Your site title</title>
          {this.props.styleTags}
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    )
  }
}

export default MyDocument

然后npm install --save -D babel-plugin-styled-components

还在 pages 目录中创建一个自定义应用程序,_App.js 并添加:

import React from "react";
import App from "next/app";

class MyApp extends App {
  render() {
    const { Component, pageProps } = this.props;
    return <Component {...pageProps} />;
  }
}

export default MyApp;

你都准备好了

也有这个问题

编辑(解决方案):

此问题与未正确设置 babel 配置有关。 如果您查看带有样式组件的 NextJS 的官方示例,您会注意到它们有一个.babelrc文件,其中包含:

{
    "presets": ["next/babel"],
    "plugins": [["styled-components", { "ssr": true }]]
}

然后你必须将此插件添加到你的package.json文件中的 devDependencies

"devDependencies": {
    "babel-plugin-styled-components": "^1.8.0"
},

然后运行你的安装命令, yarn installnpm install ,然后你就可以开始了!

PS:确保只为您的本地主机开发工作打开一个选项卡!

这有效,谢谢

不幸的是,这仍然是一个问题。

不过,我目睹了一些奇怪的事情:

如果你有

styled.h1`
color: red;
`

在初始加载时它是红色的,当您将其更改为

styled.h1`
color: purple;
`

它被忽略,文本变成黑色,没有样式。
当您重新加载页面时,它会按预期变成紫色。
但是当您将颜色更改为red ,HMR 正常工作并且文本变为红色。
如果你愿意,你可以用尽可能多的颜色来做,就像某种缓存正在进行一样。

因此,当您通过 HMR 添加新样式时,它会被忽略,但在初始渲染时,它会被放置在缓存中,如果您稍后通过 HMR 使用此样式,它就会起作用。 所以它没有在 HMR 上正确传送到浏览器?

我不了解 SC 和 Next.js 内部结构,所以这些只是我的猜测。

编辑:
它在样式组件5.0.0-rc.2上工作正常

不确定这些信息的相关性,但是我如何为自己修复它是我遵循下一个 repo 中的示例并将丢失的部分整合在一起
https://github.com/zeit/next.js/tree/canary/examples/with-typescript-styled-components

我正在使用 next.js, @MaxMcKinney解决方案对我.babelrc首选项,因为它是一种令人困惑的格式或要遵循的数组和对象。

这是我的.babelrc文件,例如:

{
    "presets": [
        [
            "next/babel",
            {
                "styled-jsx": {
                    "plugins": [
                        "styled-jsx-plugin-postcss"
                    ]
                }
            }
        ]
    ],
    "plugins": [
        [
            "styled-components",
            {
                "ssr": true
            }
        ]
    ]
}

如果您在不具有相同package.json依赖项和.babelrc设置的 Next.js 示例之一上进行克隆和构建,则会出现此问题。 除了 MaxMckinney 解决方案,请确保您在package.json具有正确的依赖项。 我完全错过了"styled-components": "^5.0.0"

在我的例子中,只需在 pages floder 下添加 _app.js 和 _document.js 文件,它工作正常。

// _app.js
import App from 'next/app'
import { ThemeProvider } from 'styled-components'

const theme = {}

export default class MyApp extends App {
    render() {
        const { Component, pageProps } = this.props
        return (
            <ThemeProvider theme={theme}>
                <Component {...pageProps} />
            </ThemeProvider>
        )
    }
}
// _document.js
import Document from 'next/document'
import { ServerStyleSheet } from 'styled-components'

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const sheet = new ServerStyleSheet()
    const originalRenderPage = ctx.renderPage

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        })

      const initialProps = await Document.getInitialProps(ctx)
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      }
    } finally {
      sheet.seal()
    }
  }
}

在我的例子中,只需在 pages floder 下添加 _app.js 和 _document.js 文件,它工作正常。

// _app.js
import App from 'next/app'
import { ThemeProvider } from 'styled-components'

const theme = {}

export default class MyApp extends App {
    render() {
        const { Component, pageProps } = this.props
        return (
            <ThemeProvider theme={theme}>
                <Component {...pageProps} />
            </ThemeProvider>
        )
    }
}
// _document.js
import Document from 'next/document'
import { ServerStyleSheet } from 'styled-components'

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const sheet = new ServerStyleSheet()
    const originalRenderPage = ctx.renderPage

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        })

      const initialProps = await Document.getInitialProps(ctx)
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      }
    } finally {
      sheet.seal()
    }
  }
}

我应该如何在 Material-UI 中使用它?

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

YarivGilad picture YarivGilad  ·  3评论

jesselee34 picture jesselee34  ·  3评论

DvirSh picture DvirSh  ·  3评论

rauchg picture rauchg  ·  3评论

havefive picture havefive  ·  3评论