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>

ページを更新すると、タイトルがピンク色になると思います

現在の動作


ページが最初に作成されたとき、タイトルはピンクで表示されます。 ページを更新すると、ピンク色が尊重されなくなります。
コードの色を他の色に変更してファイルを保存すると、ページが更新されます。 ただし、更新すると、変更は再び失われます。 何が原因なのかわかりません。 どんな助けでも大歓迎です。

あなたの環境


| 技術| バージョン|
| --------- | --------- |
| 次へ| 最新|
| ノード| |
| OS | アーチ|
| ブラウザ| vivaldi |

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 installまたはnpm installと、準備が整います。

PS:ローカルホスト開発作業用に開いているタブは1つだけにしてください!

全てのコメント27件

同じバグがありますが、設定が異なります。 私は2つのフォルダを持つmonorepoを持っています:

  • app 、next.jsアプリを使用
  • ui 、スタイル付きコンポーネントを使用した「uiライブラリ」

リポジトリの例にあります//github.com/lucleray/ssr-ui-library

たとえば、uiフォルダーの背景色を更新してファイルを保存すると、ページが更新されます。
しかし、ページを更新すると、更新が失われます。

これは、 <head>のスタイルシートの挿入順序と関係がありますか?

@ianregisterいいえ、 <head>での注入の順序は関係ありません

問題は、サーバーとクライアントがスタイルシートに同じコードをレンダリングしないことです。

同じバグがあり、スタイルだけではありません。 ホットリロードは変更を取得しますが、ブラウザを更新しても取得しません。 最新の更新を取得するには、サーバー(ノードserver.js)を再度実行する必要があります。 私は[email protected]を使用して

@lucleray 、これを試してください:

依存関係としてbabel-plugin-styled-componentsがあることを確認し、package.jsonで、サーバー側のレンダリングを行っていることをbabelに伝えます。

これは、直面している構成の問題にすぎないと考えてください。

package.json
`` `json
「バベル」:{
"env":{
"発達": {
"プリセット":["next / babel"]、
「プラグイン」:[
[
「スタイル付きコンポーネント」、
{{
「ssr」:true、
"displayName":true
}
]
]
}、
"製造": {
"プリセット":["next / babel"]、
「プラグイン」:[
[
「スタイル付きコンポーネント」、
{{
「ssr」:true、
"displayName":false
}
]
]
}
}
}

@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である可能性があります。

サーバー側では、バンドルに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依存関係を解決していないようですが、キャッシュされたバージョンを使用しています。


これは、 @monorepo/ui外部依存関係として扱わず、次のようにサーバー側のバンドルにバンドルするようにwebpackを構成することで解決しました: 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 installまたはnpm installと、準備が整います。

PS:ローカルホスト開発作業用に開いているタブは1つだけにしてください!

わかりました。 これが解決策です。 ディレクトリのルートに_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 installまたはnpm installと、準備が整います。

PS:ローカルホスト開発作業用に開いているタブは1つだけにしてください!

これはうまくいきます、ありがとう

残念ながら、それはまだ問題です。

しかし、私は何か奇妙なことを目撃しています:

あなたが持っている場合

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

この問題は、同じpackage.json依存関係と.babelrc設定を持たないNext.jsの例の1つを複製して構築している場合に発生します。 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 評価

関連する問題

knipferrc picture knipferrc  ·  3コメント

olifante picture olifante  ·  3コメント

havefive picture havefive  ·  3コメント

timneutkens picture timneutkens  ·  3コメント

flybayer picture flybayer  ·  3コメント