Material-ui: build de produção - conflitos de nomes de classe

Criado em 15 set. 2017  ·  62Comentários  ·  Fonte: mui-org/material-ui


As definições dos nomes das classes css são duplicadas para alguns componentes - no meu caso, é duplicado (eu acho que pela minha depuração) para MuiIconButton e MuiModal - verifique o comportamento atual

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

Comportamento esperado

Os nomes das classes não devem ser duplicados entre os componentes.

Comportamento Atual

Meus estilos de botão:
classnames_conflict
A classe está duplicada.
Definição de estilos:
classnames_conflit_2

Está funcionando em modo de desenvolvimento:
Meus estilos de botões:
development_class

e encontrei as definições:
mui-icon-button-dev

e do modal:
mui-modal-dev

Etapas para reproduzir (para bugs)

Posso tentar preparar o ambiente para reproduzir o problema, mas agora só queria relatar aqui.

Contexto


Estou tentando lançar meu aplicativo com o ambiente de produção.

Seu Ambiente

| Tech | Versão |
| -------------- | --------- |
| Material-UI | 1.0.0-beta.10 |
| Reagir | 15.6.1 |
| navegador | qualquer |
| webpack | ^ 3.3.0 |

Preciso de algumas dicas de onde pode estar o problema. Não estou usando a solução withStyles nenhum lugar - eu uso componentes estilizados para substituir estilos.

bug 🐛

Comentários muito úteis

Eu tinha os nomes de classe colidindo e adicionando um prefixo em createGenerateClassName options resolveu o problema.

Usei o excelente e abrangente documento aqui

Todos 62 comentários

Já vi alguns problemas em torno desse problema. Ele sempre foi vinculado a instâncias duplicadas do gerador de className. Não posso ajudar mais sem uma reprodução.

Estou encerrando o problema por enquanto como não acionável. Deixe-me saber se você tem um exemplo de reprodução.

@oliviertassinari Consegui reproduzir o problema. Aqui está o webpack bin - https://www.webpackbin.com/bins/-KuO6ia3h-JDpBOJncZ3

No meu caso, tenho 2 raízes de aplicativo que são montadas independentemente em 2 div diferentes. Ambos usam o mesmo material-ui ThemeProvider embrulhado com JssProvider para substituir insertionPoint de _jss_.

generate_classnames_counter

Com base na função createGenerateClassName , você usa contador para ter nomes de classe exclusivos

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}`;
  };
}

E minha captura de tela confirma que, por algum motivo, o contador está duplicado.

Eu preciso de ajuda. Não sei o que estou fazendo de errado agora.

@darkowic Você precisa compartilhar a instância jss entre as diferentes árvores de reação. Você deve estar bem com essa mudança.

@oliviertassinari Acho que estou fazendo isso usando meu ThemeProvider

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

Eu envolvo todas as minhas árvores de reação com isso.

Este problema deve ser aberto.

Claro, vamos resumir o que sabemos até agora. Esse problema surge assim que você usa a árvore de renderização de reação múltipla. O provedor jss criará dois geradores de nome de classe, um para cada árvore. Portanto, acabamos com conflitos de nome de classe.
@kof Devemos estender o JssProvider de react-jss para aceitar um gerador de nome de classe?

SOLUÇÃO ALTERNATIVA para o aplicativo do lado do cliente: você pode criar seu próprio createGenerateClassName e mover ruleCounter fora da função de empacotador

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}`;
  };
}

Boa, tínhamos um caso de uso no servidor e eu já estava planejando para obter uma dica ousada na documentação, consulte # 5

Mas agora você realmente encontrou um bom motivo para oferecer suporte a 2 provedores de execução paralela.

Precisamos pesquisar se há casos de uso para uma forte necessidade de vários JssProviders paralelos. Se houver, precisamos pensar em algo para apoiá-lo.

@kof Você acabou de encontrar um caso de uso para vários JssProviders paralelos no lado do cliente. E acho que a solução proposta é simples de implementar :).

mover ruleCounter para fora da função wrapper

Isso significa que, no servidor, o ruleCounter nunca será redefinido. Não podemos fazer isso.

No lado do servidor, o JssProviders definitivamente precisa oferecer suporte a renderização assíncrona simultânea de uma árvore de reação (forte necessidade). Mas a implementação atual já o torna compatível :)

@darkowic Proposta de solução alternativa sem acesso à pilha subjacente. Nós fazemos. Podemos fazer melhor com esta flexibilidade extra: aceitar uma instância do gerador de nome de classe.

Além disso, a solicitação para o mesmo terminal deve sempre responder com os mesmos nomes de classe.

@kof Devemos estender o JssProvider de react-jss para aceitar um gerador de nome de classe?

  1. Sim, uma maneira possível seria permitir que JssProvider aceite um gerador de nome de classe como este:

import {createGenerateClassName} from 'react-jss'

const generateClassName = createGenerateClassName()

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

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

  1. Outra opção potencial seria fornecer algum prefixo, como o nome de um aplicativo. Isso pode funcionar se assumirmos que não temos uma quantidade imprevisível de aplicativos.

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

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

Pro 1:

  • O usuário não precisa fornecer o prefixo

Pro 2:

  • O usuário pode ter algo significativo nos nomes da classe DOM que identifica o aplicativo durante o desenvolvimento
  • O usuário tem mais controle sobre o prefixo.
  • É relativamente fácil ter um prefixo não conflitante. Ou você tem apenas algumas subárvores e nomear já é fácil o suficiente ou você pode adicionar seu próprio prefixo de número a esses nomes e redefini-los em cada solicitação.

Na verdade, faz sentido ter ambos os adereços classNamePrefix e generateClassName . Primeiro para depuração, segundo para exclusividade automatizada de nomes de classe.

Eu encontrei esse problema via https://github.com/facebookincubator/create-react-app/issues/3173 (e o caso de teste reduzido vinculado).

No meu caso, um componente dependente da IU material (v1.0.0-beta.11) foi incluído em um aplicativo que também usa material-ui (mesmas versões). No desenvolvimento, isso funciona bem, mas na produção o layout é quebrado devido a nomes de classes conflitantes.

Não tenho certeza se isso se qualifica como "árvores de renderização de reação múltipla" e movendo var ruleCounter = 0; antes de createGenerateClassName() _não_ solução alternativa para o problema, mas comentar o seguinte, _did_ funcionou:

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

Não pude fornecer mais informações no momento em que abri o número 7855.😊
Este comentário cobre basicamente o problema que enfrentei ao executar a compilação de produção.

Uma solução alternativa para isso no pipeline?

Criado um PR que deve corrigir isso em react-jss https://github.com/cssinjs/react-jss/pull/155

Então, vamos resumir.

  • @darkowic de causar problemas de raiz é descrita aqui: https://github.com/callemall/material-ui/issues/8223#issuecomment -331076580 e será corrigido graças à @kof 's PR: cssinjs / reagem-jss # 155 e um novo aviso será adicionado para evitar essa situação no futuro: # 8341.

  • Os sintomas do problema de

  • O problema de @Robophil é muito vago para ser acionado.

Eu tinha os nomes de classe colidindo e adicionando um prefixo em createGenerateClassName options resolveu o problema.

Usei o excelente e abrangente documento aqui

@oliviertassinari obrigado pelo resumo!

Em uma única árvore de renderização react, esse problema é provavelmente causado por diferentes versões do material-ui em sua construção. Certifique-se de verificar sua árvore de dependências e verificar as versões material-ui sendo usadas.

yarn list | grep material-ui

Minha configuração do webpack é a seguinte

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

Eu tenho esses dois componentes e um componente comum que é construído usando a opção splitChunks.
Eu envolvi o componente exportado padrão em MyFirstComp e MySecondComp usando JSSProvider.
Como devo usar o JSSProvider em torno do componente comum?

@Sewdn Eu também acho que pode ser causado por diferentes versões do material-ui. Este problema de conflito de className foi introduzido em meu aplicativo ontem quando comecei a migrar para ganchos e o gancho useStyles criado por makeStyles de @ material-ui / styles que está em 3.0.0-alpha.1
Também estava usando "@ material-ui / core" que está em 3.6.0

De repente, minhas classes de aplicativos e as classes de material-ui começaram com jss1, contando em paralelo. Isso misturaria tudo. Meu cabeçalho, por exemplo, com jss5 também foi estilizado com o jss5 de, digamos, MuiListItem.

Depois de seguir essa solução https://github.com/mui-org/material-ui/issues/8223#issuecomment -412349569 por @iamhosseindhv as classes dos mui-componentes foram prefixadas com ac e o problema foi resolvido.

@christiaanwesterbeek Você está usando a etapa de instalação corretamente? Usamos injeção de dependência. install() chamada precisa ser executada antes de todas as importações de componentes de ordem superior.

@oliviertassinari Infelizmente, não sei a que etapa você está se referindo. Além disso, não sei do que install() faz parte e onde deve ser chamado. Ficaria feliz em saber mais sobre isso, mas preciso saber onde está documentado.

@christiaanwesterbeek Estou me referindo a https://material-ui.com/css-in-js/basics/#migration -for-material-ui-core-users.

@oliviertassinari Parece que install() deve ser chamado em cada arquivo de componente? Talvez precisemos de uma descrição mais clara.

Talvez eu esteja errado, a instalação não resolve conflitos.
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 Como instalar before importing any Material-UI's components ?
a importação é sempre feita por babel e tsc estaticamente

@zheeeng As importações de módulos ES são içadas para o topo do módulo e resolvidas de forma síncrona na ordem em que são definidas. Temos enfrentado o mesmo problema com a documentação da IU do material. A solução era empacotar tudo em um módulo bootstrap.js e importá-lo primeiro:
https://github.com/mui-org/material-ui/blob/cb30b43e9c6cd49f9b16536a125456f5ea3a85c5/docs/src/modules/components/bootstrap.js#L1 -L13
Se o problema persistir, por favor, passemos à discussão para um problema diferente.

@oliviertassinari Mudei o pedido de importação de

// 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'

para

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

o código relata o erro Cannot read property 'text' of undefined . Ao inspecionar o objeto do tema, ele está vazio.
Se eu voltar a ordem de importação, essa parte funcionará bem.

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

O mesmo problema acontece quando envolvo todo o aplicativo com <StylesProvider>

@zheeeng

o código relata o erro Cannot read property 'text' of undefined . Ao inspecionar o objeto do tema, ele está vazio.

Eu tive o mesmo problema. Foi corrigido atualizando "@ material-ui / core" para 3.6.0 ou @ material-ui / styles que para 3.0.0-alpha.1. Eu esqueci qual. Melhor fazer as duas coisas.

Porém, o tema exato que a função passada para makeStyles receberia, não era o tema que eu havia criado com createMuiTheme. Em vez disso, obteve o tema padrão. O que acabei fazendo foi não confiar em nenhum tema que seria aprovado. Em vez disso, importei o tema em todos os arquivos de que os estilos precisavam.

@christiaanwesterbeek Eu instalei @material-ui/[email protected] e @material-ui/styles/.0.0-alpha.2 e ainda tenho esse problema.

Isso parece não ter relação com este problema (8223) em questão. Mas aqui vai de qualquer maneira. Apenas importe o tema e não dependa que ele seja passado para a função que você passou para makeStyles . E pronto.

Alguém pode confirmar se a etapa de instalação ainda é necessária com a v3.7.0 (https://github.com/mui-org/material-ui/releases/tag/v3.7.0)

@christiaanwesterbeek sim, é obrigatório. Removeremos a etapa de instalação no Material-UI v4.

@oliviertassinari ei, estou tendo esse problema com a última v3.9.0 e não estou usando @ material-ui / styles, ainda estou usando withStyles de core Tenho duas perguntas .

  1. devo migrar agora para mui / styes ou aguardar o lançamento da v4. (aplicativo em grande escala)
  2. usar esta solução alternativa https://github.com/mui-org/material-ui/issues/8223#issuecomment -331081785 é a maneira correta de lidar com esse problema? finalmente funciona bem na construção, mas não consigo entender por que isso está acontecendo em primeiro lugar.

obrigado

Estou tendo esse problema com a última v3.9.0

@ w3nda Isso é muito genérico, há um milhão de razões diferentes para esse problema acontecer.

devo migrar agora para mui / styes ou aguardar o lançamento da v4. (aplicativo em grande escala)

Podemos reverter a lógica de hashing do nome da classe. Embora melhore muito o desempenho no servidor, tem um custo significativo para o cliente. Em vez disso, forneceremos um sinalizador para habilitá-lo. Portanto, não, acho que a melhor opção é resolver o problema principal. Você tentou esta página https://material-ui.com/guides/server-rendering/#trou troubleshooting ?

@oliviertassinari Obrigado pela resposta rápida, eu realmente não sei como depurar o problema e o link que você mencionou não é relevante para mim porque eu o sirvo como um site estático.
Embora o comentário que mencionei tenha me ajudado, não deveria dizer a causa desse problema no meu caso?

O site @ w3nda Static tem o mesmo problema. Você precisa gerar o HTML, então ele usará a API de renderização do lado do servidor. Se o contador do índice vazar entre duas páginas, o nome da classe não estará correto. Bem, eu acho que um gerador de nome de classe mais lento é uma boa troca em comparação com a dificuldade de depurar esse problema (e quão frequente é). Então, sim, você pode atualizar para @material-ui/styles , é uma saída de emergência simples.

Acabei de ter um problema semelhante e era uma importação de material-ui antigo que estava em uma de nossas bibliotecas. Funcionou bem no modo de desenvolvimento, mas foi interrompido na produção. Tenho certeza de que isso estava funcionando antes, não sei se um aviso poderia ser emitido neste caso, mesmo que seja claramente nossa culpa.
Eu atualizei as versões para combiná-las entre os projetos e tudo funcionou novamente.

Olá, estou usando o material apenas para uma única entrada, botão e formulário em meu site e tive que usar um <JssProvider /> após este comentário https://github.com/mui-org/material-ui/issues / 8223 # issuecomment -331412432

É irritante precisar desse provedor jss. Existe outra correção que possamos fazer que não aumente o tamanho final da compilação?

@kopax Para que você está usando JssProvider ?

Olá @oliviertassinari , Em production antes de visitar outra rota (usamos react-router):

image

Em production depois de visitar uma rota ou em development

image

Algo semelhante aqui acontece com um formulário (estranhas sombras de caixa), precisamos visitar outra página para ter o css adequado, isso só acontece na produção:

image

Ambos os problemas serão corrigidos se adicionarmos JssProvider . (corrigido: temos o mesmo css em production que em development )

Eu não faço ideia. Não posso ajudar com as informações fornecidas.

Tudo está quebrado também. Eu observo jssXX classes erradas na produção e, como resultado, o estilo errado. Acontece depois de atualizar a página.

Ainda não consigo encontrar o motivo.

@oliviertassinari talvez os números da versão usados ​​por [email protected] que estamos usando ajudem a nos contar o que está acontecendo:

        "@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",

Você poderia ter certeza de que Material-UI é empacotado apenas uma vez ? Usar duas versões ao mesmo tempo pode criar o mesmo comportamento com erros.

Bem. É possível. Estamos usando react-admin que tem a versão recomendada ~ 1.5.

Resolvi o bug na produção adicionando JssProvider . Agora posso atualizar a página normalmente.

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 isso é exatamente o que estamos tentando evitar, preferimos usá-lo sem JssProvider porque usamos apenas um componente Input e Button de @ material-ui , em vez disso, preferimos usar para o resto outra interface do

@oliviertassinari Acabei de verificar e tive alguns problemas de dependências. Eu corrigi, mas ainda recebo os erros com o seguinte npm ls @material-ui/core :

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

Depois de fazer:

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] 

Então agora funciona (nenhum problema de css na produção). Acho que não é isso que eu quero ...

Dependências de projeto @ material-ui relacionadas:

alguma ideia do que fazer?

@kopax É difícil dizer sem algo que possa depurar. Fico feliz em saber que está funcionando agora.

Percebi que você está usando componentes estilizados com Material-UI. Se você tiver algum tempo, adoraria conversar sobre a integração no Gitter.

A solução de trabalho não é natural. O que significa que envolve tarefas que não podem ser executadas com o npm. Não vou usar, dei isso como uma dica.

Teremos a chance na segunda, vou entrar no canal mui gitter.

Olá @kopax , você conseguiu encontrar uma solução?

Não, ainda não. Não sem o provedor. @oliviertassinari Estou no gitter.

@andrewkslv Sua solução realmente funcionou para mim. Também estou usando react-admin e AWS Amplify. Sempre que eu implantaria meu aplicativo de reação em um balde S3, o estilo estaria todo quebrado e sua solução realmente me salvou.

O mesmo problema aqui. Por que adicionar JssProvider ajuda?

Eu adicionei um aviso na v4 para avisar quando instâncias de estilo duplicadas são usadas: # 15422.

Eu não sei. Eu levantei esse problema em react-admin quando eles estavam implementando uma nova versão do material da interface do usuário para o framework, mas ele foi ignorado.

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

Onde posso encontrar a solução sobre a construção de produção - conflitos de nomes de classe # 8223?

Obrigado,

@oliviertassinari Enfrentando esse problema novamente, apesar de ter seguido todas as instruções. Já que está funcionando para outras pessoas, acho que pode estar faltando algo básico.

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

Estou usando as seguintes versões dos pacotes.

"@ material-ui / core": "^ 4.6.1",
"@ material-ui / icons": "^ 4.5.1",
"react": "^ 16.12.0",
"react-dom": "^ 16.12.0",
"react-jss": "^ 10.0.0",
"react-scripts": "3.2.0"

Atualização: o problema foi resolvido. Desculpe por não examinar a documentação completamente. Esta parte da documentação resolveu meu problema.

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

Mas de alguma forma, a solução JSSProvider que estava funcionando para todos os outros, não estava funcionando para mim. De qualquer forma, obrigado :)

Obrigado @KannugoPrithvi , esta é a boa solução! https://material-ui.com/styles/api/#creategenerateclassname -options-class-name-generator

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