Sacudida del árbol de JavaScript, como un profesional

Esta es una traducción de un artículo sobre la optimización y reducción del tamaño de un paquete de aplicaciones. Es bueno porque las mejores prácticas se describen aquí, consejos que debe seguir para hacer que el acabado funcione y arroje código no utilizado desde el ensamblado. Será útil para muchos, porque ahora todo el mundo usa sistemas de ensamblaje en los que hay muchas cosas listas para usar. Pero para que funcione correctamente, debe cumplir con los principios que se describen a continuación.

imagen

Trichashing se convierte en la técnica principal cuando necesita reducir el tamaño del paquete y mejorar el rendimiento de la aplicación en JS.

Cómo funciona trichashing:

  1. Usted declara importaciones y exportaciones en cada módulo.
  2. El recopilador (Webpack, Rollup u otro) analiza el árbol de dependencias durante el ensamblaje.
  3. El código no utilizado se excluye del paquete final.

imagen
El archivo de utilidad exporta dos funciones,

imagen
pero solo se utiliza initializeName, formatName se puede eliminar.

Desafortunadamente, para el correcto funcionamiento del trishaking, una configuración del colector no es suficiente. Para lograr un mejor resultado, es necesario tener en cuenta muchos detalles, así como asegurarse de que los módulos no se omitieron durante la optimización.

¿Dónde empezar?


Hay muchas pautas para configurar el trishaking. Es mejor comenzar a sumergirse en el tema con la documentación oficial de Webpack .

Vale la pena mencionar que hace unos años creé una placa repetitiva con un ensamblaje y trichashing ya configurados. Entonces, si necesita un punto de partida para un proyecto, mi repositorio puede ser un buen ejemplo de krakenjs / grumbler .

Este artículo aborda el trabajo con Webpack, Babel y Terser. Sin embargo, la mayoría de los principios presentados funcionarán si usa Webpack, Rollup u otra cosa.

Use la sintaxis ES6 para importaciones y exportaciones


El uso de importaciones y exportaciones de ES6 es el primer y más importante paso para trabajar en trichashing.

La mayoría de las otras implementaciones del patrón "módulo", incluidos commonjs y require.js, no son deterministas durante el proceso de compilación. Esta característica no permite que los recopiladores como Webpack determinen exactamente qué se importa, qué se exporta y, como resultado, qué código se puede eliminar de forma segura.

imagen
Opciones que son posibles al usar commonjs.

Cuando se utilizan módulos ES6, las opciones de importación y exportación son más limitadas:

  • Puede importar y exportar solo a nivel de módulo, y no dentro de la función;
  • el nombre del módulo solo puede ser una cadena estática, no una variable;
  • todo lo que importe debe exportarse a alguna parte.

imagen
Los módulos ES6 tienen una semántica y reglas de uso más simples.

Las reglas simplificadas permiten a los ensambladores comprender exactamente qué se importó y exportó y, como resultado, determinar qué código no se utiliza en absoluto.

No permita que Babel transporte importaciones y exportaciones.


El primer problema que puede encontrar al usar Babel para traducir código es la conversión predeterminada de los módulos ES6 a commonjs. Esto evita que el recopilador optimice el código y arroje demasiado.

Afortunadamente, en la configuración de Babel hay una manera fácil de deshabilitar la transpilación del módulo .

Después de hacer esto, el recolector podrá asumir la transpilación de las importaciones y exportaciones.

Haz tus exportaciones atómicas


Webpack generalmente deja las exportaciones intactas en los siguientes casos:

  • ;
  • ;
  • .

Dichas exportaciones se incluirán completamente en el paquete o se eliminarán por completo. Entonces, al final, puede terminar con un paquete que contiene código que nunca se usará.

imagen
Ambas funciones se incluirán en el paquete, incluso si solo se usa una.

imagen
Y aquí la clase se agregará por completo a la asamblea.

Intente mantener sus exportaciones lo más pequeñas y simples posible.

imagen
Solo la función que se utilizará entrará en el paquete final.

Seguir este consejo le permite al recopilador arrojar más código debido al hecho de que ahora durante el proceso de ensamblaje puede rastrear qué función se importó y se usó y cuál no.

Este consejo también ayuda a escribir código en un estilo más funcional y reutilizable, y a evitar el uso de clases donde esto no está justificado.

Si está interesado en la programación funcional, consulte este artículo .

Evite los efectos secundarios a nivel del módulo.


Al escribir módulos, muchas personas omiten un factor importante pero muy insidioso: la influencia de los efectos secundarios.

imagen
Webpack no entiende lo que hace window.memoize y, por lo tanto, no puede lanzar esta función.

Tenga en cuenta que el ejemplo anterior window.memoizese llamará en el momento de la importación del módulo.

Como lo ve Webpack:

  • ok, aquí se crea y se exporta una función de adición pura; tal vez pueda eliminarla si no se utilizará más adelante;
  • entonces se llama a window.memoize, al cual se pasa add;
  • No sé lo que está haciendo window.memoize, pero sé que probablemente llamará agregar y crear un efecto secundario.
  • por seguridad, dejaré la función de agregar en el paquete, incluso si nadie más la usa .

En realidad, estamos seguros de que window.memoizees una función pura que no crea ningún efecto secundario y agrega llamadas si alguien la usa memoizedAdd.

Pero Webpack no lo sabe y, en aras de la paz, agrega la función de agregar al paquete final.

Para ser honesto: las últimas versiones de Webpack y Terser son inusualmente buenas para detectar efectos secundarios.

imagen
Brindamos a Webpack más información y obtenemos un paquete optimizado.

Ahora el recolector tiene suficiente información para el análisis:

  • llamado aquí memoizea nivel de módulo, esto puede estar lleno de problemas;
  • pero la función memoizevino de ES6 import, necesita mirar la función en util.js;
  • de hecho, memorizar parece una función pura, no hay efectos secundarios;
  • Si nadie usa la función add, podemos excluirla con seguridad del paquete final.

Cuando Webpack no recibe suficiente información para tomar una decisión, tomará el camino seguro y abandonará la función.

Use herramientas para identificar posibles problemas de trishaking


Encontré dos herramientas para identificar problemas.

La primera herramienta es la concatenación de módulos , un complemento para Webpack, que le permite lograr un aumento significativo en el rendimiento. Tiene una opción de depuración. Vale la pena señalar que los factores que impiden la concatenación y el trichashing son los mismos: por ejemplo, los efectos secundarios a nivel del módulo. Tome en serio las advertencias del complemento, ya que cualquier problema aumenta potencialmente el tamaño del paquete.

El segundo es el complemento para la interfaz https://www.npmjs.com/package/eslint-plugin-tree-shaking . Todavía no lo he integrado en mi repetitivo, porque no soportaba el flujo cuando experimenté con él. Sin embargo, él identificó bastante bien los problemas con trichashing.

Ten cuidado con las bibliotecas


Intente utilizar bibliotecas optimizadas para trichashing. Si importa un gran paquete de código minimizado, por ejemplo jquery.min.js, existe la posibilidad de que este módulo no se optimice. Es mejor buscar un módulo desde el cual se puedan importar funciones atómicas, y para el ensamblaje y la minificación, use Webpack o Rollup.

A veces puedes importar una biblioteca completa. Por ejemplo, cuando usa la compilación de producción React, no necesita tirar nada: todo lo que contiene ya está optimizado.

Si usa una biblioteca que exporta funciones individuales, por ejemplo, lodash, intente importar solo las funciones necesarias y asegúrese de que las demás estén excluidas del paquete final.

Usar indicadores de compilación


El complemento DefinePlugin para Webpack tiene una característica maravillosa, pero no la más famosa: la capacidad de influir en el código que se excluirá durante el proceso de compilación.

imagen

Si lo pasamos __PRODUCTION__: trueal complemento, no solo la llamada a la función validateOptions, sino también su definición se excluirá del paquete final .
Esto simplifica la creación de diferentes paquetes para el desarrollo y la producción, y también ayuda a garantizar que el código destinado a la depuración no entre en producción.

Iniciar ensamblaje


A simple vista, es muy difícil determinar cómo Webpack optimizará un módulo en particular.

Ejecute la compilación, verifique el paquete final y vea qué sucede. Eche un vistazo al código JavaScript y asegúrese de que no quede nada en él que debería haber sido descartado por trichashing.

¿Algo más?


Si conoce otros consejos útiles, escriba sobre esto en los comentarios.

All Articles