Как интегрировать Nextjs + styled-components с material-ui

1. Создать приложение next.js с использованием стилизованных компонентов очень просто. Вам просто нужно использовать их фрагмент _document.js, чтобы включить SSR и предотвратить мерцание стилей при загрузке страницы: https://github.com/zeit/next.js/blob/canary/examples/with-styled-components/pages/_document.js

2. Создать приложение next.js с использованием material-ui почти так же просто. Вам просто нужно начать с базы проекта: https://github.com/mui-org/material-ui/tree/master/examples/nextjs, у которой есть своя реализация на _document.js: https://github.com/mui-org/material-ui/blob/master/examples/nextjs/pages/_document.js

3. К сожалению, я не смог понять, как "объединить" обе реализации и получить следующее приложение, в котором компоненты styled-components и material-ui могут сосуществовать, SSR и не мерцать при загрузке страницы.

Вы можете помочь мне? Есть ли в Интернете кто-то с лучшими способностями, чем у меня, кто уже решил эту проблему, но я не знаю?

Заранее спасибо.

Здесь вы можете найти рабочий пример github.com/manakuro/nextjs-styled-component-material-ui-exam‌​ple и пост о нем javascript.plainenglish.io/… . Это общепринятый подход, которым я тоже пользуюсь.

Evgeny Bobkin 13.03.2021 18:29

Здесь вы также можете найти хороший пример: связь

Matheus Gagno Brunetti 29.08.2021 20:09
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
29
2
10 874
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Попробуйте это

_document.js

import React from 'react';
import Document, { Head, Main, NextScript } from 'next/document';
import { ServerStyleSheet } from 'styled-components'
import { ServerStyleSheets } from '@material-ui/styles';
import theme from '../src/theme';

class MyDocument extends Document {
  static async getInitialProps (ctx) {
    const styledComponentsSheet = new ServerStyleSheet()
    const materialSheets = new ServerStyleSheets()
    const originalRenderPage = ctx.renderPage;

    try {
        ctx.renderPage = () => originalRenderPage({
            enhanceApp: App => props => styledComponentsSheet.collectStyles(materialSheets.collect(<App {...props} />))
          })
        const initialProps = await Document.getInitialProps(ctx)
        return {
          ...initialProps,
          styles: (
            <React.Fragment>
              {initialProps.styles}
              {materialSheets.getStyleElement()}
              {styledComponentsSheet.getStyleElement()}
            </React.Fragment>
          )
        }
      } finally {
        styledComponentsSheet.seal()
      }
  }

  render() {
    return (
      <html lang = "en" dir = "ltr">
        <Head>
          <meta charSet = "utf-8" />
          {/* Use minimum-scale=1 to enable GPU rasterization */}
          <meta
            name = "viewport"
            content = "minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"
          />
          {/* PWA primary color */}
          <meta
            name = "theme-color"
            content = {theme.palette.primary.main}
          />
          <link
            rel = "stylesheet"
            href = "https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    );
  }
}

export default MyDocument;

.babelrc

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

Для обновления проверьте https://github.com/nblthree/nextjs-with-material-ui-and-styled-components

@alevardi Я обновил свой ответ после его тестирования. Теперь работает без сомнений.

evgeni fotia 13.03.2019 16:06

@alevardi вот репозиторий github, который я создал github.com/MarchWorks/nextjs-with-material-ui-styled-compone‌​nts

evgeni fotia 13.03.2019 16:27

Большое спасибо, вы потрясающие. Работает как шарм! :)

Amet Alvirde 15.03.2019 19:49

сначала я пробовал код здесь, но он не работал. затем я попробовал код в репозитории, он работает хорошо.

Mehmet N. Yarar 04.07.2019 12:35

MehmetN.Yarar Да, начиная с материала 4.4 это решение устарело. Может быть, @evgenifotia могла бы обновить его? Это было бы потрясающе, и мы будем очень благодарны.

Amet Alvirde 19.09.2019 19:38

@Alevardi, если есть что-то устаревшее, просто откройте проблему, и я посмотрю на нее, и спасибо за сообщение.

evgeni fotia 19.09.2019 19:58

На самом деле, я был неправ, возможно, он устарел, когда @MehmetN.Yarar обнаружил эту ветку, купите прямо сейчас, я просто клонировал ваш репозиторий, чтобы посмотреть, что происходит, и все работает нормально. Большое спасибо за эту работу!

Amet Alvirde 19.09.2019 20:00

Это решение отлично работает на стороне сервера, на стороне клиента вам также необходимо изменить порядок инъекций, как описано здесь: https://material-ui.com/customization/css-in-js/#css-injection-order

Чтобы это работало с next.js, вам нужно изменить назначение константы jss следующим образом:

const jss = create({
  ...jssPreset(),
  insertionPoint: process.browser
    ? window.document.getElementById('jss-insertion-point')
    : null
})

вот мой _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();
      }
    }
  }

и ниже найдите мой .babelrc файл:

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

Для всех, у кого все еще есть проблема с приведенным выше кодом: мне также пришлось включить StylesProvider в pages/_app.tsx.

_app.tsx:

import { StylesProvider } from '@material-ui/core/styles';

<StylesProvider injectFirst>
  {/* Your component tree.
      Now, you can override Material-UI's styles. */}
</StylesProvider>

_document.tsx:

import React from 'react';
import Document, { Head, Main, NextScript } from 'next/document';
import { ServerStyleSheets } from '@material-ui/styles';
import { ServerStyleSheet } from 'styled-components';

class MyDocument extends Document {
  render() {
    return (
      <html lang = "en">
        <Head>
          <meta charSet = "utf-8" />
          <meta
            name = "viewport"
            content = "width=device-width, initial-scale=1, shrink-to-fit=no"
          />
          <meta name = "theme-color" content = "#000000" />
          {/* Fonts and icons */}
          <link
            rel = "stylesheet"
            type = "text/css"
            href = "https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Roboto+Slab:400,700|Material+Icons"
          />
          <link
            href = "https://use.fontawesome.com/releases/v5.0.10/css/all.css"
            rel = "stylesheet"
          />
        </Head>
        <body>
          <div id = "page-transition" />
          <Main />
          <NextScript />
        </body>
      </html>
    );
  }
}

MyDocument.getInitialProps = async (ctx) => {

  // Render app and page and get the context of the page with collected side effects.
  const materialSheet = new ServerStyleSheets();
  const styledComponentSheet = new ServerStyleSheet();
  const originalRenderPage = ctx.renderPage;

  try {
    ctx.renderPage = () =>
      originalRenderPage({
        enhanceApp: (App) => (props) =>
          styledComponentSheet.collectStyles(
            materialSheet.collect(<App {...props} />),
          ),
      });

    const initialProps = await Document.getInitialProps(ctx);

    return {
      ...initialProps,
      // Styles fragment is rendered after the app and page rendering finish.
      styles: [
        ...React.Children.toArray(initialProps.styles),
        materialSheet.getStyleElement(),
        styledComponentSheet.getStyleElement(),
      ],
    };
  } finally {
    styledComponentSheet.seal();
  }
};

export default MyDocument;

Это сработало для меня и кажется довольно чистым, спасибо

mattwad 25.09.2021 03:59

Я следовал этому примеру и хорошо работал у меня:

https://github.com/mui-org/material-ui/tree/next/examples/nextjs-with-styled-components-typescript

Ваш пример работает. Но в то же время у него есть проблема со статическими сборками связь

Alex Gusev 10.11.2021 19:12

Другие вопросы по теме