Material-ui: производственная сборка - конфликты имен классов

Созданный на 15 сент. 2017  ·  62Комментарии  ·  Источник: mui-org/material-ui


Определения имен классов css дублируются для некоторых компонентов - в моем случае они дублируются (я думаю, из моей отладки) для MuiIconButton и MuiModal - проверьте текущее поведение

  • [x] Я искал проблемы в этом репозитории и считаю, что это не дубликат.

Ожидаемое поведение

Имена классов не должны дублироваться в компонентах.

Текущее поведение

Мои стили кнопок:
classnames_conflict
Класс дублируется.
Определение стилей:
classnames_conflit_2

Он работает в режиме разработки:
Мои стили кнопок:
development_class

и нашел определения:
mui-icon-button-dev

и из модального:
mui-modal-dev

Шаги по воспроизведению (для ошибок)

Я могу попытаться подготовить среду для воспроизведения проблемы, но сейчас я просто хотел сообщить об этом здесь.

Контекст


Я пытаюсь выпустить свое приложение в производственной среде.

Ваше окружение

| Технология | Версия |
| -------------- | --------- |
| Material-UI | 1.0.0-beta.10 |
| React | 15.6.1 |
| браузер | любой |
| webpack | ^ 3.3.0 |

Мне нужны подсказки, в чем может быть проблема. Я нигде не использую решение withStyles - я использую стилизованные компоненты для переопределения стилей.

bug 🐛

Самый полезный комментарий

У меня были совпадающие имена классов, и добавление префикса в параметрах createGenerateClassName решило проблему.

Пользовался большой, всеобъемлющий документ здесь

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

Я уже видел проблему с этой проблемой. Он всегда был связан с дублированными экземплярами генератора className. Я не могу больше помочь без репродукции.

Я пока закрываю вопрос как не требующий действий. Дайте мне знать, если у вас есть пример репродукции.

@oliviertassinari Мне удалось воспроизвести проблему. Вот корзина веб-пакета - https://www.webpackbin.com/bins/-KuO6ia3h-JDpBOJncZ3

В моем случае у меня есть 2 корня приложений, которые независимо монтируются в 2 разных div. Оба используют один и тот же материал-ui ThemeProvider завернутый в JssProvider чтобы переопределить insertionPoint из _jss_.

generate_classnames_counter

На основе функции createGenerateClassName вы используете счетчик, чтобы иметь уникальные имена классов

export default function createGenerateClassName(): generateClassName {
  let ruleCounter = 0;

  return (rule: Rule, sheet?: StyleSheet): string => {
    ruleCounter += 1;
    warning(
      ruleCounter < 1e10,
      [
        'Material-UI: you might have a memory leak.',
        'The ruleCounter is not supposed to grow that much.',
      ].join(''),
    );

    if (process.env.NODE_ENV === 'production') {
      return `c${ruleCounter}`;
    }

    if (sheet && sheet.options.meta) {
      return `${sheet.options.meta}-${rule.key}-${ruleCounter}`;
    }

    return `${rule.key}-${ruleCounter}`;
  };
}

И мой скриншот подтверждает, что счетчик почему-то продублирован.

Мне нужна помощь. Я не знаю, что делаю сейчас не так.

@darkowic Вам нужно поделиться экземпляром jss между разными деревьями реакции. Вы должны хорошо относиться к таким изменениям.

@oliviertassinari Я думаю, что делаю это, используя свой собственный ThemeProvider

  <JssProvider registry={context.sheetsRegistry} jss={context.jss}>
    <MuiThemeProvider
      theme={context.theme}
      sheetManage={context.sheetsManager}
      {...props}
    />
  </JssProvider>

Я оборачиваю этим каждое свое дерево реакций.

Этот вопрос следует открыть.

Конечно, давайте подведем итог тому, что мы знаем на данный момент. Эта проблема возникает, как только вы используете дерево рендеринга с несколькими реакциями. Поставщик jss собирается создать два генератора имен классов, по одному для каждого дерева. Следовательно, мы получаем конфликты имен классов.
@kof Должны ли мы расширить JssProvider от react-jss чтобы принять генератор имени класса?

РЕШЕНИЕ для клиентского приложения: вы можете создать свой собственный createGenerateClassName и переместить ruleCounter за пределы функции оболочки

import warning from 'warning';

// Returns a function which generates unique class names based on counters.
// When new generator function is created, rule counter is reset.
// We need to reset the rule counter for SSR for each request.
//
// It's an improved version of
// https://github.com/cssinjs/jss/blob/4e6a05dd3f7b6572fdd3ab216861d9e446c20331/src/utils/createGenerateClassName.js
//
// Copied from material-ui due to issue https://github.com/callemall/material-ui/issues/8223

// This counter is moved outside from `createGenerateClassName` to solve the issue
let ruleCounter = 0;

export default function createGenerateClassName() {
  return (rule, sheet) => {
    ruleCounter += 1;
    warning(
      ruleCounter < 1e10,
      [
        'Material-UI: you might have a memory leak.',
        'The ruleCounter is not supposed to grow that much.'
      ].join('')
    );

    if (process.env.NODE_ENV === 'production') {
      return `c${ruleCounter}`;
    }

    if (sheet && sheet.options.meta) {
      return `${sheet.options.meta}-${rule.key}-${ruleCounter}`;
    }

    return `${rule.key}-${ruleCounter}`;
  };
}

Хороший, у нас был такой вариант использования на сервере, и я уже планировал смелую подсказку в документации см. # 5

Но теперь вы действительно нашли вескую причину для поддержки двух параллельно работающих провайдеров.

Нам нужно исследовать, есть ли варианты использования, в которых остро требуется несколько параллельных JssProvider. Если есть, нам нужно придумать что-нибудь, чтобы поддержать это.

@kof Вы только что нашли вариант использования нескольких параллельных JssProvider на стороне клиента. И я считаю, что предложенное решение просто реализовать :).

переместить ruleCounter за пределы функции-оболочки

Это будет означать, что на сервере ruleCounter никогда не будет сброшен. Мы не можем этого сделать.

На стороне сервера JssProviders определенно должны поддерживать параллельный асинхронный рендеринг дерева реакции (острая необходимость). Но текущая реализация делает его уже поддерживаемым :)

@darkowic Предложил обходной путь без доступа к базовому стеку. Мы делаем. Мы можем добиться большего с помощью этой дополнительной гибкости: принятия экземпляра генератора имени класса.

Также запрос к той же конечной точке всегда должен отвечать с одинаковыми именами классов.

@kof Должны ли мы расширить JssProvider от response-jss, чтобы принять генератор имени класса?

  1. Да, один из возможных способов - разрешить JssProvider принимать генератор имен классов следующим образом:

import {createGenerateClassName} from 'react-jss'

const generateClassName = createGenerateClassName()

<JssProvider generateClassName={generateClassName}>
  <App1 />
</JssProvider>

<JssProvider generateClassName={generateClassName}>
  <App2 />
</JssProvider>

  1. Другой потенциальный вариант - предоставить некоторый префикс, например, имя приложения. Это может сработать, если мы предположим, что у нас нет непредсказуемого количества приложений.

<JssProvider classNamePrefix="app-1">
  <App1 />
</JssProvider>

<JssProvider classNamePrefix="app-2">
  <App2 />
</JssProvider>

Pro 1:

  • Пользователю не нужно указывать префикс

Pro 2:

  • Пользователь может иметь что-то значимое в именах классов DOM, которое идентифицирует приложение во время разработки.
  • У пользователя больше контроля над префиксом.
  • Иметь неконфликтный префикс относительно легко. Либо у вас всего несколько поддеревьев и присвоение имен уже достаточно просто, либо вы можете добавить к этим именам собственный префикс номера и сбрасывать их при каждом запросе.

На самом деле имеет смысл иметь оба свойства classNamePrefix и generateClassName . Первый - для отладки, второй - для автоматической уникальности имен классов.

Я столкнулся с этой проблемой через https://github.com/facebookincubator/create-react-app/issues/3173 (и связанный сокращенный тестовый пример ).

В моем случае компонент, зависящий от UI материала (v1.0.0-beta.11), был включен в приложение, которое также использует material-ui (те же версии). В разработке это работает нормально, но в производстве макет нарушен из-за конфликта имен классов.

Я не уверен, что это квалифицируется как «деревья рендеринга с множественными реакциями» и перемещение var ruleCounter = 0; перед createGenerateClassName() _did not_ решение проблемы, но, комментируя следующее, _did_ работает:

https://github.com/callemall/material-ui/blob/2361339fd6df9bfbb85ed2ee4da9d42ee6fee71c/src/styles/createGenerateClassName.js#L26 -L28

Извините, я не мог предоставить больше информации, когда открывал # 7855.😊
Этот комментарий в основном касается проблемы, с которой я столкнулся при запуске производственной сборки.

Обходной путь для этого в разработке?

Создал PR, который должен исправить это в response-jss https://github.com/cssinjs/react-jss/pull/155

Итак, подведем итоги.

  • @darkowic 's проблемы первопричиной описано здесь: https://github.com/callemall/material-ui/issues/8223#issuecomment -331076580 и будет исправлена благодаря @kof' s PR: cssinjs / реагировать-Jss # 155 и будет добавлено новое предупреждение, чтобы предотвратить такую ​​ситуацию в будущем: # 8341.

  • Симптомы проблемы основная причина в другом. Вы используете единое дерево рендеринга реакции. Это может быть связано с установленной дублированной версией Material-UI. Проверьте свои предупреждения, и, если вы точно можете понять, что происходит, откройте другую проблему.

  • Проблема @Robophil слишком расплывчата, чтобы ее можно было решить.

У меня были совпадающие имена классов, и добавление префикса в параметрах createGenerateClassName решило проблему.

Пользовался большой, всеобъемлющий документ здесь

@oliviertassinari спасибо за резюме!

В одном дереве рендеринга реакции эта проблема, скорее всего, вызвана разными версиями material-ui в вашей сборке. Обязательно проверьте свое дерево зависимостей и проверьте, используются ли версии material-ui.

yarn list | grep material-ui

Моя конфигурация веб-пакета выглядит следующим образом

module.exports = {
    entry: {
        FirstComp: path.join(paths.JS, '/components/FirstComponent/MyFirstComp.js'),
        SecondComp: path.join(paths.JS, '/components/SecondComponent/MySecondComp.js'),
    },
}

У меня есть эти два компонента и общий компонент, созданный с использованием опции splitChunks.
Я обернул экспортированный компонент по умолчанию в MyFirstComp и MySecondComp с помощью JSSProvider.
Как мне использовать JSSProvider для общего компонента?

@Sewdn Я также думаю, что это может быть вызвано разными версиями material-ui. Эта проблема конфликта className была представлена ​​в моем приложении вчера, когда я начал переходить на хуки и хук useStyles, созданный makeStyles из @ material-ui / styles, который находится на 3.0.0-alpha.1
Также я использовал "@ material-ui / core" версии 3.6.0.

Внезапно мои классы приложений и классы material-ui начали с jss1, считая их параллельно. Это все перепутает. Мой заголовок, например, с jss5, также был стилизован под jss5, скажем, MuiListItem.

После выполнения этого решения https://github.com/mui-org/material-ui/issues/8223#issuecomment -412349569 от @iamhosseindhv классы mui-компонентов получили префикс ac, и проблема была решена.

@christiaanwesterbeek Правильно ли вы используете этап установки? Мы используем внедрение зависимостей. install() вызов должен выполняться перед импортом всех компонентов более высокого порядка.

@oliviertassinari Боюсь, я не знаю, о каком шаге вы говорите. Кроме того, я не знаю, частью чего является install() и где его нужно вызвать. Я был бы рад узнать об этом больше, но мне нужно знать, где это задокументировано.

@christiaanwesterbeek Я имею в виду https://material-ui.com/css-in-js/basics/#migration -for-material-ui-core-users.

@oliviertassinari Кажется, что install() нужно вызывать в каждом файле компонента? Может, нам нужно более четкое описание.

Может я ошибаюсь, установка не может разрешить конфликты.
To switch from the default style implementation to this newest version, you need to execute the following code before importing any Material-UI's components:

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

install();

@oliviertassinari Как установить before importing any Material-UI's components ?
импорт всегда выполняется babel и tsc статически

Импорт модулей bootstrap.js и сначала импортировать его:
https://github.com/mui-org/material-ui/blob/cb30b43e9c6cd49f9b16536a125456f5ea3a85c5/docs/src/modules/components/bootstrap.js#L1 -L13
Если проблема не исчезнет, ​​давайте перейдем к обсуждению другого вопроса.

@oliviertassinari Я переместил порядок импорта из

// entry index.js
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import CssBaseline from '@material-ui/core/CssBaseline'
import { install } from '@material-ui/styles'

к

import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { install } from '@material-ui/styles'
import CssBaseline from '@material-ui/core/CssBaseline'

код сообщает об ошибке Cannot read property 'text' of undefined . Проверив объект темы, он пуст.
Если я верну порядок импорта, эта часть будет работать нормально.

const useStyles = makeStyles(
  (theme: Theme) => ({
    root: {
      flexShrink: 0,
      color: theme.palette.text.secondary,
    },
  }),
)

Та же проблема возникает, когда я оборачиваю все приложение с помощью <StylesProvider>

@zheeeng

код сообщает об ошибке Cannot read property 'text' of undefined . Проверив объект темы, он пуст.

У меня такая же проблема. Это было исправлено обновлением "@ material-ui / core" до 3.6.0 или @ material-ui / styles до 3.0.0-alpha.1. Я забыл какой. Лучше сделайте и то, и другое.

Однако точная тема, которую получит функция, переданная в makeStyles, не была темой, которую я создал с помощью createMuiTheme. Вместо этого он получил тему по умолчанию. В конечном итоге я не стал полагаться на какую-либо тему, которая будет пройдена. Вместо этого я импортировал тему в каждый файл, который требовался стилям.

@christiaanwesterbeek Я установил @material-ui/[email protected] и @material-ui/styles/.0.0-alpha.2 но проблема не исчезла .

Кажется, это не связано с рассматриваемой проблемой (8223). Но все равно здесь. Просто импортируйте тему и не полагайтесь на ее передачу функции, которую вы передаете в makeStyles . И вы сделали.

Может ли кто-нибудь подтвердить, требуется ли по-прежнему этап установки для версии v3.7.0 (https://github.com/mui-org/material-ui/releases/tag/v3.7.0)

@christiaanwesterbeek да, это обязательно. Мы удалим этап установки в Material-UI v4.

@oliviertassinari, эй, у меня проблема с последней версией v3.9.0, и я не использую @ material-ui / styles, я все еще использую withStyles из core У меня два вопроса .

  1. мне следует перейти на mui / styes сейчас или дождаться выпуска v4. (крупномасштабное приложение)
  2. использование этого обходного пути https://github.com/mui-org/material-ui/issues/8223#issuecomment -331081785 - правильный способ решения этой проблемы? наконец, он отлично работает в сборке, но, похоже, не может понять, почему это происходит в первую очередь.

благодаря

У меня проблема с последней версией 3.9.0

@ w3nda Это слишком

мне следует перейти на mui / styes сейчас или дождаться выпуска v4. (крупномасштабное приложение)

Мы могли бы вернуть логику хеширования имени класса. Хотя это значительно повышает производительность сервера, это требует значительных затрат для клиента. Возможно, вместо этого мы предоставим флаг, чтобы включить его. Так что нет, я думаю, что лучший вариант - решить основную проблему. Вы пробовали эту страницу https://material-ui.com/guides/server-rendering/#troubleshooting ?

@oliviertassinari Спасибо за быстрый ответ, я действительно не знаю, как отладить проблему, и ссылка, которую вы упомянули, для меня не имеет отношения, потому что я использую ее как статический сайт ..
Если комментарий, на который я ссылаюсь, мне помог, разве он не должен указывать на причину этой проблемы в моем случае?

@ w3nda Статический сайт имеет ту же проблему. Вам нужно сгенерировать HTML, чтобы он использовал API рендеринга на стороне сервера. Если между двумя страницами происходит утечка счетчика индекса, имя класса будет неправильным. Что ж, я думаю, что более медленный генератор имени класса - хороший компромисс по сравнению с болью, связанной с отладкой такой проблемы (и насколько часто это происходит). Итак, да, вы можете перейти на @material-ui/styles , это простой аварийный выход.

У меня была аналогичная проблема, и это был старый импорт UI-материала, который был в одной из наших библиотек. Он работал нормально в режиме разработки, но не работал в продакшене. Я почти уверен, что это работало раньше, я не знаю, может ли быть выдано предупреждение в этом случае, даже если это явно наша вина.
Я обновил версии, чтобы они соответствовали проектам, и все снова заработало.

Привет, я использую материал только для одного ввода, кнопки и формы на моем сайте, и мне пришлось использовать <JssProvider /> после этого комментария https://github.com/mui-org/material-ui/issues / 8223 # issuecomment -331412432

Этот провайдер jss раздражает, есть ли еще какое-то исправление, которое не увеличило бы размер окончательной сборки?

@kopax Для чего вы используете JssProvider ?

Привет @oliviertassinari , в production перед посещением другого маршрута (мы используем response-router):

image

Через production после посещения маршрута или через development

image

Что-то похожее здесь происходит с формой (странные тени блоков), нам нужно посетить другую страницу, чтобы иметь правильный CSS, что происходит только в производственной среде:

image

Обе проблемы будут исправлены, если мы добавим JssProvider . (исправлено: у нас такой же css в production чем в development )

Понятия не имею. Я не могу помочь с предоставленной информацией.

Все тоже сломано. Я наблюдаю неправильный порядок jssXX классов в производстве и, как следствие, неправильный стиль. Это происходит после обновления страницы.

Пока не могу найти причину.

@oliviertassinari, возможно, те номера версии, которые использует [email protected], которые мы используем, помогут вам рассказать нам, что происходит:

        "@material-ui/core": "^1.4.0",
        "@material-ui/icons": "^1.0.0",
        "material-ui-chip-input": "1.0.0-beta.6 - 1.0.0-beta.8",

Не могли бы вы убедиться, что Material-UI входит в комплект только один раз ? Использование двух версий одновременно может привести к одинаковому ошибочному поведению.

Хорошо. Возможно. Мы используем react-admin которого рекомендована версия ~ 1.5.

Я решил ошибку на производстве, добавив JssProvider . Теперь я могу нормально обновить страницу.

import React from "react";
import { Admin, Resource } from "react-admin";
import JssProvider from "react-jss/lib/JssProvider";

const App = () => (
  <JssProvider>
    <Admin dataProvider={dataProvider}>
      <Resource name="trip" list={RequestsList} className="resourceItem" />
    </Admin>
  </JssProvider>
);

export default App;

@andrewkslv это именно то, чего мы пытаемся избежать, мы бы предпочли использовать его без JssProvider потому что мы используем только один компонент Input и Button из @ material-ui , вместо этого мы предпочитаем использовать для остальных другой пользовательский интерфейс для react-admin.

@oliviertassinari Я только что проверил, и у меня были проблемы с зависимостями. Я исправил это, но по-прежнему получаю ошибки со следующими npm ls @material-ui/core :

├─┬ @bootstrap-styled/[email protected]
│ └── @material-ui/[email protected] 
├── @material-ui/[email protected] 
└─┬ [email protected]
  └── @material-ui/[email protected] 

После выполнения:

rm -rf node_modules/@bootstrap-styled/ra-ui/node_modules/@material-ui/
rm -rf node_modules/ra-ui-materialui/node_modules/@material-ui/
npm ls @material-ui/core
├─┬ @bootstrap-styled/[email protected]
│ └── UNMET DEPENDENCY @material-ui/[email protected] 
├── @material-ui/[email protected] 
└─┬ [email protected]
  └── UNMET DEPENDENCY @material-ui/[email protected] 

Тогда теперь он работает (в производстве нет проблем с css). Думаю, это не то, что я хочу ...

Связанный проект @ material-ui dependencies:

Есть идеи, что делать?

@kopax Трудно сказать без того, что я могу отлаживать. Я рад слышать, что теперь он работает.

Я заметил, что вы используете стилизованные компоненты с Material-UI. Если у вас есть время, я хотел бы поговорить об интеграции с Gitter.

Рабочий раствор неестественный. Это означает, что это связано с задачей, которую нельзя запустить с помощью npm. Я не буду использовать это, я дал это как подсказку.

У нас будет шанс в понедельник, я присоединюсь к каналу mui gitter.

Привет @kopax , удалось найти решение?

Нет, не сейчас. Не обошлось и без провайдера. @oliviertassinari Я на gitter.

@andrewkslv Ваше решение действительно сработало для меня. Я также использую react-admin и AWS Amplify. Каждый раз, когда я развертывал свое приложение для реагирования на ведро S3, стиль был нарушен, и ваше решение действительно спасало меня.

Здесь та же проблема. Почему помогает добавление JssProvider?

Я добавил предупреждение в версии 4, чтобы предупредить об использовании дублированных экземпляров стиля: # 15422.

Я не знаю. Я поднял эту проблему в react-admin когда они внедряли новую версию пользовательского интерфейса материалов в структуру, но она была проигнорирована.

https://github.com/marmelab/react-admin/pull/3102#issuecomment -484228320

Где я могу найти решение о производственной сборке - конфликты имен классов # 8223?

Благодаря,

@oliviertassinari Снова столкнулся с этой проблемой, хотя я выполнил все инструкции. Поскольку это работает для других, я думаю, что мне не хватает чего-то базового.

https://stackoverflow.com/questions/58938080/jssprovider-not-generating-class-prefix-with-classnameprefix

Я использую следующие версии пакетов.

"@ material-ui / core": "^ 4.6.1",
"@ material-ui / icons": "^ 4.5.1",
"реагировать": "^ 16.12.0",
"react-dom": "^ 16.12.0",
"react-jss": "^ 10.0.0",
"react-scripts": "3.2.0"

Обновление: проблема решена. Извините за то, что не изучил документацию полностью. Эта часть документации решила мою проблему.

https://material-ui.com/styles/api/#creategenerateclassname -options-class-name-generator

Но почему-то решение JSSProvider, которое работало для всех остальных, не работало для меня. В любом случае, спасибо :)

Спасибо @KannugoPrithvi , это хорошее решение! https://material-ui.com/styles/api/#creategenerateclassname -options-class-name-generator

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

finaiized picture finaiized  ·  3Комментарии

ericraffin picture ericraffin  ·  3Комментарии

reflog picture reflog  ·  3Комментарии

FranBran picture FranBran  ·  3Комментарии

rbozan picture rbozan  ·  3Комментарии