Material-ui: ¿Se pueden simplificar las mecanografías para mejorar el rendimiento?

Creado en 7 ene. 2020  ·  70Comentarios  ·  Fuente: mui-org/material-ui

Como lo sugirió @ eps1lon en # 18128, estoy creando este problema como un lugar para discutir las mecanografías de Material-UI y si pueden simplificarse para reducir la cantidad de tiempo dedicado a revisarlas, especialmente durante la edición.

Siempre existe una tensión entre tener los tipos más exactos (que proporcionan los mejores errores y finalizaciones del editor) y tener la verificación rápida de tipos (el extremo más alejado del espectro es any ).
Problemas como https://github.com/microsoft/TypeScript/issues/34801 sugieren que Material-UI podría beneficiarse de relajar la exactitud para recuperar algo de rendimiento.

De los repros que he investigado hasta ahora, gran parte de la lentitud parece provenir de la gran cantidad de nombres de propiedades CSS (consulte https://github.com/mui-org/material-ui/blob/master/packages/ material-ui-styles / src / withStyles / withStyles.d.ts). Al no ser un usuario activo de CSS, tengo algunas preguntas ingenuas:

1) ¿Estoy en lo cierto al suponer que tener un nombre y un tipo para cada propiedad CSS conocida es increíblemente valioso y no es algo a lo que podamos renunciar?
2) El tipo CSSProperties parece existir para admitir "pseudo selectores y consultas de medios", que, según mi lectura limitada, parecen denominarse bolsas de propiedades CSS adicionales.
a) ¿Son estas bolsas en sí mismas recursivas o solo hay una capa adicional? Es decir, ¿pasa de width a foo.width oa foo.bar.width , etc.? Si es solo un nivel, simplificar los tipos reduce mi reproducción local de 4.6 segundos a 3.6 segundos (es decir, gran ganancia).
b) Jugué con los tipos y no pude encontrar nada mejor que BaseCSSProperties[keyof BaseCSSProperties] , pero, como supongo que ya sabrás, ese no es un tipo muy útil. Básicamente dice que cualquier propiedad CSS puede tener el tipo de cualquier (otra) propiedad CSS, eso es solo un poco mejor que any .
3) En StyleRules , si no hay propiedades, obtienes CSSProperties o () => CSSProperties (que llamaré descuidadamente "CSSProperties thunked"), lo cual tiene sentido - el CSSProperties podría ser perezoso. Si hay propiedades, obtienes CreateCSSProperties<Props> , lo cual tiene sentido - el Props podría ser necesario para calcular el CSSProperties - o (props: Props) => CreateCSSProperties<Props> , que no hice No lo entiendo porque es efectivamente doblemente vago: tienes que pasar el Props una vez para obtener el CreateCSSProperties y luego nuevamente para obtener propiedades individuales. ¿Por qué es "doble thunked"?

Por separado, sospecho, pero todavía tengo que demostrar que IsEmptyInterface es demasiado caro para el beneficio que proporciona. Sin embargo, es muy posible que no entienda completamente los beneficios, por lo que sería útil escuchar más.

¿Podemos trabajar juntos para encontrar el equilibrio adecuado entre precisión y rendimiento? (Nota: "hacer que el compilador sea más rápido" es obviamente una estrategia viable, pero me gustaría llevar las mecanografías a un buen lugar antes de optimizarlas). ¡Gracias!

performance typescript

Comentario más útil

Comencé a agregar Material UI ( 4.9.4 ) a mi proyecto hoy, y la desaceleración es realmente tan significativa que no creo que pueda usarla en mi proyecto. Acabo de agregar un componente <Slider/> simple, personalizado usando withStyles() .

Estamos hablando de pasar de la retroalimentación instantánea de TypeScript en mi IDE a lo que se siente como de 5 a 10 segundos a veces (para partes de mi código que ni siquiera interactúan con Material UI ahora, es solo una desaceleración completa de TypeScript en el archivo que usa el componente). Algo debe estar significativamente mal con estos tipos (o sí, demasiado complejo), parece que @amcasey está haciendo algunas buenas investigaciones, ¡espero que puedas llegar al fondo de esto!

Tratando de encontrar una manera de que al menos pueda excluir todas las cosas de TypeScript por @material-ui por ahora (básicamente, hacer que todo el módulo sea any ), pero TypeScript no parece hacerlo lo suficientemente fácil.

Todos 70 comentarios

No estoy familiarizado con los tipos de interfaz de usuario de material, pero trato de responder estas preguntas.

  1. Sí, es útil el soporte completo para todas las propiedades css declaradas en los estándares web reales.
  2. a) En nuestro caso nunca usamos una profundidad superior a 2, pero casos como este son bastante posibles
    mecanografiado
    estilos const = (tema: Tema) =>
    createStyles ({
    somediv: {
    '&: botón de desplazamiento': {
    visibilidad: 'visible',
    opacidad: 1,
                ':after': {
                    content: 'x',

                    [theme.breakpoints.up('lg')]: {
                        content: 'close',
                    },
                }
            },
        }
    });
```
b) I do not understand why `BaseCSSProperties[keyof BaseCSSProperties]` is needed there

  1. Creo que (props: Props) => CreateCSSProperties<Props> no es necesario, excluimos este tipo en nuestra versión de tipos de material-ui y no pasó nada malo.

Podría valer la pena ver la implementación de tipos en la versión 3.9.3, porque en esta versión, la verificación de tipos era lo suficientemente rápida y la escritura era buena.

En primer lugar, me gustaría agradecerle por acercarse e investigar esto. Es increíblemente útil que alguien evalúe qué partes de los tipos son lentas o no.

  1. ¿Estoy en lo cierto al suponer que tener un nombre y un tipo para cada propiedad CSS conocida es increíblemente valioso y no es algo a lo que podamos renunciar?

Es imposible ser imparcial aquí. No creo que podamos renunciar a él si miramos el ecosistema más amplio. Las herramientas de desarrollo de Chrome tienen esta característica, reacciona por sí mismo y escribe style prop con CSSProperties etc. transformación de texto.

  1. [...]
    ¿Son estas bolsas en sí mismas recursivas o solo hay una capa adicional?

Necesitaría verificar la solución CSS-in-JS que estamos usando. Técnicamente, las consultas de medios en CSS pueden ser recursivas. Estaría dispuesto a eliminar esta recursividad y ver si recibimos informes. Las consultas de medios técnicamente anidadas se pueden acoplar con el operador and . Sin embargo, deberíamos limitarlo a dos niveles: uno para consultas de medios y otro para pseudo selectores. Esto aún debe ser verificado por tipo IMO:

const styles = {
  root: {
    '<strong i="18">@media</strong> (max-width: 12cm)': {
      ':hover': {}
    }    
  }
}

¿Es esto algo que te ves escribiendo @oliviertassinari?

  1. [...]
    CSSProperties - o (props: Props) => CreateCSSProperties, que no entendí porque es efectivamente doblemente perezoso: tiene que pasar los Props una vez para obtener CreateCSSProperties y luego nuevamente para obtener propiedades individuales. ¿Por qué es "doble thunked"?

Si el argumento en sí no es una bolsa de propiedades sino una función, entonces requiere un tema. Los estilos pueden depender de dos tipos diferentes de bolsas de propiedades: el tema (disponible a través de la API de contexto de React) o los accesorios (pasados ​​directamente al componente):

makeStyles({ root: { color: 'blue' }}); // A
makeStyles(theme => ({ root: { color: theme.color } })); // B
makeStyles({ root: props => ({ color: props.color})}); // C
makeStyles({ root: { color: props => props.color } }); // D: same as C, only exists for dev ergonomics
makeStyles(theme => ({ root: props => ({ color: props.color || theme.color }) })); // E: what you called "double-lazy"

Se trata menos de una evaluación perezosa para mejorar el rendimiento, sino más de tener que esperar a que el contexto y los accesorios estén disponibles.

Por separado, sospecho, pero todavía tengo que demostrar que IsEmptyInterface es demasiado caro para el beneficio que proporciona. Sin embargo, es muy posible que no entienda completamente los beneficios, por lo que sería útil escuchar más.

Hay un caso en el que se utiliza:

Considerar

const useStaticStyles = makeStyles({ root: { color: 'blue' } });
const useDynamicStyles= makeStyles({ root: { color: props =>  props.color } })
function Component() {
  const staticClasses = useStaticStyles(); // No error
  const throwingClasses = useDynamicStyles(); // $ExpectError
  const dynamicClasses = useDynamicStyles({ color: 'blue' });
}

Para inferir la firma de llamada de la función devuelta desde makeStyles (es decir, el gancho llamado algo así como useSomeStyles ). Necesitamos comprobar qué tipo de bolsa de estilo se pasa a makeStyles . Ya tenemos un ayudante para inferir los tipos de accesorios utilizados en la bolsa de estilo . Si la bolsa de estilo es estática, es decir, TS infiere el tipo {} . Luego verificamos el tipo inferido de Props con IsEmptyInterface y para una rama usamos una firma de llamada con 0 parámetros y para la otra rama usamos una firma de llamada con 1 parámetro que es igual al tipo de props inferido ( ver StylesRequireProps y StylesHook .

En resumen: evitamos tener que escribir useStaticStyles({}) o useStaticStyles(null as any) . Se introdujo en https://github.com/mui-org/material-ui/pull/14019 para cerrar https://github.com/mui-org/material-ui/issues/14018. Supongo que podemos hacer un cortocircuito determinando la firma de la llamada. ¿Quizás sobrecargar la firma de la llamada en lugar de usar tipos condicionales?

El problema con esta "función" es que los usuarios avanzados no tienen problemas para usar null as any si entienden por qué. Tal vez incluso pasar un objeto vacío esté bien aunque no sea necesario. Sin embargo, es muy confuso / frustrante cuando no se usa para Material-UI o TypeScript. Especialmente porque la mayor parte del estilo no se basa en accesorios de todos modos.

¿Parece que la mayor parte del tiempo el verificador de tipos está ocupado con la solución de estilo? Hubiera esperado la firma de llamada para nuestros componentes, es decir, qué accesorios son posibles de tomar la mayor parte del tiempo.

Puedo rastrear más repositorios para ver específicamente el uso de withStyles o makeStyles . Hasta ahora solo he analizado el uso de accesorios.

¿Es esto algo que te ves escribiendo @oliviertassinari?

@ eps1lon Tenemos un par de ocurrencias de este anidamiento en el código base (por ejemplo, con <strong i="8">@media</strong> (hover: none) ). Pero no es muy frecuente para los componentes centrales. Imagino que es la misma tierra de usuarios. Definitivamente podría ser parte de la compensación.

@beholderrk

  1. Me lo imaginé, pero pensé que también podría preguntar.
  2. a) La profundidad dos debe poder expresarse; solo habrá un poco más de duplicación que la profundidad uno.
    b) Me tomó bastante tiempo entender esto y desearía poder explicarlo en persona, en lugar de en un texto. Básicamente, la firma del índice dice que todas las propiedades tienen el mismo tipo. Eso solo puede funcionar si especifica un tipo que funcione para todos ellos. Una forma de hacerlo es construir la unión de todos los tipos de propiedad, BaseCSSProperties[keyof BaseCSSProperties] ; entonces será cierto que cada propiedad tiene un tipo compatible. Por ejemplo, suponga que las únicas propiedades que podría tener en CSS fueran name: string y width: number . Una forma de especificar una firma de índice que funcione con ambas propiedades sería decir que cada propiedad es un string | number . No es genial - name nunca será un number y width nunca será un string - pero funciona. El problema real es que lo que desea no se puede expresar en realidad (al menos, hasta donde hemos podido determinar, podría haber un truco "inteligente" que lo haga). De hecho, quiere decir que su tipo contiene name: string , width: number o x: CSSProperties , donde x es cualquier cosa menos name o width - es el "todo menos" lo que falta. Espero que esté un poco más claro.
  3. Parecía que @ eps1lon tenía algo que decir sobre esto, pero todavía estoy analizando su respuesta.

Sería muy útil contar con una línea de base buena conocida. ¿Tiene un enlace?
Editar: lo encontré.

@ eps1lon Feliz de ser parte de la conversación. Los tipos rápidos y correctos son buenos para todos. 😄

  1. No hay discusión aquí, pensé que preguntaría temprano porque habría provocado un cortocircuito en toda la conversación.
  2. Dos capas parecen factibles (con la notable salvedad de que los tipos seguirán siendo en gran parte inútiles). Veré si puedo redactar algo.
  3. Con mi falta de contexto, no estaba claro que los temas y los accesorios fueran diferentes. Si es así, entonces la estructura tiene sentido. Gracias por aclararlo.

Con respecto a isEmptyInterface , ¿podría hacer que el parámetro de propiedades (por ejemplo) useStaticStyles opcional? Sería menos correcto, en el sentido de que las personas que llaman podrían omitirlos cuando se espera, pero sería mucho más barato escribir check. Como dije, no tengo números ni nada para ti, es solo una especulación de mi parte.

¿Cuáles son sus pensamientos sobre 2 (b)? Parece que ese tipo no proporciona mucho valor, ya que básicamente dice que se aceptará cualquier nombre de propiedad y que el tipo de retorno puede ser una de muchas cosas.

Con respecto a isEmptyInterface, ¿podría hacer que el parámetro de propiedades (por ejemplo) useStaticStyles sea opcional?

Primero me gustaría experimentar con la sobrecarga de la firma de la llamada y ver si esto tiene algún impacto. Luego intentaremos hacerlo menos sonoro haciéndolo siempre opcional. Parece más seguro de lo habitual hacer que suene menos, ya que casi todos los casos de uso solo lo llaman una vez, por lo que es probable que solo cometa el error una vez y salga a la luz con bastante rapidez. Sin embargo, va a ser difícil venderlo si no nos da mucho rendimiento. Usaré el repositorio creado para el problema original (https://github.com/microsoft/TypeScript/issues/34801#issue-514055289).

¿Cuáles son sus pensamientos sobre 2 (b)? Parece que ese tipo no proporciona mucho valor, ya que básicamente dice que se aceptará cualquier nombre de propiedad y que el tipo de retorno puede ser una de muchas cosas.

Omití eso accidentalmente. Lo veré después del experimento IsEmptyInterface.

@ eps1lon Totalmente de acuerdo: isEmptyInterface si eliminarlo no es una ganancia de rendimiento sustancial.

Con # 19320 nos deshicimos de algunos tipos condicionales complejos donde la sobrecarga de funciones lograba lo mismo (eliminando IsEmptyInterface y cualquier tipo de lógica booleana). Aunque parece que no nos ganó mucho además de tener menos código.

Quiero agregar que actualmente estoy cambiando entre TS 3.2.4 y 3.7.4. Nuestro conjunto de pruebas de tipo se ejecuta un 50% más lento en 3.7.4 en comparación con 3.2.4 (~ 90 vs 50).

Continuaré investigando si podemos limitar la profundidad de CSSProperties y eliminar por completo el soporte para consultas de medios y pseudo selectores. Sin embargo, tener los que no están escritos no es realmente una opción. El verificador de tipos debería poder comprobarlos en un tiempo razonable.

Puede ser que el verificador de tipos sea el cuello de botella real. Tal vez podamos investigar en qué versión se acertó el rendimiento.

Si me envía los comandos que está ejecutando en 3.2.4 y 3.7.4, puedo crear un perfil localmente. Sin embargo, la experiencia sugiere que la causa probablemente resultará ser una verificación adicional deseable agregada desde 3.2.4. (Y supongo que "0" es un error tipográfico, ¿probablemente "40" o "50"?)

Con respecto a CSSProperties, estoy de acuerdo en que mantener los nombres y tipos de propiedad es extremadamente valioso. Sin embargo, creo que hay más que verificarlos en un período de tiempo razonable: el primer problema es que el sistema de tipos no puede expresar la forma que desea. Creo que probablemente vamos a pasar algún tiempo trabajando en una solución general al problema. ¿Puedo asumir que le interesaría participar en esa discusión?

Tenemos scripts para comparar múltiples versiones del compilador, por lo que, si puede identificar una prueba bastante estable que le gustaría que ejecutamos, podemos calcular la desaceleración a lo largo del tiempo.

(Y supongo que "0" es un error tipográfico, ¿probablemente "40" o "50"?)

Lo siento, son 50.

Si me envía los comandos que está ejecutando en 3.2.4 y 3.7.4, puedo crear un perfil localmente.

Es solo yarn typescript en la raíz que ejecuta el mismo comando en cada espacio de trabajo que lo implementa. Por ejemplo, yarn workspace @material-ui/styles run typescript prueba nuestros tipos con tslint y dtslint $ExpectError . En 3.7.4 encontramos algunas fallas y tuvimos que ajustar nuestras pruebas (ver # 19242)

el primer problema es que el sistema de tipos no puede expresar la forma deseada.

Lo sospechaba mucho. Parece que la forma en que mezclamos una forma "concreta" con un objeto con una firma de índice es simplemente una solución.

¿Puedo asumir que le interesaría participar en esa discusión?

Definitivamente. Pasaré un poco más de tiempo con CSSProperties no recursivas y luego escribiré un poco más de pruebas para ilustrar lo que estamos buscando en esos tipos. Sospecho que otras soluciones de estilo css-in-js tienen cuellos de botella de rendimiento similares.

Probaré esos comandos mañana (supongo que debería mencionar que estoy en hora del Pacífico y observo los días festivos de EE. UU.).

Parece que la forma en que mezclamos una forma "concreta" con un objeto con una firma de índice es simplemente una solución.

Gracias, he estado luchando con la mejor manera de expresar eso. Sí, tiene razón en que la firma de índice no está haciendo lo que desea. Tenemos algunas ideas sobre una variante que podría, pero necesitamos explorar las implicaciones de rendimiento.

Sospecho que otras soluciones de estilo css-in-js tienen cuellos de botella de rendimiento similares.

Mucho. Esperamos que todo lo que hagamos por usted pueda generalizarse para mejorar todo el ecosistema.

Siento que me estoy perdiendo algo obvio, pero actualmente estoy atascado. Primero, renuncié a Windows, las cosas parecen funcionar mejor en Linux. Avísame si quieres profundizar en eso. En segundo lugar, puedo hacer que yarn typescript ejecute, limpiamente, por lo que puedo decir, pero parece estar ejecutando tslint, en lugar de tsc puro. Cuando ejecuto tsc en el mismo tsconfig.json (estoy probando específicamente con estilos), obtengo ~ 40 errores. ¿Qué estoy haciendo mal? Para fines de creación de perfiles, sería muy útil reducir la reproducción a una única invocación de tsc.

@amcasey yarn typescript no se trata de compilación, sino de probar nuestros tipos. Estamos usando una configuración similar a la utilizada en el repositorio DefinitelyTyped. Los archivos TypeScript en packages/* casi siempre son solo un montón de declaraciones que deberían pasar o fallar, las cuales capturamos con $ExpectError .

Creo que el mejor caso de prueba del "mundo real" es usar tsc en nuestros documentos a través de yarn workspace docs run tsc -p tsconfig.json después de agregar skipLibCheck: true y noEmit: true a ./docs/tsconfig.json :

--- a/docs/tsconfig.json
+++ b/docs/tsconfig.json
@@ -3,6 +3,8 @@
   "include": ["types", "src/pages/**/*"],
   "compilerOptions": {
     "allowJs": false,
-    "noUnusedLocals": true
+    "noUnusedLocals": true,
+    "noEmit": true,
+    "skipLibCheck": true
   }
 }

@ eps1lon Gracias por aclarar. No me entusiasma que tslint se haya ralentizado, pero me gustaría centrarme en una variable a la vez. Ejecutaré la compilación de documentos que sugirió con varias versiones de mecanografiado y veré si surge algo. ¡Gracias!

Esta configuración es perfecta. Veo que el tiempo de verificación se duplica entre 3.3 y 3.4.

| Versión | Compruebe el tiempo |
| - | - |
| 3,2 | 16,71s |
| 3,3 | 16,79s |
| 3,4 | 35.25s |
| 3,5 | 21,40 s |
| 3,6 | 23,10s |
| 3,7 | 27,39s |

Investigaré un poco más, pero me dijeron que la implementación 3.3 de los tipos condicionales estaba incompleta, la implementación 3.4 fue lenta y la implementación 3.5 es buena. Entonces, desafortunadamente, esto probablemente sea lo esperado.

Específicamente, sospecho que este cambio introdujo la desaceleración como se describe en este error .

Me parece preocupante que entre 3.5 y 3.7 hubo un aumento de 6 segundos en el tiempo que lleva ejecutar la verificación. Eso parece bastante sustancial.

@embeddedt Esos números son de ejecuciones individuales con cada versión, por lo que probablemente haya bastante ruido. Sin embargo, investigaré y veré si puedo encontrar algo.

Lo rehice en una VM Linux y 3.7 fue consistentemente un 20-25% más lento que 3.5.

Esto ha demostrado ser bastante difícil de dividir en dos porque las ejecuciones consecutivas de la misma compilación varían en ~ 5% y la diferencia entre 3.5 y 3.6 o entre 3.6 y 3.7 es solo ~ 10%.

Una cosa sospechosa que he notado es que styled-components proporciona archivos .d.ts separados para TS> = 3.7, por lo que es posible que la comparación no sea igual.

Para mi sorpresa, los nuevos tipos styled-components parecen ser más rápidos. Sin embargo, comparar manzanas con manzanas facilitará la investigación.

No pude pensar en una solución inteligente, así que voy a trazar el tiempo de compilación fusionar por fusionar y buscar picos. Espero tener números mañana.

@amcasey ¡ Gracias por tus esfuerzos para investigar esto! Realmente genial ver a los miembros del equipo de TS y Material UI trabajando juntos. Me encontré con este problema de Github tratando de averiguar por qué nuestra experiencia de editor con Material UI es tan lenta (la estamos usando en dos proyectos en el trabajo). Definitivamente puedo confirmar que estamos viendo un impacto bastante significativo en intellisense y usabilidad dentro de VsCode.

En este punto, estaremos encantados de intercambiar un poco de seguridad de tipos en nuestro JSS por comentarios rápidos para el resto de la biblioteca. A veces se necesitan de 8 a 10 segundos de espera antes de que el servidor de Typecript se ponga al día con los cambios de código

Incluso con promedios de tres corridas, los datos son muy ruidosos. Sin embargo, parece haber una caída notable en el tiempo de ejecución en https://github.com/microsoft/TypeScript/commit/ad322a561a301ae357da051b9221b2222c13be36 un aumento notable (volviendo aproximadamente al nivel anterior) en https://github.com/microsoft/TypeScript / commit / 480b73915fdd805952fd355e4cf3e1bc803e0878 y una tendencia general al alza después de eso (aunque me parece demasiado uniforme y sospecho que hay factores ambientales) que incluye un pico particular en https://github.com/microsoft/TypeScript/commit/c5e6d95e930048a033a968d7244404. Me voy a centrar en los dos primeros hasta que realice algunas pruebas más para confirmar la tendencia general ascendente (¿cómo podría empeorar uniformemente con cada confirmación?).

La tendencia alcista está resistiendo el escrutinio y no tengo idea de qué podría causar eso. Tal vez las desaceleraciones discretas estén tan juntas que el ruido las haga parecer una sola curva.

Aumenté hasta 10 ejecuciones por confirmación y ahora hay cuatro regresiones distintas en el área inclinada. :sonrisa:

https://github.com/microsoft/TypeScript/commit/26caa3793e310e271ddee8adc1804486e5b0749f (~ 700ms)
https://github.com/microsoft/TypeScript/commit/250d5a8229e17342f36fe52545bb68140db96a2e (~ 500ms)
https://github.com/microsoft/TypeScript/commit/7ce793c5b8c621af5ce50af0ca3958c7bd6541bf (~ 1300ms)
https://github.com/microsoft/TypeScript/commit/28050d5c47c6cd7627555f12cf13b1062f80322a (~ 400ms)

(El tiempo total antes de que comenzaran las regresiones fue ~ 33 s).

Solo para moderar un poco las expectativas: es muy probable que varias de estas regresiones resulten ser valiosos controles adicionales e, incluso si logramos obtener todos esos controles de forma gratuita, solo obtendríamos un 20% de descuento "demasiado tiempo ".

Editar: He actualizado los enlaces. Debido a que estaba retrocediendo en el tiempo, me confundí y marqué la fusión _antes_ de cada regresión.

@ eps1lon Alguien sugirió que eliminar @ts-ignore podría ayudar. Básicamente, cuando se detecta un error, se asume que la principal prioridad del usuario es obtener buena información sobre el error, por lo que es posible que se haga un montón de trabajo adicional. Si esa información se elimina posteriormente (debido a @ts-ignore ), entonces ese tiempo es una pérdida. (Desafortunadamente, no es sencillo detectar que no es necesario detectar un error). Una estrategia alternativa es agregar aserciones de tipo explícitas (incluso a any ) hasta que el compilador deje de quejarse.

@ eps1lon Alguien sugirió que eliminar @ts-ignore podría ayudar.

Solo tuvimos un uso en docs/ . Lo quité de todos modos por si acaso: # 19504

Para ser honesto, parece que @ts-ignore es un anti-patrón en ese caso. No solo no le brinda información útil, es decir, qué tipo de error tenemos, sino que también es un cuello de botella de rendimiento.

Por lo que puedo decir, @ts-ignore solo es útil en archivos .js que están siendo revisados.

Mmmm, eso casi con certeza no explica por qué las relaciones públicas mejorando los mensajes de error redujeron el rendimiento. Sin embargo, definitivamente parece una mejora. 😄

Soy bastante nuevo en el mundo de TypeScript, particularmente cuando se trata de soluciones de estilo en JS, pero he estado siguiendo este hilo en silencio durante el último mes y tenía curiosidad por escuchar los pensamientos de las personas sobre una posible solución alternativa, en menos en el corto plazo.

Supongo que algunos usuarios (yo mismo soy uno) no hacen un uso intensivo del sistema de estilo incorporado, o lo evitan por completo. Lo hago principalmente porque estoy mucho más familiarizado con CSS simple o Sass y realmente no he tenido tiempo para investigar cómo usar de manera efectiva el sistema de estilo JS. Prefiero simplemente inventar mis propios nombres de clase, escribir un archivo de hoja de estilo separado, usar los nombres de clase dentro de mis componentes React y continuar. Esencialmente, estilizo como si estuviera escribiendo HTML simple.

Dicho esto, ¿es posible / práctico agregar una bandera que desactive la verificación de tipos para las partes costosas del sistema de estilo (posiblemente haciendo condicionalmente cosas como type CSSProperties = any )? No conozco las estadísticas de la cantidad de personas que usan el sistema de estilo frente a las que no lo usan, pero me imagino que realmente no puede hacer mucho daño (siempre que se agregue una verificación para probar los mecanografiados con ese conjunto de banderas) y sería una forma rápida de mejorar el rendimiento de al menos un segmento de usuarios.

Solo quería mencionar la idea general; siéntete libre de derribarlo. : leve_sonriente_cara:

@embeddedt En términos generales, marcar algo explícitamente como any es una buena forma de deshabilitar la verificación de tipo para ese símbolo. Habiendo dicho eso, no puedo recordar si puede simplemente aplastar una declaración anterior o más bien, como sugiere, necesitaría soporte del compilador para evitar problemas de declaración duplicada.

Nuevos números (máquina diferente, métrica de tiempo diferente):

| Versión | Tiempo total |
| - | - |
| 3.5.3 | 32,5s |
| 3.7.5 | 35,9s |
| maestro | 29,9s |

Algunos de los problemas que publiqué anteriormente aún están abiertos, pero básicamente volvemos a 3.5 perf (para este punto de referencia). Obviamente, sigue siendo mucho más lento de lo que nos gustaría, pero es probable que el próximo lote de cambios esté en el lado de la interfaz de usuario del material.

Probamos 3.8.1 en nuestro conjunto de pruebas y parece que son tan rápidos como los anteriores con 3.2.4 (3.7 fue significativamente más lento).

Francamente, no puedo creer la cantidad de rendimiento que pudimos recuperar sin renunciar a la nueva funcionalidad. : smile: Creo que podría haber un poco más de holgura (por ejemplo, https://github.com/microsoft/TypeScript/pull/36754), pero aún sospecho que el cambio más impactante sería una simplificación de los tipos CSSProperties. ¿Has tenido la oportunidad de jugar con ellos? Parece que al menos un subconjunto de usuarios (por ejemplo, @embeddedt) estaría feliz de renunciar a alguna verificación de tipo a cambio de una ganancia de rendimiento.

Parece que al menos un subconjunto de usuarios (por ejemplo, @embeddedt) estaría feliz de renunciar a alguna verificación de tipo a cambio de una ganancia de rendimiento

¿Acaso alguien del equipo de TS no tuiteó recientemente que por cada usuario que quiere tipos más estrictos, hay uno que quiere unos más flexibles? :sonrisa:

Para mí, no se trata realmente de la verificación de tipos (las herramientas de desarrollo del navegador tienen capacidades mucho mejores para verificar su CSS). Se trata más de tener disponible la función de autocompletar.

Jugaré con diferentes "versiones" y veré cómo funcionan.

@amcasey No creo que la naturaleza recursiva de CSSProperties (llamado CSSObject en styled-components) sea el problema principal. De lo contrario, su desempeño sería tan malo como el nuestro. Consulte https://github.com/eps1lon/mui-types-perf/pull/6 y los registros de referencia .

Podría ser más un problema con la cantidad de "sobrecarga" que hacemos. styled-components solo permite un objeto estático, mientras que permitimos una versión procesada, así como cada propiedad es un procesador. Aunque no estoy seguro.

Me encantaría simplificar la firma de tipo (ya que en mi opinión también es más fácil de entender para los desarrolladores) pero se me pidió explícitamente que coincidiera con la implementación de JSS. Ahora que lo apoyamos, no podemos retroceder fácilmente. Especialmente si la ganancia está en la región del 20%. No creo que eso justifique la rotura.

¿Se pueden hacer los tipos condicionalmente menos precisos (según la configuración del usuario)? Eso no debería romper ningún código existente (porque la configuración puede estar desactivada de forma predeterminada) y permitiría a los usuarios como yo que no necesitan los tipos complejos ver rápidamente un aumento de rendimiento.

permitiría a los usuarios como yo, que no necesitan los tipos complejos, ver rápidamente un aumento de rendimiento.

Ni siquiera está confirmado que obtendría una diferencia notable. He visto ganancias de rendimiento del 15%, pero es cuestionable si esto es reconocible.

La "configuración de usuario" que pude ver es parchear el paquete en la instalación. No tenemos el ancho de banda para mantener múltiples versiones de los mecanografiados.

@ eps1lon Lo siento, creo que mi pregunta puede no haber sido clara. Creo que CSSProperties está bien (aunque, obviamente, si sería más rápido si fuera más pequeño); de hecho, esperaba que hubiera espacio para simplificar los subtipos en https://github.com/mui-org /material-ui/blob/master/packages/material-ui-styles/src/withStyles/withStyles.d.ts. Por ejemplo, ¿obtendría menos finalizaciones si cambiara este tipo a any ?

Editar: en mi caja, esto hace que la compilación del proyecto docs 15% más rápido (29,7 segundos hasta 25,5 segundos), pero no conozco el efecto en la experiencia de edición.
Edición 2: en realidad, una vez que haya renunciado a doblar en la parte recursiva del tipo, puede usar BaseCreateCSSProperties y cualquier otra propiedad tendrá el tipo any (es decir, puede mantener los tipos reales de propiedades CSS).
Edición 3: la Edición 2 no funciona debido a un exceso de verificación de propiedades (es decir, los nombres de propiedad arbitrarios no están permitidos en los objetos literales).

Su punto sobre las terminaciones frente a la verificación de tipos fue muy interesante porque tenía la hipótesis de que algunos autores de tipos podrían sentirse de esa manera. @DanielRosenwasser Creo que buscamos hacer algo como esto para acomodar el patrón "a" | "b" | string - ¿se fue a alguna parte?

También tenga en cuenta que styled-components está teniendo (creemos) problemas de rendimiento del verificador estrechamente relacionados.

En cuanto a poder especificar el tipo con más precisión, he presentado https://github.com/microsoft/TypeScript/issues/36782.

Parece que emotion podría estar en el mismo barco.

Comencé a agregar Material UI ( 4.9.4 ) a mi proyecto hoy, y la desaceleración es realmente tan significativa que no creo que pueda usarla en mi proyecto. Acabo de agregar un componente <Slider/> simple, personalizado usando withStyles() .

Estamos hablando de pasar de la retroalimentación instantánea de TypeScript en mi IDE a lo que se siente como de 5 a 10 segundos a veces (para partes de mi código que ni siquiera interactúan con Material UI ahora, es solo una desaceleración completa de TypeScript en el archivo que usa el componente). Algo debe estar significativamente mal con estos tipos (o sí, demasiado complejo), parece que @amcasey está haciendo algunas buenas investigaciones, ¡espero que puedas llegar al fondo de esto!

Tratando de encontrar una manera de que al menos pueda excluir todas las cosas de TypeScript por @material-ui por ahora (básicamente, hacer que todo el módulo sea any ), pero TypeScript no parece hacerlo lo suficientemente fácil.

@lostpebble ¿ withStyles para personalizar el control deslizante, digamos módulos CSS?

@lostpebble Actualmente no tenemos una forma compatible de excluir un conjunto particular de tipos. Si realmente lo desea, lo que experimentaría serían las asignaciones de ruta. Puede probar un mapeo de ruta como "@material-ui/*": ["simplemui"] y luego crear un simplemui.d.ts contenga

declare const x: any;
export = x;

Eso haría que todos los tipos de interfaz de usuario de material sean any . Definitivamente es un truco y no es algo que pueda recomendar, pero podría desbloquear su experiencia de edición.

Creo que hemos hecho algunas mejoras buenas (en algún lugar en el área del 30%), pero parece que todo lo que podemos hacer ahora es aflojar la mecanografía.

Esto requiere absolutamente propuestas concretas, por ejemplo, con qué código incorrecto estaría de acuerdo para ser aceptado por el verificador de tipos. Entonces necesitaríamos comparar y ver si esto hace una mella significativa.

Debe comprender que las regresiones introducidas a propósito agregan mucho trabajo para los mantenedores, ya que tenemos que explicar esto a los consumidores de bibliotecas y es bastante estresante en general.

Así que esto no es una prioridad para mí en este momento a menos que alguien tenga inteligencia procesable. De lo contrario, tengo que dedicar demasiado tiempo a muy poco rendimiento.

En mi caso, para makeStyles(theme => createStyles(...)) , devolviendo Record<ClassKey, any> de createStyles(...) casi ~ mitades ~ (en mi código y computadora, aproximadamente ~ 1200ms -> 750ms ~ 1400ms → 1100ms) encodedSemanticClassifications-full: elapsed time muestra en el registro de tsserver (no parece un trabajo caro, pero tal vez esté esperando a que se complete la verificación de tipo).

export default function createStyles<ClassKey extends string, Props extends {}>(
  styles: StyleRules<Props, ClassKey>,
): Record<ClassKey, any>;

createStyles(...) verifica la estructura de estilo para que podamos omitir la verificación de tipo para argumento-tipo-de-unión-masiva de makeStyles frente a retorno-tipo-de-unión-masiva de createStyles.

~ (Y comentando todo el código makeStyles: 650ms) ~

@ypresto createStyles solo es necesario para versiones mecanografiadas sin const aserciones. Si puede usar { display: 'block' as const } en su base de código (ts> = 3.4), utilícelo sobre createStyles .

@ eps1lon Nos docs pero los resultados no fueron impresionantes.

@ eps1lon con const y sin createStyles , IntelliSense ya no muestra candidatos sensibles al contexto: llorar:

@ypresto Debería. ¿Tiene un fragmento de código de ejemplo?

@amcasey

Agregar as const al objeto externo o la propiedad lo mata efectivamente. No quiero colocarlo en todas las propiedades.

const useStyles = makeStyles(theme => ({
  root: {
    // no IntelliSense
  }
} as const))

Además, sin createStyles tiene una pequeña limitación para completar la cadena.

const useStyles = makeStyles(theme => ({
  root: {
    direction: '|', // no IntelliSense at | (works with createStyles)
    direction: | // IntelliSense works at |
  }
}))

@ypresto Por "lo mata", ¿quieres decir "hace que funcione de la misma manera que createStyles hizo"?

Es complicado ponerlo en todas partes, pero no es más complicado que poner createStyles todas partes.

@amacleay Quise decir kills IntelliSense : orar :

Lo siento, me perdí tus comentarios. Le daré una oportunidad.

No tengo idea de por qué, pero esto es 1100ms → 750ms, curiosamente:

 export const DropArea: React.FC<CardProps & {
   active?: boolean
   description: string
   icon?: React.ReactNode
-}> = ({ active, description, icon, children, ...props }) => {
+}> = ({ children, ...props }) => {
   const classes = useStyles()
+  const active = false
+  const icon: React.ReactNode = null
+  const description = ''
   return (
     <Card {...props} className={clsx(classes.root)} variant="outlined">

Eliminar CardProps & de FC es casi el mismo resultado. Quizás sea porque CardProps amplía PaperProps, que amplía los grandes atributos HTMLA.

ACTUALIZACIÓN E HTMLAttributes<HTMLDivElement> también reduce el tiempo (no medido).

Finalmente, encontré el más grande, 750ms → 130ms:

Eliminando style={...} de dos tipografías.

-<Typography variant="subtitle2" component="div" noWrap style={{ width: '26ch' }}>...</Typography>
+<Typography variant="subtitle2" component="div" noWrap>...</Typography>
-<Typography variant="caption" component="div" noWrap style={{ width: '20ch' }}>...</Typography>
+<Typography variant="caption" component="div" noWrap>...</Typography>

¿Pero por qué? Agregar el mismo estilo a <div> no afecta el rendimiento. ¿Quizás OverridableComponent es demasiado complicado ...?

(Estoy usando TypeScript 3.8.3, @material-ui/core 4.9.1)

AFAIK, la forma en que Material-UI maneja los estilos locales en los componentes es diferente a la forma en que React lo maneja para los elementos HTML.

@embeddedt En el nivel de tipo, se resuelve en React.CSSProperties que es lo mismo que el estilo de div.

@ypresto me quedo corregido. Lo siento.

Hola chicos, no estoy seguro de si vale la pena abrir un nuevo número para esto, así que lo publicaré aquí ya que está relacionado con los tipos de corrección / rendimiento. Avísame si debería abrir un problema en su lugar.
Al seguir la documentación para agregar una fuente personalizada , termino con el siguiente error de escritura:
Type 'string' is not assignable to type 'FontFaceFontDisplayProperty'

Es extraño, porque la mecanografía de csstype 2.6.9 parece válida y otros atributos están bien (usando MUI 4.9.5).

const sourceSansPro = {
  fontFamily: "'Source Sans Pro'",
  fontStyle: "normal",
  fontDisplay: "swap", // won't work
  fontWeight: 400,
  src: `
    url('/static/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf') format("truetype")
  `
};

Propiedad del tema:

  overrides: {
    MuiCssBaseline: {
      "@global": {
        "@font-face": [sourceSansPro]
      }
    }

El tipo es type FontFaceFontDisplayProperty = "auto" | "block" | "fallback" | "optional" | "swap";

@ eric-burel Este es un problema con el ensanchamiento automático de tipos de mecanografiado. Tratar

- fontDisplay: "swap", // won't work
+ fontDisplay: "swap" as "swap",

Gracias, funciona, y he aprendido un nuevo concepto de "ampliación de tipo" :) Es extraño que fontStyle no se vea afectado, por ejemplo, no es la única propiedad CSS definida como una enumeración, pero la primera vez que lo hago .

Editar: ok mi mal, está bien documentado: https://material-ui.com/guides/typescript/#using -createstyles-to-failure-type-widening

Finalmente, encontré el más grande, 750ms → 130ms:

Eliminando style={...} de dos tipografías.

-<Typography variant="subtitle2" component="div" noWrap style={{ width: '26ch' }}>...</Typography>
+<Typography variant="subtitle2" component="div" noWrap>...</Typography>
-<Typography variant="caption" component="div" noWrap style={{ width: '20ch' }}>...</Typography>
+<Typography variant="caption" component="div" noWrap>...</Typography>

¿Pero por qué? Agregar el mismo estilo a <div> no afecta el rendimiento. ¿Quizás OverridableComponent es demasiado complicado ...?

(Estoy usando TypeScript 3.8.3, @material-ui/core 4.9.1)

¿Has descubierto que esto afecta el tiempo de compilación o solo el tiempo que tarda intellisense en ser útil? Recibo el problema de compilación (sin memoria) y parte de nuestro código TS tiene una tonelada de style={someStyle} configurada en los componentes. Preguntándome si eso es parte de nuestro problema.

@ yatrix7 , en términos generales, esperaría que estos largos tiempos de verificación afecten los tiempos de respuesta tanto de la compilación como del editor.

¿Alguien está investigando esto actualmente? Sé que ha habido algunas mejoras con respecto al tiempo de verificación del tipo de mecanografiado en las actualizaciones de versiones anteriores. Sin embargo, todavía es lento.
No me importaría investigar esto yo mismo.

No me importaría investigar esto yo mismo.

Eso sería genial. Actualmente no tenemos conocimiento de elementos procesables en los que podamos trabajar. Por lo tanto, se agradecería cualquier indicación sobre los cuellos de botella.

Se agregaron algunas evaluaciones comparativas por ahora, para ayudar a investigar: https://github.com/mui-org/material-ui/pull/22110

@FabianKielmann En el extremo de TS, he estado trabajando en herramientas de investigación de rendimiento que espero que pronto sean lo suficientemente maduras para aplicar a material-ui.

Si tiene algo de tiempo para dedicarlo a esto, también puede probar algo como https://github.com/microsoft/TypeScript/issues/38583.

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

Temas relacionados

TimoRuetten picture TimoRuetten  ·  3Comentarios

rbozan picture rbozan  ·  3Comentarios

finaiized picture finaiized  ·  3Comentarios

ghost picture ghost  ·  3Comentarios

FranBran picture FranBran  ·  3Comentarios