software1

Parte II – Una lista aparte


Ella y el resto del equipo de desarrollo adoptaron con entusiasmo un rediseño completo del sitio web antiguo de la compañía. Sus pedidos fueron escuchados por la gerencia, incluso hasta el C-Suite, que dio luz verde. El equipo y el equipo comenzaron a trabajar con entusiasmo con los equipos de Diseño, Copia e IA. No pasó mucho tiempo antes de que trajeras un nuevo código.

Artículo siguiente

Comenzó lo suficientemente inofensivo con una instalación npm aquí y una instalación npm allí. Antes de que lo supiera, instaló dependencias de producción como un barril de pregrado que permaneció sin preocupaciones por la mañana.

Entonces empezaste.

En contraste con las consecuencias de la bebida más extensa, la agonía no comenzó la mañana siguiente. Oh no. Llegó meses después en la terrible forma de náuseas leves y dolores de cabeza de los propietarios de productos y mandos intermedios. Cuando el CTO regresó de un fin de semana en la cabina y se preguntó por qué el sitio en su teléfono se estaba cargando tan lentamente, si alguna vez estaba cargado.

Todos estaban felices. Ahora nadie está contento . Bienvenido a tu primera resaca de JavaScript.

No es tu culpa. # section2

Si lidias con una resaca diabólica, "Te lo dije", sería una merecida si provocas la pelea. reprimenda: siempre que incluso puedas luchar en un estado tan triste.

Cuando se trata de la resaca de JavaScript, hay mucha culpa que puede eliminarse. Sin embargo, es una pérdida de tiempo señalar con los dedos. El panorama web actual requiere que iteremos más rápido que nuestros competidores. Este tipo de presión significa que es probable que usemos todos los medios disponibles para ser lo más productivos posible. Esto significa que es más probable, pero no necesariamente condenado, crear aplicaciones con más esfuerzo y posiblemente usar patrones que puedan afectar el rendimiento y la accesibilidad.

El desarrollo web no es fácil. Es un pasatiempo largo que rara vez nos acercamos al primer intento. Sin embargo, lo mejor de trabajar en la Web es que no tenemos para hacerlo perfecto al principio. Podemos hacer mejoras más tarde, y para eso es exactamente el segundo episodio de de esta serie . La perfección está muy lejos. Por el momento, analicemos esta resaca de JavaScript mejorando la escritura de su sitio a corto plazo.

Reúna a los sospechosos habituales # section3

Tal vez rojo, pero vale la pena revisar la lista de optimizaciones básicas. No es raro que grandes equipos de desarrollo, especialmente aquellos que trabajan en muchos repositorios o no usan repeticiones optimizadas, los ignoren.

Agite estos árboles # section4

Primero, asegúrese de que su cadena de herramientas esté configurada para Agite el árbol . Si la sacudida del árbol es nueva para usted, el año pasado escribí una guía que puede consultar. En resumen, sacudir árboles es un proceso en el que las exportaciones no utilizadas en su base de código no se empaquetan en sus paquetes de producción.

Sacudir árboles es común en los paquetes modernos como webpack rollup o package . Grunts o Swallow – estos no son Bundler sino Task Runner – no hagas esto por ti. Un corredor de tareas no crea un diagrama de dependencia como un coordinador. En su lugar, realiza tareas discretas en los archivos que les proporciona cualquier cantidad de complementos. Task Runner puede ampliarse con complementos para usar Bundler para procesar JavaScript. Si le resulta difícil extender Task Runners de esta manera, es posible que deba verificar y eliminar manualmente el código no utilizado.

Para que la sacudida de árboles sea efectiva, debe cumplirse lo siguiente:

  1. La lógica y los paquetes de su aplicación Debe haber creado módulos ES6 en su proyecto. Sacudida de árboles Los módulos CommonJS son ​​prácticamente imposibles.
  2. Su paquete no puede convertir módulos ES6 a otro formato de módulo en el momento de la creación. Al hacer esto en una cadena de herramientas que utiliza Babel, debe especificar los módulos @ babel / settings- env ​​configuration : false para evitar que el código ES6 se convierta en CommonJS.

Desactivado No se produce ninguna sacudida del árbol aleatorio durante la construcción. Puede ser útil ponerlo en funcionamiento. Por supuesto, su efectividad varía de un caso a otro. También depende de si los módulos que importa producen efectos secundarios que pueden afectar la capacidad de un coordinador para sacudir las exportaciones no utilizadas.

Comparta este código en # section5

Lo más probable es que usted & # 39; Use alguna forma de desglose del código pero vale la pena reconsiderar cómo lo hace. No importa cómo divide el código, hay dos preguntas que siempre debe hacerse:

  1. ¿Está deduplicando el código común entre puntos de entrada ?
  2. ¿Eres lento para cargar todas las funciones que puedes hacer razonablemente con dinámico import () ?

Estos son importantes porque reducir el código redundante es esencial para el rendimiento. La función de carga diferida también mejora el rendimiento al reducir la huella inicial de JavaScript en una página en particular. En el lado de la redundancia, puede usar una herramienta de análisis como Bundle Buddy para averiguar si hay un problema.

<img src = "https://alistapart.com/wp-content/uploads/2019/06/figure-6-2x.png?w=960" alt = "La utilidad Bundle Buddy muestra cuánto código paquetes de JavaScript. [19659031] Bundle Buddy puede verificar las estadísticas de compilación de su paquete web y ver cuánto código se comparte entre sus paquetes.

Cuando se trata de una carga retrasada, averiguar dónde se encuentra puede ser difícil Cuando busco oportunidades en proyectos existentes, busco puntos de interacción del usuario en toda la base del código, como eventos de clic y teclado y candidatos similares, y cualquier código que requiera la interacción del usuario es un potencialmente buen candidato para la importación dinámica (19459007) () .

Por supuesto, cargar scripts puede, si es necesario, provocar un retraso notable en la interactividad para la interacción primero ser descargado Si el uso de datos no es un problema, debe usar la sugerencia de recurso rel = prefetch para cargar scripts de baja prioridad que no compiten con el ancho de banda de los recursos críticos. El soporte para rel = prefetch está bien, pero nada se romperá si no es compatible, ya que dichos navegadores ignoran el marcado que no entienden.

Código alojado externo de terceros # section6

Idealmente, debe alojar tantas dependencias de su sitio como sea posible. Si necesita cargar dependencias por cualquier motivo de un tercero márquelas en la configuración de su coordinador como dependencias externas . De lo contrario, los visitantes de su sitio pueden descargar tanto el código alojado localmente como el mismo código de un tercero.

Considera una situación hipotética en la que esto podría lastimarte: Digamos que tu sitio web está cargando a Lodash desde un CDN público. También ha instalado Lodash para el desarrollo local en su proyecto. Sin embargo, si no marca Lodash como externo, su código de producción eventualmente cargará una copia de un tercero además de la copia empaquetada y alojada localmente . Esto puede parecer como es bien sabido, si está familiarizado con los coordinadores, pero he visto que se pasa por alto. Vale la pena revisar dos veces.

Si no está convencido de alojar sus dependencias de terceros usted mismo, considere dns-prefetch preconnect o posiblemente agregue incluso punteros sesgo . De esta manera, puede reducir el Tiempo interactivo de su sitio y, si JavaScript es crítico para representar el contenido, reduzca el índice de velocidad de su sitio .

Alternativas más pequeñas para menos gastos generales # section7 [19659008] Userland JavaScript es como una tienda de dulces de gran tamaño, y nosotros, como desarrolladores, estamos impresionados con la gran cantidad de ofertas de código abierto. Los marcos y las bibliotecas nos permiten ampliar nuestras aplicaciones para hacer rápidamente cosas que de otro modo tomarían mucho tiempo y esfuerzo.

Personalmente, prefiero minimizar agresivamente el uso de marcos y bibliotecas del lado del cliente en el valor de mis proyectos es obligatorio. Sin embargo, tenemos la responsabilidad de ser un poco traviesos con nuestra instalación. Si ya hemos creado y entregado algo cuya ejecución depende de una gran cantidad de códigos instalados, hemos soportado los costos básicos que solo pueden cumplir los encargados del mantenimiento de este código. ¿Verdad?

Quizás, pero quizás no. Esto depende de las dependencias utilizadas. Por ejemplo, React es muy popular, pero Preact es una alternativa ultra pequeña que utiliza la misma API y sigue siendo compatible con muchos complementos de React. Luxon y Date-Fns son ​​alternativas mucho más compactas a moment.js que es no exactamente pequeño .

Las bibliotecas como Lodash ofrecen muchos métodos útiles. Sin embargo, algunos de ellos se reemplazan fácilmente con ES6 nativo. Por ejemplo, el método compacto de Lodash puede reemplazarse por el método de matriz . Se pueden reemplazar muchos más sin mucho esfuerzo y sin la necesidad de llamar a una gran biblioteca auxiliar.

Independientemente de sus herramientas preferidas, se aplica la misma idea: investigue un poco para ver si existen alternativas menores, o si las funciones del idioma nativo pueden hacer el truco. Se sorprenderá del poco esfuerzo que puede necesitar para reducir seriamente la sobrecarga de su aplicación.

Implemente sus scripts de manera diferente. # section8

Hay una buena posibilidad de que uses Babel en tu cadena de herramientas para transformar tu código fuente ES6 en código que pueda ejecutarse en navegadores más antiguos. ¿Significa esto que estamos condenados a proporcionar paquetes enormes para navegadores que no los necesitan hasta que los navegadores más antiguos hayan desaparecido por completo? ¡Por supuesto que no ! El servicio diferencial nos ayuda a solucionar este problema al generar dos compilaciones diferentes de su fuente ES6:

  • Bundle 1, que contiene todas las transformaciones y polyfills necesarios para que su sitio funcione en navegadores más antiguos. Probablemente ya esté operando este paquete en este momento.
  • Bundle Two contiene poco a nada transformaciones y polyfills, ya que se dirige a los navegadores modernos. Este es el paquete que probablemente no ofrezca, al menos todavía no .

Lograr esto es un poco complicado. He escrito una guía sobre cómo hacerlo por lo que no se requiere una inmersión profunda aquí. La conclusión es que puede cambiar su configuración de compilación para generar una versión adicional, pero más pequeña, del código JavaScript de su sitio que solo está disponible para los navegadores modernos. La mejor parte es que puede ahorrar dinero sin sacrificar las funciones que ya tiene. Dependiendo de su código de aplicación, los ahorros pueden ser significativos.

Un análisis del analizador de paquetes webpack del paquete heredado de un proyecto (izquierda) versus un paquete moderno (derecha). Ver imagen en tamaño original .

El patrón más simple para proporcionar estos paquetes para sus respectivas plataformas es corto. Esto también es un placer en los navegadores modernos:




Desafortunadamente, este patrón tiene una limitación: los navegadores más antiguos como IE 11 – e incluso los relativamente modernos como las versiones Edge 15-18 – descargue ambos paquetes , Si este es un compromiso aceptable para usted, no necesita preocuparse más.

Por otro lado, si tiene alguna inquietud, necesitará una solución alternativa para que los navegadores más antiguos descarguen ambos paquetes . Aquí hay una posible solución donde la entrada de script (en lugar de las etiquetas anteriores y ) se usa para evitar descargas duplicadas en los navegadores afectados:

  var scriptEl = document.createElement ("script") ;

if ("noModule" en scriptEl) 
// configurar un guión moderno
scriptEl.src = "http://alistapart.com/js/app.mjs";
scriptEl.type = "módulo";
 más 
// configurar script heredado
scriptEl.src = "/js/app.js";
scriptEl.defer = verdadero; // type = "module" cambia por defecto, así que ponlo aquí.


// inyectar!
document.body.appendChild (scriptEl); 

Este script concluye que un navegador que admite el atributo nomodule en el elemento de script entiende type = "module" . Esto garantiza que los navegadores antiguos reciban solo los scripts más antiguos y los navegadores modernos solo los modernos. Sin embargo, tenga en cuenta que las secuencias de comandos inyectadas dinámicamente se cargan de forma asincrónica de forma predeterminada. Establezca el atributo asíncrono en falso si el orden de dependencia es crítico.

No estoy aquí para arrojar a Babel a la basura. Es indispensable, pero genial. Agrega muchas cosas extra sin que lo sepas. Vale la pena mirar debajo del capó para ver qué está pasando. Algunos cambios menores en sus hábitos de codificación pueden tener un efecto positivo en lo que Babel escupe.

https://twitter.com/_developit/status/1110229993999777793

Nota: El parámetro predeterminado es una [ES muy útil función ES6 que probablemente ya use :

  Registrador de funciones (mensaje, nivel = "log") 
Consola [level] (mensaje);
 

Tenga en cuenta el parámetro nivel con la configuración predeterminada "log". Esto significa que con este contenedor se debe llamar al archivo console.log no tenemos que especificar el nivel . Genial, verdad? A menos que Babel transforme esta función, la salida se verá así:

  registrador de funciones (mensaje) 
var nivel = argumentos.length> 1 && argumentos [1]! == indefinido? Argumentos [1]: "log";

Consola [level] (mensaje);
 

Este es un ejemplo de cómo la comodidad del desarrollador puede ser contraproducente a pesar de nuestras mejores intenciones. Lo que era un puñado de bytes en nuestra fuente ahora se ha convertido a que es mucho más grande en nuestro código de producción . La aglomeración no puede hacer mucho al respecto porque los argumentos no se pueden reducir. Ah, y si piensas que Los parámetros de descanso podrían ser un antídoto digno, entonces las transformaciones de Babel son aún más extensas para ellos:

  // Fuente
Registrador de funciones (... args) 
const [level, message] = args;

Consola [level] (mensaje);


// problema de Babel
Registrador de funciones () 
for (var_len = argumentos.length, args = new_array (_len), _key = 0; _key <_len; _key ++) 
Argumentos [_key] = Argumentos [_key];


nivel constante = args [0],
mensaje = args [1];
Consola [level] (mensaje);
 

Peor aún, Babel transforma este código incluso para proyectos con una configuración @ babel / preset-env [level] que apunta a navegadores modernos lo que significa que los paquetes modernos están en ¡Su JavaScript con servicio diferente también se verá afectado! Usted podría usar transformaciones sueltas para mitigar el golpe, y esa es una buena idea, ya que a menudo son mucho más pequeñas que sus contrapartes más compatibles, pero permitir que muchas transformaciones puedan causar problemas si elimina Babel más tarde de su canal de compilación.

Independientemente de si elige activar transformaciones sueltas, tiene las siguientes opciones para reducir el conjunto de parámetros estándar transpuestos:

  // Babel no tocará eso
Registrador de funciones (mensaje, nivel)  "log"] (mensaje);
  

Por supuesto, los parámetros estándar no solo son cautelosos . Por ejemplo, la sintaxis de propagación se transforma, así como las funciones de flecha y una gama completa de otras cosas .

Si desea evitar esto en general, tiene algunas formas de reducir el impacto en la biblioteca:

  1. Cuando cree una biblioteca, debe considerar @babel / runtime juntos usando @babel / plugin-transform-runtime para deduplicar las funciones auxiliares que Babel inserta en su código.
  2. Para las funciones con múltiples funciones en las aplicaciones, puede insertarlas selectivamente usando @ babel / polyfill a través de useBuiltIns de @ babel / preset-env: opción "use" .

Esta es solo mi opinión, pero creo que la mejor opción es evitar la transpilación en los paquetes generados para los navegadores modernos. Esto no siempre es posible, especialmente si utiliza JSX que debe transformarse para todos los navegadores o si utiliza funciones de lenguaje de vanguardia que generalmente no son compatibles. En el último caso, puede valer la pena preguntar si estas características son realmente necesarias para una buena experiencia de usuario (que rara vez es el caso). Si llega a la conclusión de que Babel necesita ser parte de su cadena de herramientas, vale la pena mirar debajo del capó de vez en cuando para detectar cosas subóptimas que Babel podría hacer para mejorarlo.

La ​​mejora no es una carrera # section10

Mientras te masajeas las sienes, preguntándote cuándo terminará esta horrible resaca de JavaScript, debes entender que en ese momento, sacaremos algo del camino que puede afectar la experiencia del usuario , Dado que la comunidad de desarrolladores web intenta iterar más rápidamente en nombre de la competencia, vale la pena reducir la velocidad . Descubrirá que no puede iterar tan rápido como sus competidores, pero su producto será más rápido que el de ellos.

Tome estas sugerencias y aplíquelas a su código base, sabiendo que el progreso no ocurre espontáneamente de la noche a la mañana. El desarrollo web es un trabajo. El trabajo realmente efectivo se realiza cuando somos reflexivos y dedicados a la artesanía a largo plazo. Centrarse en mejoras constantes. La medición, las pruebas, la repetición y la experiencia del usuario de su sitio mejorarán con el tiempo y gradualmente se volverá más rápido.

Un agradecimiento especial a Jason Miller por la pieza de edición técnica. Jason es el creador y uno de los muchos mantenedores de Preact una alternativa mucho más pequeña a React usando la misma API. Si usa Preact debería considerar apoyar Preact a través de Open Collective .





Control de obras 3000 de Cea Ordenadores

Comentarios desactivados en Parte II – Una lista aparte