Material-ui: generación de producción - conflictos de nombres de clases

Creado en 15 sept. 2017  ·  62Comentarios  ·  Fuente: mui-org/material-ui


Las definiciones de los nombres de clase css están duplicadas para algunos componentes; en mi caso, está duplicado (supongo que por mi depuración) para MuiIconButton y MuiModal - verifique el comportamiento actual

  • [x] He buscado las ediciones de este repositorio y creo que esto no es un duplicado.

Comportamiento esperado

Los nombres de las clases no deben duplicarse en los componentes.

Comportamiento actual

Mis estilos de botones:
classnames_conflict
La clase está duplicada.
Definición de estilos:
classnames_conflit_2

Está funcionando en modo de desarrollo:
Mis estilos de botones:
development_class

y encontré las definiciones:
mui-icon-button-dev

y de modal:
mui-modal-dev

Pasos para reproducir (para errores)

Puedo intentar preparar el entorno para reproducir el problema, pero ahora solo quería informarlo aquí.

Contexto


Estoy intentando lanzar mi aplicación con el entorno de producción.

Tu entorno

| Tech | Versión |
| -------------- | --------- |
| Material-UI | 1.0.0-beta.10 |
| Reaccionar | 15.6.1 |
| navegador | cualquiera |
| paquete web | ^ 3.3.0 |

Necesito algunas pistas sobre dónde puede estar el problema. No estoy usando la solución withStyles ninguna parte; uso componentes con estilo para anular estilos.

bug 🐛

Comentario más útil

Tenía los nombres de clase que colisionaban y agregar un prefijo en las opciones createGenerateClassName resolvió el problema.

Usé el gran y completo documento aquí

Todos 62 comentarios

Ya he visto algún problema relacionado con este problema. Siempre estuvo vinculado a instancias de generador de className duplicadas. No puedo ayudar más sin una reproducción.

Estoy cerrando el problema por ahora como no procesable. Avísame si tienes un ejemplo de reproducción.

@oliviertassinari pude reproducir el problema. Aquí está el contenedor de paquetes web: https://www.webpackbin.com/bins/-KuO6ia3h-JDpBOJncZ3

En mi caso, tengo 2 raíces de aplicación que se montan de forma independiente en 2 div diferentes. Ambos usan el mismo material-ui ThemeProvider envuelto con JssProvider para anular insertionPoint de _jss_.

generate_classnames_counter

Basado en la función createGenerateClassName , usa el contador para tener nombres de clase únicos

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

Y mi captura de pantalla confirma que, por alguna razón, el contador está duplicado.

Necesito ayuda. No sé qué estoy haciendo mal ahora mismo.

@darkowic Necesita compartir la instancia jss entre los diferentes árboles de reacción. Deberías estar bien con ese cambio.

@oliviertassinari Creo que lo estoy haciendo usando mi ThemeProvider

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

Envuelvo todos mis árboles de reacción con esto.

Este problema debería abrirse.

Seguro, resumamos lo que sabemos hasta ahora. Este problema surge tan pronto como está utilizando el árbol de representación de reacción múltiple. El proveedor jss va a crear dos generadores de nombres de clases, uno para cada árbol. Por lo tanto, terminamos con conflictos de nombres de clases.
@kof ¿Deberíamos extender JssProvider de react-jss para aceptar un generador de nombre de clase?

SOLUCIÓN ALTERNATIVA para la aplicación del lado del cliente: puede crear su propio createGenerateClassName y mover ruleCounter fuera de la función contenedora

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

Bonito, teníamos un caso de uso de este tipo en el servidor y ya estaba planeando una pista en negrita en la documentación, ver n.

Pero ahora ha encontrado una buena razón para admitir 2 proveedores de ejecución paralela.

Necesitamos investigar si hay casos de uso para una gran necesidad de múltiples JssProviders paralelos. Si los hay, debemos pensar en algo que lo respalde.

@kof Acaba de encontrar un caso de uso para varios JssProviders paralelos en el lado del cliente. Y creo que la solución propuesta es sencilla de implementar :).

mover ruleCounter fuera de la función contenedora

Esto significará que en el servidor, ruleCounter nunca se reiniciará. No podemos hacer eso.

En el lado del servidor, JssProviders definitivamente necesita admitir la representación asíncrona concurrente de un árbol de reacción (gran necesidad). Pero la implementación actual hace que ya sea compatible :)

@darkowic propuso una solución al no tener acceso a la pila subyacente. Hacemos. Podemos hacerlo mejor con esta flexibilidad adicional: aceptar una instancia de generador de nombre de clase.

Además, la solicitud al mismo punto final siempre debe responder con los mismos nombres de clase.

@kof ¿Deberíamos extender JssProvider de react-jss para aceptar un generador de nombre de clase?

  1. Sí, una forma posible sería permitir que JssProvider acepte un generador de nombre de clase como este:

import {createGenerateClassName} from 'react-jss'

const generateClassName = createGenerateClassName()

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

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

  1. Otra posible opción sería proporcionar algún prefijo, como el nombre de una aplicación. Esto podría funcionar si asumimos que no tenemos una cantidad impredecible de aplicaciones.

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

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

Pro 1:

  • El usuario no necesita proporcionar el prefijo

Pro 2:

  • El usuario puede tener algo significativo en los nombres de las clases DOM que identifique la aplicación durante el desarrollo.
  • El usuario tiene más control sobre el prefijo.
  • Es relativamente fácil tener un prefijo no conflictivo. O tiene solo algunos subárboles y la asignación de nombres ya es bastante fácil o puede agregar su propio prefijo numérico a esos nombres y restablecerlos en cada solicitud.

En realidad, tiene sentido tener ambos accesorios classNamePrefix y generateClassName . Primero para la depuración, segundo para la unicidad automatizada de los nombres de clase.

Me encontré con este problema a través de https://github.com/facebookincubator/create-react-app/issues/3173 (y el caso de prueba reducido vinculado).

En mi caso, se incluyó un componente material dependiente de la interfaz de usuario (v1.0.0-beta.11) en una aplicación que también usa material-ui (mismas versiones). En desarrollo, esto funciona bien, pero en producción el diseño está roto debido a nombres de clases en conflicto.

No estoy seguro de si esto califica como "múltiples árboles de representación de reacción" y mover var ruleCounter = 0; antes de createGenerateClassName() _did_ no_ solucionó el problema, pero comentando lo siguiente, _did_ funcionó:

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

Lo siento, no pude proporcionar más información en el momento en que abrí # 7855.😊
Este comentario básicamente cubre el problema que enfrenté al ejecutar la compilación de producción.

¿Una solución para esto en proceso?

Creé un PR que debería solucionar esto en react-jss https://github.com/cssinjs/react-jss/pull/155

Así que resumamos.

  • @darkowic 's causa problemas de raíz se describe aquí: https://github.com/callemall/material-ui/issues/8223#issuecomment -331 076 580 y se fija gracias a @kof' s PR: cssinjs / reaccionan JSS-# 155 y se agregará una nueva advertencia para evitar esta situación en el futuro: # 8341.

  • Los síntomas del problema de

  • El problema de @Robophil es demasiado vago para ser procesable.

Tenía los nombres de clase que colisionaban y agregar un prefijo en las opciones createGenerateClassName resolvió el problema.

Usé el gran y completo documento aquí

@oliviertassinari gracias por el resumen!

En un solo árbol de renderizado de reacción, es muy probable que este problema sea causado por diferentes versiones de material-ui en su compilación. Asegúrese de verificar su árbol de dependencias y verificar si se están utilizando versiones de material-ui.

yarn list | grep material-ui

Mi configuración de paquete web es la siguiente

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

Tengo estos dos componentes y un componente común que se crea con la opción splitChunks.
Envolví el componente exportado predeterminado en MyFirstComp y MySecondComp usando JSSProvider.
¿Cómo debería utilizar JSSProvider en torno al componente común?

@Sewdn También creo que puede ser causado por diferentes versiones de material-ui. Este problema de conflicto de className se introdujo en mi aplicación ayer cuando comencé a migrar a hooks y el hook useStyles creado por makeStyles desde @ material-ui / styles que está en 3.0.0-alpha.1
También estaba usando "@ material-ui / core" que está en 3.6.0

De repente, mis clases de aplicaciones y las clases de material-ui comenzaron con jss1, contando en paralelo. Eso mezclaría todo. Mi encabezado, por ejemplo, con jss5 también fue diseñado con el jss5 de digamos MuiListItem.

Después de seguir esta solución https://github.com/mui-org/material-ui/issues/8223#issuecomment -412349569 por @iamhosseindhv, las clases de los componentes mui obtuvieron el prefijo ac y el problema se resolvió.

@christiaanwesterbeek ¿Está utilizando el paso de instalación correctamente? Usamos la inyección de dependencia. install() call debe ejecutarse antes de todas las importaciones de componentes de orden superior.

@oliviertassinari Me temo que no sé a qué paso te refieres. Además, no sé de qué forma parte install() y dónde debe llamarse. Me encantaría saber más sobre él, pero necesito saber dónde está documentado.

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

@oliviertassinari ¿ Parece que se debería llamar install() en el archivo de cada componente? Quizás necesitemos una descripción más clara.

Tal vez me equivoque, la instalación no puede resolver los conflictos.
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 ¿Cómo instalarlo before importing any Material-UI's components ?
la importación siempre la manejan babel y tsc estáticamente

Las importaciones de módulos de elevan a la parte superior del módulo y se resuelven sincrónicamente en el orden en que se definen. Nos hemos enfrentado al mismo problema con la documentación de Material-UI. La solución fue empaquetar todo en un módulo bootstrap.js e importarlo primero:
https://github.com/mui-org/material-ui/blob/cb30b43e9c6cd49f9b16536a125456f5ea3a85c5/docs/src/modules/components/bootstrap.js#L1 -L13
Si el problema persiste, pasemos a la discusión sobre un tema diferente.

@oliviertassinari Moví la orden de importación 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'

a

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

el código informa de error Cannot read property 'text' of undefined . Al inspeccionar el objeto del tema, está vacío.
Si cambio el orden de importación, esta parte funciona bien.

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

El mismo problema ocurre cuando envuelvo toda la aplicación con <StylesProvider>

@zheeeng

el código informa de error Cannot read property 'text' of undefined . Al inspeccionar el objeto del tema, está vacío.

Yo tuve el mismo problema. Se solucionó actualizando "@ material-ui / core" a 3.6.0 o @ material-ui / styles que a 3.0.0-alpha.1. Olvidé cuál. Mejor haz ambas cosas.

Sin embargo, el tema exacto que recibiría la función pasada a makeStyles no era el tema que había creado con createMuiTheme. En cambio, obtuvo el tema predeterminado. Lo que terminé haciendo fue no confiar en cualquier tema que se aprobara. En su lugar, importé el tema en cada archivo que los estilos lo necesitaban.

@christiaanwesterbeek Instalé @material-ui/[email protected] y @material-ui/styles/.0.0-alpha.2 y todavía tengo este problema.

Esto parece no estar relacionado con este problema (8223) en cuestión. Pero aquí va de todos modos. Simplemente importe el tema y no confíe en que se pase a la función que pasa a makeStyles . Y tu estas listo.

¿Alguien puede confirmar si el paso de instalación todavía es necesario con v3.7.0 (https://github.com/mui-org/material-ui/releases/tag/v3.7.0)

@christiaanwesterbeek sí, es obligatorio. Eliminaremos el paso de instalación en Material-UI v4.

@oliviertassinari hey, estoy experimentando este problema con la última versión v3.9.0 y no estoy usando @ material-ui / styles, todavía estoy usando withStyles de core Tengo dos preguntas .

  1. ¿Debo migrar ahora a mui / styes o esperar a la versión 4? (aplicación a gran escala)
  2. usando esta solución https://github.com/mui-org/material-ui/issues/8223#issuecomment -331081785 ¿es la forma correcta de manejar este problema? finalmente funciona bien en la compilación, pero parece que no puede entender por qué está sucediendo en primer lugar.

Gracias

Estoy experimentando este problema con la última v3.9.0

@ w3nda Esto es demasiado genérico, hay un millón de razones diferentes para que ocurra este problema.

¿Debo migrar ahora a mui / styes o esperar a la versión 4? (aplicación a gran escala)

Podríamos revertir la lógica de hash del nombre de clase. Si bien mejora considerablemente el rendimiento en el servidor, tiene un costo significativo para el cliente. Quizás proporcionemos una bandera para habilitarlo en su lugar. Entonces no, creo que la mejor opción es resolver el problema central. ¿Intentó esta página https://material-ui.com/guides/server-rendering/#troubleshooting ?

@oliviertassinari Gracias por la respuesta rápida, realmente no sé cómo depurar el problema y el enlace que mencionaste no es relevante para mí porque lo sirvo como un sitio estático.
Si el comentario al que hice referencia me ayudó, ¿no debería indicar la causa de este problema en mi caso?

@ w3nda El sitio web estático tiene el mismo problema. Debe generar el HTML, por lo que utilizará la API de representación del lado del servidor. Si el contador de índice se filtra entre dos páginas, el nombre de la clase no será correcto. Bueno, creo que un generador de nombres de clase más lento es una buena compensación en comparación con el dolor que supone depurar un problema de este tipo (y con qué frecuencia es). Entonces, sí, puede actualizar a @material-ui/styles , es una simple trampilla de escape.

Acabo de tener un problema similar y era una importación de material-ui antigua que estaba en una de nuestras bibliotecas. Funcionó bien en modo de desarrollo pero se rompió en producción. Estoy bastante seguro de que esto funcionaba antes, no sé si se podría emitir una advertencia en este caso, incluso si claramente es culpa nuestra.
Actualicé las versiones para hacerlas coincidir entre proyectos y todo funcionó nuevamente.

Hola, estoy usando material solo para una sola entrada, botón y formulario en mi sitio y tuve que usar un <JssProvider /> siguiendo este comentario https://github.com/mui-org/material-ui/issues / 8223 # issuecomment -331412432

Es molesto necesitar este proveedor jss, ¿hay otra solución que podamos hacer que no aumente el tamaño de compilación final?

@kopax ¿ JssProvider ?

Hola @oliviertassinari , En production antes de visitar otra ruta (usamos react-router):

image

En production después de visitar una ruta o en development

image

Algo similar sucede aquí con un formulario (sombras de caja raras), necesitamos visitar otra página para tener el CSS adecuado, eso solo ocurre en producción:

image

Ambos problemas se solucionan si agregamos JssProvider . (solucionado: tenemos el mismo CSS en production que en development )

No tengo idea. No puedo ayudar con la información proporcionada.

Todo está roto también. Observo clases de orden jssXX incorrectas en producción y, como resultado, el estilo incorrecto. Ocurre después de actualizar la página.

Aún no puedo encontrar el motivo.

@oliviertassinari tal vez el número de versión usado por [email protected] que estamos usando lo ayudaría a decirnos qué está pasando:

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

¿Puede asegurarse de que Material-UI solo se incluya una vez ? El uso de dos versiones al mismo tiempo puede crear el mismo comportamiento con errores.

Bien. Es posible. Estamos usando react-admin que ha recomendado la versión ~ 1.5.

Resolví el error en producción agregando JssProvider . Ahora puedo actualizar la 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 esto es exactamente lo que estamos tratando de evitar, preferiríamos usarlo sin JssProvider porque solo usamos un componente Input y Button de @ material-ui , en cambio, preferimos usar para el resto otra interfaz de usuario para react-admin.

@oliviertassinari Acabo de verificar y tuve algunos problemas de dependencias. Lo arreglé pero todavía tengo los errores con los siguientes npm ls @material-ui/core :

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

Después de hacer:

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] 

Entonces ahora funciona (no hay problema de CSS en producción). Supongo que esto no es lo que quiero ...

Proyecto relacionado con dependencias de material-ui:

¿Alguna idea de qué hacer?

@kopax Es difícil saberlo sin algo que pueda depurar. Me alegra saber que está funcionando ahora.

Me he dado cuenta de que está utilizando componentes con estilo con Material-UI. Si tiene algo de tiempo, me encantaría charlar sobre la integración en Gitter.

La solución de trabajo no es natural. Lo que significa que implica una tarea que no se puede ejecutar con npm. No lo usaré, di esto como una pista.

Tendremos la oportunidad el lunes, me uniré al canal mui gitter.

Hola @kopax , ¿

No aún no. No sin el proveedor. @oliviertassinari Estoy en gitter.

@andrewkslv Tu solución realmente funcionó para mí. También estoy usando react-admin y AWS Amplify. Cada vez que implementaba mi aplicación de reacción en un bucket de S3, el estilo se rompía y su solución realmente me salvó.

El mismo problema aquí. ¿Por qué ayuda agregar JssProvider?

He agregado una advertencia en v4 para advertir cuando se usan instancias de estilo duplicadas: # 15422.

No lo sé. Planteé este problema en react-admin cuando estaban implementando una nueva versión de material ui en el marco, pero fue ignorado.

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

¿Dónde puedo encontrar la solución sobre la compilación de producción - conflictos de nombres de clase # 8223?

Gracias,

@oliviertassinari Volviendo a

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

Estoy usando las siguientes versiones de los paquetes.

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

Actualización: el problema se resolvió. Perdón por no haber revisado la documentación a fondo. Esta parte de la documentación resolvió mi problema.

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

Pero de alguna manera, la solución JSSProvider que funcionaba para todos los demás, no funcionaba para mí. De todos modos, gracias :)

Gracias @KannugoPrithvi , ¡esta es la buena solución! https://material-ui.com/styles/api/#creategenerateclassname -options-class-name-generator

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

FranBran picture FranBran  ·  3Comentarios

revskill10 picture revskill10  ·  3Comentarios

sys13 picture sys13  ·  3Comentarios

reflog picture reflog  ·  3Comentarios

activatedgeek picture activatedgeek  ·  3Comentarios