Next.js: стилизованный компонент переопределяется при горячей перезагрузке

Созданный на 28 мар. 2018  ·  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 }]]
}

Затем вы должны добавить этот плагин в devDependencies в вашем файле package.json

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

Затем запустите команду установки yarn install или npm install и тогда все будет в порядке!

PS: Убедитесь, что открыта только одна вкладка для вашей работы с localhost dev!

Все 27 Комментарий

У меня такая же ошибка, но с другой настройкой. У меня монорепозиторий с двумя папками:

  • app , с моим приложением next.js
  • ui , с моей "библиотекой пользовательского интерфейса", использующей стилизованные компоненты

У меня есть пример репо: https://github.com/lucleray/ssr-ui-library

Когда я обновляю цвет фона, например, в папке ui, и сохраняю файл, страница обновляется.
Но затем, если я обновлю страницу, обновления будут потеряны.

Связано ли это с порядком внедрения таблиц стилей в <head> ?

@ianregister Нет, порядок инъекции в <head> не имеет отношения

Проблема в том, что сервер и клиент не отображают один и тот же код для таблиц стилей.

У меня такая же ошибка, и дело не только в стилях. При горячей перезагрузке изменения сохранятся, а при обновлении браузера - нет. Мне нужно снова запустить сервер (узел server.js), чтобы получить последнее обновление. Я использую [email protected] , реагирую на 16.3 и выражаю для сервера.

@lucleray , попробуйте это:

Убедитесь, что у вас есть babel-plugin-styled-components в качестве зависимости и в вашем package.json сообщите babel, что вы выполняете рендеринг на стороне сервера.

Подумайте, что это просто проблема конфигурации, с которой вы столкнулись.

package.json
`` json
"babel": {
"env": {
"разработка": {
"presets": ["next / babel"],
"плагины": [
[
"стилизованные компоненты",
{
"ssr": правда,
"displayName": true
}
]
]
},
"производство": {
"presets": ["next / babel"],
"плагины": [
[
"стилизованные компоненты",
{
"ssr": правда,
"displayName": ложь
}
]
]
}
}
}

@tvthatsme Я добавил 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

Я не уверен, что это конфигурация (конфигурация веб-пакета) или где-то ошибка.

имеющая аналогичную проблему, когда любые изменения в компоненте (не связанные со стилями) вызовут ошибку «Предупреждение: Prop className не соответствует. Сервер:» на следующей новой жесткой странице. Необходимо перезапустить сервер, чтобы он исчез.

@ sea129 удалось исправить?

Лол, здесь та же проблема. @valeeum удалось ли вам решить эту проблему?

Я немного исследовал эту проблему и думаю, что это может быть ссылка на какое-то «кеширование веб-пакетов».

Я использую здесь код в качестве примера проблемы: https://github.com/lucleray/ssr-ui-library

app использует Next.js и зависит от ui . Я использую рабочую область yarn, чтобы связать их, но это может быть более простой yarn link .

На стороне сервера пакет не включает модуль 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://github.com/lucleray/ssr-ui-library/blob/ webpack-config / приложение / next.config.js

Я все еще хотел бы понять, что происходит 🤔

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 }]]
}

Затем вы должны добавить этот плагин в devDependencies в вашем файле package.json

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

Затем запустите команду установки yarn install или npm install и тогда все будет в порядке!

PS: Убедитесь, что открыта только одна вкладка для вашей работы с localhost dev!

хорошо люди. вот решение. создайте _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

также создайте собственное приложение в каталоге страниц _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 }]]
}

Затем вы должны добавить этот плагин в devDependencies в вашем файле package.json

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

Затем запустите команду установки yarn install или npm install и тогда все будет в порядке!

PS: Убедитесь, что открыта только одна вкладка для вашей работы с localhost dev!

Это работает, спасибо

К сожалению, это все еще проблема.

Однако я наблюдаю кое-что странное:

Если у вас есть

styled.h1`
color: red;
`

при начальной загрузке он красный, когда вы меняете его на

styled.h1`
color: purple;
`

он игнорируется, текст становится черным, без стилей.
Когда вы перезагружаете страницу, она, как и ожидалось, становится фиолетовой.
Но когда вы затем меняете цвет на red , HMR работает правильно, и текст становится красным.
Вы можете сделать это с любым количеством цветов, если хотите, например, если происходит какое-то кеширование.

Поэтому, когда вы добавляете новый стиль через HMR, он игнорируется, но при первоначальном рендеринге он помещается в кеш, и если вы используете этот стиль позже через HMR, он будет работать. Значит, он не доставляется в браузер должным образом на HMR?

У меня нет знаний о внутреннем устройстве SC и Next.js, так что это только мои предположения.

РЕДАКТИРОВАТЬ:
он работал нормально на стилизованных компонентах 5.0.0-rc.2

Не уверен, насколько актуальной будет эта информация, но как я ее исправил, я последовал примеру из следующего репо и интегрировал недостающие биты по частям
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
            }
        ]
    ]
}

Эта проблема возникает , если вы Клонирование и строительство на одном из примеров Next.js , которые не имеют те же package.json зависимостей и .babelrc настройки. В дополнение к решению MaxMckinney убедитесь, что у вас есть правильная зависимость в package.json . Мне совершенно не хватало "styled-components": "^5.0.0"

В моем случае просто добавьте файл _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()
    }
  }
}

В моем случае просто добавьте файл _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 рейтинги