Optimización de JavaScript

Escrito por Ramón Saquet

con O paso dos usuarios de dispositivos de escritorio a dispositivos móbiles, a optimización das páxinas web do cliente convértese en máis interese que no pasado, equipando importancia ás optimizacións do servidor. E é facer que unha web execute rápido en dispositivos máis lentos e con conexións que, dependendo da cobertura, poden ser malas ou incluso cortes, non é unha tarefa fácil, pero é necesario, xa que teñen unha maior velocidade implicará Usuarios máis satisfeitos que nos visitarán con máis frecuencia e mellor posicionamento en busca de móbiles.

Neste artigo probarei algúns dos puntos nos que ten que prestar máis atención no momento da optimización do JavaScript que funciona co cliente. Primeiro de todo, veremos como optimizar a súa descarga e compilación e, en segundo lugar, como optimizar a súa execución para que a páxina teña un bo rendemento. Comprensión do rendemento, a definición dada polo modelo de Google Rail. Estes acrónimos significan:

  • A resposta da interface en menos de 100 ms.
  • Animacións con cheo completo cada 16mas que son 60 fps ou 60 imaxes por segundo.
  • Desactivado: cando o usuario non interactúa coa páxina que funciona en segundo plano, non debe durar máis de 50 ms.
  • Cargar: a páxina debe cargar a 1000 m.

Nestes tempos debemos alcanzalos no peor dos casos (cando a web é executada nun móbil antigo), con poucos procesadores e recursos de memoria.

Tempo de carga web en comparación co escritorio.
Comparación da carga dun sitio web móbil e no escritorio obtido a partir da base de datos de base de datos pública. O histograma mostra o número de usuarios que obtiveron cada tempo de resposta. Como podes ver o máximo pico en móbil é de 2,5y no escritorio en 1.5s.

Seguinte, primeiro, as accións necesarias para optimizar a descarga e compilación E, en segundo lugar, as accións necesarias para optimizar a execución do código, esta parte sendo máis técnica, pero non menos importante.

Accións para optimizar a descarga e compilación do código JavaScript

Cachear no navegador

Aquí temos dúas opcións. O primeiro é usar a API de caché de JavaScript, a partir da cal podemos usar instalando un traballador de servizos. O segundo é usar a caché do protocolo HTTP. Se usamos a Cache API, a nosa aplicación podería ter a opción de operar en modo desconectado. Se usamos a caché do protocolo HTTP, aproximadamente, debemos configurala usando o parámetro de control de caché con valores públicos e de idade máxima, cun gran tempo de caché, como un ano. Despois, se queremos invalidar esta caché cambiaremos o nome ao ficheiro.

comprimir con Brotli Q11 e Gzip

Ao comprimir o código JavaScript, estamos a reducir os bits que Son transmitidos pola rede e, polo tanto, o tempo de transmisión, pero hai que ter en conta que estamos a aumentar o tempo de procesamento tanto no servidor como ao cliente, xa que o primeiro debe comprimir o ficheiro eo segundo descomprimido. Podemos gardar a primeira vez se temos unha caché de ficheiros comprimidos no servidor, pero o tempo de descompresión no cliente máis o tempo de transmisión comprimido pode ser maior que o tempo de transmisión do ficheiro descomprimido, facendo que esta técnica descargue máis lenta. Isto ocorrerá só con arquivos moi pequenos e con altas velocidades de transmisión. A velocidade de transmisión do usuario non pode saber, pero pódese dicir ao noso servidor que non comprende os ficheiros moi pequenos, por exemplo, dígalle que non comprende os ficheiros menos de 280 bytes. En conexións con altas velocidades, por riba de 100 MB / s, este valor debe ser moito maior, pero trata de optimizar para aqueles que teñen conexións móbiles con pouca cobertura, onde a perda de rendemento é máis pronunciada, aínda que en conexións rápidas van un pouco máis lentas.

O novo algoritmo de compresión Brotli mellora a compresión respecto de GZIP nun 17%. Se o navegador envía, no encabezado do protocolo HTTP, o valor “BR” dentro do parámetro de codificación de acectos, isto significará que o servidor pode enviar o ficheiro en formato Brotli no canto de en gzip.

Minimizar

Consiste en usar unha ferramenta automática para eliminar comentarios, espazos, pestanas e substituír as variables para que o código ocupe menos espazo.Os ficheiros minimizados deben estar atestados no servidor ou xerados xa minimizados ao cargarlos, xa que se o servidor ten que minimizarlos con cada solicitude, terá un rendemento negativo no rendemento.

Unificar o código JavaScript

Esta é unha técnica de optimización que non é moi importante se o noso sitio web funciona con HTTPS e HTTP2, xa que este protocolo envía os ficheiros coma se fosen só un, pero se o noso sitio web funciona con http1.1 ou esperamos Ten moitos clientes con navegadores antigos que usan este protocolo, a unificación é necesaria para optimizar a descarga. Pero non hai que ser aprobado e unificar todo o código web do ficheiro único, xa que se só se envía o código que precisa do usuario en cada páxina, os bytes poden ser bastante reducidos. Para iso, separaremos o código base que é necesario para todo o portal do que se vai executar en cada páxina individual. Deste xeito teremos dous ficheiros de JavaScript para cada páxina, unha coas bibliotecas básicas que serán comúns para todas as páxinas e outra co código específico da páxina. Cunha ferramenta como Webpack podemos unificar e minimizar estes dous grupos de ficheiros no noso proxecto de desenvolvemento. Probe que a ferramenta que use para iso xerará os chamados “mapas de orixe”. Estes son arquivos .Map que están asociados no encabezado do ficheiro final e no que se establecen a relación entre o código minimizado e unificado e os ficheiros de código fonte real. Deste xeito, podemos depurar o código sen problemas.

A opción de unificar todo nun único arquivo máis grande, ten o bo lado que pode golpear todo o código JavaScript na web no navegador, activado A primeira visita e, na seguinte carga, o usuario non terá que descargar todo o código JavaScript. Polo tanto, esta opción recoméndovos só se o aforro de bytes é prácticamente despreciable con respecto á arte anterior e temos unha taxa de baixa rebote.

Marcar o JavaScript como asíncrono

Debemos Incluír o JavaScript como segue:

<script async src="/codigo.js" />

Deste xeito, estamos a evitar a aparición da etiqueta de script que bloquee a fase de documentos da páxina da páxina.

Non use JavaScript incorporado na páxina

Cando se usa a etiqueta de script para inserir código na páxina, a construción de DOM tamén está bloqueada e aínda máis se se usa a función document.Write () .. Noutras palabras, isto está prohibido:

< script > document.Write (“Hello World!”) ; < / script >

Cargar o JavaScript no cabeceira da páxina con async

Antes de ter a etiqueta ASYNC, recoméndase poñer todas as etiquetas de script na parte inferior da páxina para evitar bloquear a construción. Isto xa non é necesario, de feito, é mellor que estea no interior da etiqueta

, de xeito que o JavaScript empeza a descargar, analizar e compilar o antes posible, xa que estas fases son os que máis van levar. Se este atributo non se usa, o JavaScript debe estar ao final.

Eliminar JavaScript que non se usa

Neste punto non só estamos a reducir o tempo de transmisión, senón tamén o Tempo que o leva ao navegador analizar e compilar o código. Para facelo, debemos ter en conta os seguintes puntos:

  • Se se detecta que unha funcionalidade non está sendo utilizada polos usuarios, podemos borralo con todo o seu código JavaScript asociado, de xeito que o A web cobrará máis rápido e os usuarios apreciaranse.
  • Tamén podemos ser incluídos por erro algunha biblioteca que non é necesaria ou temos bibliotecas que ofrecen algunha funcionalidade a partir da cal xa temos de forma nativa en todos os navegadores, sen necesidade Para usar código adicional e máis rápido.
  • Finalmente, se queremos optimizar o final, independentemente do tempo que use, debemos eliminar o código que non estamos a usar dentro das bibliotecas. Pero non o recomendo, porque nunca sabemos cando pode necesitar ser necesario.

Aprazar a carga de JavaScript que non é necesaria:

debería ser feito con esas funcionalidades que non son necesarias para o debuxo inicial da páxina. Son funcionalidades para as que o usuario debe realizar unha determinada acción para executala. Deste xeito, evitamos a carga e compilación de código JavaScript que retrasaría a visualización inicial. Unha vez que a páxina está totalmente cargada, podemos iniciar a carga destas funcionalidades para que estean inmediatamente dispoñibles cando o usuario comeza a interactuar.Google no modelo ferroviario recomenda que a carga postergada se realice en bloques de 50 ms para que non inflúe na interacción do usuario coa páxina. Se o usuario interactúa cunha funcionalidade que aínda non se cobrou, debemos cargalo nese momento.

Accións para optimizar a execución do código JavaScript

Evite usar demasiada memoria

Non podes dicir canta memoria será demasiado, pero podes dicir que sempre debemos tentar non usar máis do necesario, porque non sabemos a cantidade de memoria que terá o dispositivo que executará a web. Cando se executa o colector de lixo do navegador, é para a execución de JavaScript, e isto ocorre cada vez que o noso código solicita ao navegador para reservar nova memoria. Se isto ocorre con frecuencia, a páxina executarase lentamente.

Na pestana “Memory” das ferramentas de desenvolvedor de Chrome, podemos ver a memoria ocupada por cada función de JavaScript:

Memoria reservada por función de JavaScript.
Memoria reservada por función

Evite as fugas de memoria

Se temos unha fuga de memoria nun ciclo, a páxina reservará cada vez máis memoria que ocupa todo o dispositivo dispoñible e facendo que todo pase cada vez máis lento. Este fallo xeralmente é dado en carrusel e controis deslizantes de imaxes.

En Chrome podemos analizar se o noso sitio web ten fugas de memoria coa gravación dunha liña de tempo sobre a pestana de rendemento das ferramentas de desenvolvedor:

Mostra de fuga de memoria na pestana de rendemento de Google Chrome.

Este é o aspecto que ten unha fuga de memoria na pestana “Performance” de Google Chrome onde Podemos observar un crecemento constante de nodos de JS DOM e HEAP.

Normalmente as fugas de memoria veñen por pezas SDU que son eliminadas da páxina pero que teñen calquera variable que lles faga referencia e, polo tanto, o colector de lixo non pode eliminar-los e non entender como o alcance das variables e peche en JavaScript funciona.

Dom Dom Dom Árbores (Dom separado) que están ocupando memoria porque hai variables que os fan referencia.

traballadores web de Estados Unidos cando precisa executar o código Necesitas moito tempo de execución

Todos os procesadores de hoxe son multi-celular e multi-core, pero Javascript foi tradicionalmente unha lingua monohlyllosa e, aínda que ten temporizadores, estes son executados no mesmo fío de execución, no que, no que, no que, Ademais, execútase a interacción coa interface, polo tanto, mentres que JavaScript está a executar a interface está bloqueada e leva máis de 50 ms. Os traballadores web e os traballadores de servizos traen a execución multi-fan a JavaScript, aínda que non permiten o acceso directo ao domingo, polo que teremos que pensar como atrasar o acceso a este, a fin de aplicar aos traballadores web nos casos que nós ter un código que a tarde máis de 50ms a ser executada.

Usando a API de busca (AJAX)

O uso da API de busca ou AJAX tamén é unha boa forma de que o usuario percibir un tempo de carga máis rápido, pero non debemos usalo na carga inicial, senón na navegación posterior e dun xeito indexable. Para iso, a mellor forma de implementar é usar un marco que usa Javascript universal.

Prioriza o acceso ás variables locais

Javascript primeiro ver se a variable existe localmente e segue a atopar Nas áreas superiores, sendo as últimas variables globais. JavaScript acceder ás variables locais máis rápido porque non ten que buscar a variable en ambites máis altos para atopalo, polo que é unha boa estratexia que aforra en variables locais aquelas variables dunha área superior ao acceder a varias veces e, ademais, ademais, Non cree novas áreas con peche ou con eles e intente atrapar declaracións, sen que sexa necesario.

Se accede a un elemento DOM varias veces para gardalo nunha variable local

Acceso ao DOM é lento. Entón, se imos ler os contidos dun elemento varias veces, gardalo nunha variable local, polo que o JavaScript non terá que buscar o elemento ao sol cada vez que queira acceder ao seu contido. Pero preste atención, se manteña unha peza de DOM nunha variable que máis tarde elimina da páxina e non usará máis, probe entón asignar a “nula” a variable onde o gardou para non causar unha fuga de memoria ..

Grupo e minimizar as lecturas de DOM e CSSOM e scripts

Cando o navegador atrae unha páxina executa a ruta de representación crítica que segue os seguintes pasos a primeira carga:

  1. O HTML é recibido.
  2. comeza a construír o DOM.
  3. Aínda que o DOM está construído, os recursos externos son solicitados (CSS e JS).
  4. A CCSOM (mestura de DOM e CSS) está construída.
  5. A árbore de representación créase (son as partes do CSSOM que se debuxarán).
  6. Da árbore de representación calcúlase a xeometría de cada parte visible da árbore nunha capa. Esta etapa chámase deseño ou refluxo.
  7. Na fase final da pintura, as capas do paso 6 están pintadas e están compostas unha sobre outra para mostrar a páxina ao usuario.
  8. Se terminou de compilar o JavaScript, execútase (en realidade, este paso podería ocorrer en calquera momento despois do paso 3, sendo mellor o antes posible).
  9. Se no paso anterior as forzas do código JavaScript Para refacer parte do DOM ou a CSSOM devolveremos varios pasos detrás que se executarán ata o punto 7.
Construción da árbore de renderización ou renderización da árbore.
Construción da árbore de representación

Aínda que os navegadores están pegando os cambios do Árbore de representación e decidir cando facer a pintura, se temos un ciclo no que lemos o DOM e / ou o CSSOM e modificámolo na seguinte liña, o navegador pode ver f Estado para executar o refluxo ou repintar a páxina varias veces, especialmente se a seguinte lectura depende da escrita anterior. É por iso que se recomenda:

  • Separar todas as lecturas nun circuíto separado e facer todos os escritos ao mesmo tempo coa propiedade CSSTTXT se é o CSSOM ou Innerhtml se é o sano, entón O navegador que só terá que lanzar un repintamento.
  • Se as lecturas dependen das escrituras anteriores, buscan unha forma de reescribir o algoritmo para que isto non sexa así.
  • Se Non tes opción de aplicar moitos cambios nun elemento do domingo, sacalo do domingo, facer os cambios e devolvelo para introducir onde estaba.
  • en Google Chrome, podemos analizar o que acontece na ruta de representación crítica coa pestana do faro na pestana “Auditorías” ou na pestana “Performance” gravando o que ocorre mentres a páxina está cargada.
Análise de rendemento da ferramenta de faro.
Neste faro análise de rendemento da páxina de inicio de Google , podemos ver que recursos bloquean a ruta de representación crítica.

Usar a función de restauración (devolución de chamada) en animacións e os efectos que dependen do desprazamento

A función de restauración () (), fai que a función que se transmite como parámetro non causa unha repintación, ata a próxima programación. Isto, ademais de evitar pinturas innecesarias, ten o efecto de que as animacións paran mentres o usuario está noutra pestana, aforrando a CPU e a batería do dispositivo.

Os efectos que dependen do desprazamento son os máis lentos porque o seguinte DOM propiedades forzar un refluxo (Paso 7 do punto anterior) ao acceder a eles:

offsetTop, offsetLeft, offsetWidth, offsetHeightscrollTop, scrollLeft, scrollWidth, scrollHeightclientTop, clientLeft, clientWidth, clientHeightgetComputedStyle() (currentStyle en IE)

Se ademais de acceder a unha destas propiedades, baseándose nelas, Pintamos unha bandeira ou un menú que o seguen movendo o desprazamento ou un efecto de desprazamento, unha pintura de varias capas cada vez que move o desprazamento, afectando negativamente o tempo de resposta da interface, co que podemos ter un desprazamento que está a saltar no seu lugar de deslizamento suavemente. Polo tanto, con estes efectos, a última posición do desprazamento no evento onscroll debe ser gardada nunha variable global e despois de utilizar a función de restostanimationframe () só se a animación anterior acaba.

se hai Moitos eventos similares agriclo

Se ten 300 botóns que cando fai clic en facer prácticamente o mesmo, podemos asignar un evento ao elemento primario dos 300 botóns en lugar de asignar 300 eventos a cada un deles. Ao facer clic nun botón, o evento “burbulla” ao pai e deste, podemos saber que botón fai clic e modificar o comportamento de conformidade.

Coidado cos eventos que disparan varias veces seguido

Eventos como onmouse ou onscroll, disparar varias veces seguidas mentres se realiza a acción. Polo tanto, intente controlar que o código asociado non executa máis veces que os necesarios, xa que este é un erro bastante común.

Evite a execución do código con código con eval (), función (), establecemento () e setinterval ()

O feito de introducir o código nun literal a ser analizado e compilado Durante a execución do resto do código é bastante lento, por exemplo: eval (“C = A + B”); Sempre pode refacer o programa para evitar ter que facer isto.

Implementar as optimizacións que aplicaría en calquera outro idioma de programación

  • sempre use os algoritmos coa complexidade menos computacional a complexidade ciclomática para que a tarefa se solucione.
  • Utiliza as estruturas de datos óptimas para acadar o punto anterior.
  • Reescribir o algoritmo para obter o mesmo resultado con menos cálculos.
  • Evite chamadas recursivas, cambiando o algoritmo por un equivalente que fai uso dunha pila.
  • Fai unha función con un custo elevado e as chamadas repetidas ao longo de diferentes bloques de código Gardar en memoria O resultado do resultado A seguinte chamada.
  • Pon os cálculos e as chamadas a funcións repetidas en variables.
  • Cando anda un ciclo, almacena o tamaño do ciclo nunha variable primeiro, para evitar calcular de novo , na súa condición de finalización, en cada iteración.
  • Factorizar e simplifica as fórmulas matemáticas.
  • substitúe os cálculos que non dependen das variables por constantes e deixa o cálculo comentario.
  • Utiliza arrays de busca: serven para obter un valor baseado noutro no seu lugar de usar un bloque de interruptor.
  • Fai que as condicións sempre sexan máis propensas a aproveitar a execución especulativa do procesador, xa que así a predición dos saltos fallará menos.
  • Simplificar as expresións booleanas Coas regras da lóxica booleana ou mellor aínda con mapas de karnaugh.
  • usa operadores a nivel de bit cando pode usalos para substituír certas operacións, xa que estes operadores usan menos ciclos de procesador. Usalos require a aritmética binaria saber, por exemplo: Ser valor xa de toda unha variable enteira, podemos poñer “y = x > > 1 ; “” no canto de “y = x / 2;” ou “y = x & 0xff;” No canto de “y = x% 256”.

Estes son algúns dos meus favoritos, o máis importante sendo os tres primeiros e os máis estudos e a práctica requiren. Este último son micro-optimizacións que só pagan a pena se realizas mentres escribes o código ou se é algo computable moi caro como un editor de video ou un videojuego, aínda que nestes casos será mellor que Websebly en vez de JavaScript .

Ferramentas para detectar problemas

Xa vimos varios. De todos eles, o faro é o máis sinxelo de interpretar, xa que simplemente nos dá unha serie de puntos para mellorar, como tamén nos pode dar ás informacións de páxinas de Google ou, moitos outros, como Gtmetrix. En Chrome tamén podemos usar, na opción “Máis ferramentas” no menú principal, o xestor de tarefas, para ver a memoria e a CPU utilizada por cada pestana. Para unha análise aínda máis técnica, temos as ferramentas para os desenvolvedores de Firefox e Google Chrome, onde temos a pestana chamada “Performance” e que nos permite analizar os tempos de cada fase, fugas de memoria, etc. Imos ver un exemplo :.

análise de rendemento de Google Chrome
na análise de rendemento de Google Chrome, na ferramenta Menú Permítenos simular unha CPU e rede máis lenta e nel vemos, entre outras cousas, as imaxes ou as táboas por segundo (recordemos que debe ser inferior a 16ms) e as fases da ruta de representación crítica con cores: En azul o tempo de carga dos ficheiros, en amarelo o tempo de execución dos scripts, en vermello o tempo de construción da árbore de representación (incluíndo os refluos ou a construción do esquema) e en verde o tempo de pintura. Ademais, o tempo que levou a pintar cada marco aparece e como este foi.

Toda a información que vexamos arriba pode ser gravada mentres a páxina está cargado, corremos unha acción ou convertemos en Scroll. Entón podemos achegar a unha parte do gráfico para velo en detalle e, se neste caso, o que máis leva é a execución de JavaScript, podemos implementar a sección principal e facer clic enriba dos scripts que levan máis tempo .. Polo tanto, a ferramenta nos mostrará detalladamente na pestana de abaixo que está a afectar o JavaScript a cada fase do camiño de representación crítica e na pestana Resumo, indicará cunha advertencia se detectou un problema de rendemento en JavaScript. Cluting encima do ficheiro que indica, levaranos específicamente á liña que produce o atraso.

Resumo da ferramenta de Devtariools con aviso de problemas de rendemento.
Aviso do resumo da ficha das ferramentas de rendemento

Finalmente, para unha análise aínda máis fino, é aconsellable empregar a API de tempo de navegación de JavaScript que nos permite medir esta parte de cada parte do noso código desde o programar en si mesmo.

Recomendacións finais

Como vexas, a optimización de JavaScript non é unha tarefa fácil e leva un proceso de optimización de análise e traballo que pode superar o orzamento destinado ao desenvolvemento que tivemos Inicialmente pensado. Polo tanto, hai poucos sitios web, complementos e temas máis famosos para os xestores de contido habituais que presentan moitos dos problemas que teño enumerado.

Se o seu sitio web presenta estes problemas, intente resolver aqueles que teñen un maior impacto Performance e buscar sempre que as optimizacións non afecten a mantemento e calidade do código. É por iso que non recomendo o uso de técnicas de optimización máis extremas, como a eliminación de chamadas a funcións substituíndoas polo código que chaman, o desenrollado de loops ou o uso da mesma variable para todo, de xeito que o fose Caching ou dos rexistros do procesador, xa que son técnicas que suciasen o código e, na compilación en JavaScript Runtime, algúns deles son aplicados. Entón, lembre:

O rendemento non é un requisito que nunca debe estar por riba da facilidade de detectar erros e engadir funcionalidades.

¿Vostede ve

Póñase en contacto connosco se quere que nos axuden a mellorar a súa visibilidade en liña. Díganos sobre o que vai o seu proxecto e presentaremos unha proposta personalizada para as necesidades do seu negocio.

Deixa unha resposta

O teu enderezo electrónico non se publicará Os campos obrigatorios están marcados con *