Next.js: componente estilizado substituído no hot reload

Criado em 28 mar. 2018  ·  27Comentários  ·  Fonte: vercel/next.js

  • [x] Pesquisei os problemas deste repositório e acredito que não seja uma duplicata.

Comportamento esperado


Minha página contém este código muito básico:

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

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

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

Quando eu atualizo a página, espero que o título esteja na cor rosa

Comportamento Atual


Na primeira vez que a página é construída, o título aparece em rosa. Quando eu atualizo a página, a cor rosa não é mais respeitada.
Se eu mudar a cor do código para qualquer outra coisa e salvar o arquivo, a página será atualizada. Mas, novamente, após a atualização, as mudanças são perdidas novamente. Não tenho ideia do que pode estar causando isso. Qualquer ajuda é apreciada.

Seu Ambiente


| Tech | Versão |
| --------- | --------- |
| próximo | mais recente |
| nó | |
| OS | arco |
| navegador | vivaldi |

good first issue

Comentários muito úteis

Também tendo esse problema

Editar (solução):

Este problema está relacionado a não ter a configuração do babel configurada corretamente. Se você olhar o exemplo oficial do NextJS com componentes estilizados, você notará que eles têm um arquivo .babelrc com:

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

Então você deve adicionar este plugin ao devDependencies em seu arquivo package.json

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

Em seguida, execute o comando de instalação, yarn install ou npm install e você estará pronto para ir!

PS: Certifique-se de ter apenas uma guia aberta para o seu trabalho de desenvolvimento localhost!

Todos 27 comentários

Tenho o mesmo bug, com uma configuração diferente. Tenho um monorepo com duas pastas:

  • app , com meu app next.js
  • ui , com minha 'biblioteca de interface do usuário' usando componentes estilizados

Eu tenho em um repositório de exemplo: https://github.com/lucleray/ssr-ui-library

Quando eu atualizo a cor de fundo, por exemplo, na pasta ui, e salvo o arquivo, a página é atualizada.
Mas então, se eu atualizar a página, as atualizações serão perdidas.

Isso tem algo a ver com a ordem de injeção das folhas de estilo em <head> ?

@ianregister Não, a ordem da injeção em <head> não está relacionada

O problema é que o servidor e o cliente não renderizam o mesmo código para as folhas de estilo

Eu tenho o mesmo bug e não é só nos estilos. O hot reload irá captar as mudanças, mas a atualização do navegador não. Tenho que executar o servidor novamente (node ​​server.js) para pegar a atualização mais recente. Estou usando [email protected] , reajo 16.3 e expresso para o servidor.

@lucleray , tente isto:

Certifique-se de ter babel-plugin-styled-components como uma dependência e em seu package.json diga ao babel que você está fazendo renderização do lado do servidor.

Pense que este é apenas um problema de configuração que você está enfrentando.

package.json
`` `json
"babel": {
"env": {
"desenvolvimento": {
"presets": ["next / babel"],
"plugins": [
[
"componentes estilizados",
{
"ssr": verdadeiro,
"displayName": verdadeiro
}
]
]
},
"Produção": {
"presets": ["next / babel"],
"plugins": [
[
"componentes estilizados",
{
"ssr": verdadeiro,
"displayName": falso
}
]
]
}
}
}

@tvthatsme Eu adicionei babel-plugin-styled-components na biblioteca da interface do usuário e no próprio aplicativo, mas ainda tenho o mesmo problema.

Você pode verificar aqui:
https://github.com/lucleray/ssr-ui-library/blob/master/app/.babelrc
https://github.com/lucleray/ssr-ui-library/blob/master/ui/.babelrc

Não tenho certeza se é configuração (configuração do webpack), ou um bug em algum lugar.

tendo um problema semelhante em que qualquer edição em um componente (não relacionado a estilos) causará um erro "Aviso: Prop className não correspondeu. Servidor:" na página física subsequente nova. É necessário reiniciar o servidor para que ele desapareça.

@ sea129 você conseguiu consertar?

Lol, tendo o mesmo problema aqui. @valeeum você conseguiu resolver isso?

Pesquisei um pouco sobre esse assunto e acho que pode ser um link de algum tipo de "cache de webpack".

Eu uso o código aqui como um exemplo do problema: https://github.com/lucleray/ssr-ui-library

O app está usando Next.js e tem uma dependência do ui . Estou usando o espaço de trabalho do yarn para vinculá-los, mas poderia ser um yarn link mais simples.

No lado do servidor, o pacote não inclui o módulo ui e o trata como external (porque está em node_modules).
No lado do cliente, o pacote inclui o módulo ui .

É assim que aparece nos pacotes .next/static (do lado do cliente):

/***/ "../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;


/***/ }),

Por outro lado, nos pacotes .next/server (lado do servidor), é assim:

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

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

/***/ }),

O estranho é que module.exports = require("@monorepo/ui") deve resolver para o pacote ui e funcionar bem. Mas parece que está em cache e não se resolve no pacote ui real.

Se eu mudar a cor de fundo do botão em ui para azul, por exemplo. O hot reloader atualiza a página corretamente. Mas se eu atualizar, a página será renderizada do lado do servidor com a cor antiga (verde no meu exemplo). É como se o pacote do lado do servidor não estivesse resolvendo a dependência @monorepo/ui do pacote real, mas estivesse usando uma versão em cache dele.


Ele resolveu configurando o webpack para tratar @monorepo/ui não como uma dependência externa e empacotá-lo nos pacotes do lado do servidor, como este: https://github.com/lucleray/ssr-ui-library/blob/ webpack-config / app / next.config.js

Eu ainda gostaria de entender o que está acontecendo 🤔

require tem um cache embutido ( require.cache ) este é o comportamento esperado para dependências em node_modules, já que não empacotaremos nada dentro de node_modules no servidor (para velocidade de compilação).

Ok, isso faz sentido.

Portanto, o problema é que o hot-reloader não recarrega as alterações de código nas dependências externas, no lado do servidor, certo?

No exemplo que compartilhei, espero que minhas alterações de código sejam carregadas no lado do cliente (que é o caso) e do servidor (que não é o caso) no modo de desenvolvimento.

Portanto, o problema é que o hot-reloader não recarrega as alterações de código nas dependências externas, no lado do servidor, certo?

Exatamente, nós apenas excluímos caminhos completos de require.cache.

Como você acha que eu poderia resolver isso @timneutkens ?

Devo remover @monorepo/ui das dependências externas para que sejam agrupados nos pacotes do lado do servidor? Isso funciona, mas como já estou traduzindo, não seria melhor apenas exigir?

Pode ser tão fácil quanto usar https://github.com/martpie/next-plugin-transpile-modules para habilitar a compilação do módulo.

@timneutkens Por que foi fechado? este problema ainda existe na última versão

Ainda estou tendo esse problema

Eu ainda estou tendo esse problema também

Idem também aqui

Também tendo esse problema

Editar (solução):

Este problema está relacionado a não ter a configuração do babel configurada corretamente. Se você olhar o exemplo oficial do NextJS com componentes estilizados, você notará que eles têm um arquivo .babelrc com:

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

Então você deve adicionar este plugin ao devDependencies em seu arquivo package.json

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

Em seguida, execute o comando de instalação, yarn install ou npm install e você estará pronto para ir!

PS: Certifique-se de ter apenas uma guia aberta para o seu trabalho de desenvolvimento localhost!

ok gente. aqui está a solução. crie um _document.js na raiz do diretório e adicione-o.

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

então npm install --save -D babel-plugin-styled-components

também crie um aplicativo personalizado no diretório de páginas, _App.js e adicione:

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;

você está pronto

Também tendo esse problema

Editar (solução):

Este problema está relacionado a não ter a configuração do babel configurada corretamente. Se você olhar o exemplo oficial do NextJS com componentes estilizados, você notará que eles têm um arquivo .babelrc com:

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

Então você deve adicionar este plugin ao devDependencies em seu arquivo package.json

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

Em seguida, execute o comando de instalação, yarn install ou npm install e você estará pronto para ir!

PS: Certifique-se de ter apenas uma guia aberta para o seu trabalho de desenvolvimento localhost!

Isso funciona, obrigado

Infelizmente, ainda é um problema.

Estou testemunhando algo estranho:

Se você tem

styled.h1`
color: red;
`

no carregamento inicial é vermelho, quando você muda para

styled.h1`
color: purple;
`

ele é ignorado, o texto fica preto, sem estilos.
Quando você recarrega a página, ela fica roxa conforme o esperado.
Mas quando você muda a cor para red , o HMR funciona corretamente e o texto fica vermelho.
Você pode fazer isso com quantas cores quiser, como se algum tipo de cache estivesse acontecendo.

Então, quando você adiciona um novo estilo via HMR, ele é ignorado, mas na renderização inicial é colocado no cache, e se você usar esse estilo mais tarde via HMR, vai funcionar. Portanto, não é entregue ao navegador corretamente no HMR?

Não tenho conhecimento sobre os internos de SC e Next.js, então esses são apenas meus palpites.

EDITAR:
funcionou bem em componentes estilizados 5.0.0-rc.2

não tenho certeza de quão relevante essa informação será, mas como eu consertei para mim mesmo, segui o exemplo do próximo repo e integrei os pedaços que faltavam em pedaços
https://github.com/zeit/next.js/tree/canary/examples/with-typescript-styled-components

Eu estava usando next.js e a solução @MaxMcKinney funcionou para mim. Apenas certifique-se de ter configurado as preferências .babelrc corretamente, pois é um formato bastante confuso de matrizes e objetos a seguir.

Este era meu arquivo .babelrc por exemplo:

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

Este problema ocorrerá se você estiver clonagem e construção em um dos exemplos Next.js que não têm as mesmas package.json dependências e .babelrc configurações. Além da solução MaxMckinney, certifique-se de ter a dependência correta em package.json . Eu estava perdendo "styled-components": "^5.0.0"

No meu caso, basta adicionar o arquivo _app.js e _document.js no floder de páginas, e funcionará bem.

// _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()
    }
  }
}

No meu caso, basta adicionar o arquivo _app.js e _document.js no floder de páginas, e funcionará bem.

// _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()
    }
  }
}

Como devo usá-lo no Material-UI?

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

lixiaoyan picture lixiaoyan  ·  3Comentários

kenji4569 picture kenji4569  ·  3Comentários

jesselee34 picture jesselee34  ·  3Comentários

flybayer picture flybayer  ·  3Comentários

timneutkens picture timneutkens  ·  3Comentários