Servir mitjans adaptatius utilitzant Service Workers
Fent pair amb @Ester Martí
Visitar un lloc web amb una connexió de xarxa lenta triga una eternitat a carregar, fent l'experiència dolorosa o impossible.
Els desenvolupadors web sovint obliden el rendiment de càrrega mentre afegeixen característiques cridaneres. Però els usuaris probablement naveguen en dispositius mòbils de gamma mitjana o baixa amb connexions 3G com a màxim--no l'últim MacBook Pro amb fibra gigabit.
El 2018, el 52.2% de totes les pàgines web globals es van servir a telèfons mòbils.
El rendiment importa, i l'entrega de mitjans consumeix més recursos. Adaptarem l'entrega de mitjans basada en la connexió de xarxa utilitzant l'API d'Informació de Xarxa. Això millora un experiment que vaig construir amb @Eduardo Aquiles com a component de React, similar a l'article de Max Böck sobre components conscients de la connexió--però utilitzant service workers.
L'API d'Informació de Xarxa
L'API d'Informació de Xarxa és un esborrany d'especificació que exposa informació de connexió del dispositiu a JavaScript.
La interfície proporciona diversos atributs de xarxa. Els més rellevants aquí:
- type: El tipus de connexió que l'agent d'usuari està utilitzant. (p.ex. ‘wifi’, ‘cellular’, ‘ethernet’, etc.)
- effectiveType El tipus de connexió efectiva que es determina utilitzant una combinació de rtt i downlink observats recentment. (veure taula)
- saveData Indica quan l'usuari va sol·licitar un ús reduït de dades.
valors d'effectiveType
| ECT | RTT Mínim (ms) | Downlink Màxim (Kbps) | Explicació |
|---|---|---|---|
| slow‑2g | 2000 | 50 | La xarxa és adequada només per a transferències petites com pàgines de només text. |
| 2g | 1400 | 70 | La xarxa és adequada per a transferències d'imatges petites. |
| 3g | 270 | 700 | La xarxa és adequada per a transferències d'actius grans com imatges d'alta resolució, àudio i vídeo SD. |
| 4g | 0 | ∞ | La xarxa és adequada per a vídeo HD, vídeo en temps real, etc. |
Suport del navegador
L'API manca de suport complet del navegador però funciona en els navegadors mòbils més populars--on aquesta tècnica té major impacte.

De fet, el 70% dels usuaris mòbils tenen aquesta API habilitada al seu dispositiu.
Servir Mitjans Adaptatius
Servirem diferents recursos multimèdia basats en effectiveType. "Diferents
mitjans" podria significar canviar entre vídeo HD, imatge HD o imatge de baixa
qualitat, com suggereix
Addy Osmani.
Aquest exemple utilitza diferents nivells de compressió per a la mateixa imatge.
Primer, obté la qualitat adequada basada en les condicions de xarxa:
function getMediaQuality() {const connection =navigator.connection ||navigator.mozConnection ||navigator.webkitConnection;if (!connection) {return "medium";}switch (connection.effectiveType) {case "slow-2g":case "2g":return "low";case "3g":return "medium";case "4g":return "high";default:return "low";}}
Imagina un servidor d'imatges que accepta un paràmetre quality (low,
medium o high). Estableix la qualitat a l'atribut src:
<img src="http://images.magarcia.io/cute_cat?quality=low" alt="Gat bonic" />
const images = document.querySelectorAll("img");images.forEach((img) => {img.src = img.src.replace("low", getMediaQuality());});
La qualitat per defecte és low, així que els dispositius carreguen primer la
imatge de baixa qualitat, després milloren en connexions ràpides.
El JavaScript obté totes les imatges i reemplaça el paràmetre de qualitat segons
getMediaQuality. Per a qualitat low, no hi ha peticions addicionals. Per a
medium o high, ocorren dues peticions: una per a low en analitzar
l'etiqueta img, una altra per a millor qualitat quan s'executa JavaScript.
Això millora els temps de càrrega en xarxes lentes però duplica les peticions en connexions ràpides, consumint dades extra.
Utilitzant Service Workers
Els service workers resolen el problema de doble petició interceptant les peticions del navegador i reemplaçant-les amb la qualitat apropiada.
Primer, registra el service worker:
if ("serviceWorker" in navigator) {window.addEventListener("load", function () {navigator.serviceWorker.register("/sw.js").then(function (registration) {console.log("Registre de ServiceWorker exitós amb abast: ",registration.scope,);},function (err) {console.log("Registre de ServiceWorker fallit: ", err);},);});}
Afegeix un listener de l'esdeveniment fetch que afegeix el paràmetre de qualitat correcte a les peticions d'imatges:
self.addEventListener("fetch", function (event) {if (/\.jpg$|.png$|.webp$/.test(event.request.url)) {const url = event.request.url + `?quality=${getMediaQuality()}`;event.respondWith(fetch(url));}});
Ara omet el paràmetre de qualitat de les etiquetes img--el service worker ho
gestiona:
<img src=“http://images.magarcia.io/cute_cat” alt=“Gat bonic”/>
El codi
Troba el codi complet i més net en aquest repositori de GitHub.