[Les stagiaires front-end se préparent pour le recrutement d'automne]—Optimisation des performances front-end, recommandé pour collecter

[Les stagiaires front-end se préparent pour le recrutement d'automne]—Optimisation des performances front-end, recommandé pour collecter

Questions d'entretien d'optimisation des performances.png

Annuaire d'articles

1. CDN

1. Le concept de CDN

CDN (Content Delivery Network ) fait référence à un système de réseau informatique connecté les uns aux autres via Internet. Il utilise le serveur le plus proche de chaque utilisateur pour diffuser de la musique, des images, des vidéos, des applications et d'autres fichiers de manière plus rapide et plus fiable. hautes performances, évolutivité et contenu réseau à faible coût pour les utilisateurs.

Un système CDN typique se compose des trois parties suivantes :

  • **Système de service de distribution :** L'unité de travail la plus élémentaire est le périphérique de cache. Le cache (Edge Cache) est chargé de répondre directement aux demandes d'accès des utilisateurs finaux et de fournir rapidement aux utilisateurs le contenu mis en cache localement. Dans le même temps, le cache est également responsable de la synchronisation du contenu avec le site source, en obtenant le contenu mis à jour et le contenu qui n'est pas disponible localement à partir du site source et en l'enregistrant localement. Le nombre, l'échelle et les capacités de service totales des périphériques de cache sont les indicateurs les plus élémentaires pour mesurer les capacités de service d'un système CDN.
  • Système d'équilibrage de charge : la fonction principale est de planifier l'accès à tous les utilisateurs qui lancent des demandes de service et de déterminer l'adresse d'accès réelle finale fournie aux utilisateurs. Le système de planification à deux niveaux est divisé en équilibrage de charge global (GSLB) et équilibrage de charge local (SLB). L'équilibrage de charge global repose principalement sur le principe de proximité des utilisateurs et détermine l'emplacement physique du cache qui fournit les services aux utilisateurs en effectuant des jugements « optimaux » sur chaque nœud de service. L'équilibrage de charge local est principalement responsable de l'équilibrage de charge des appareils au sein du nœud.
  • Système de gestion des opérations : le système de gestion des opérations est divisé en sous-systèmes de gestion des opérations et de gestion du réseau. Il est responsable de la gestion des travaux de collecte, de tri et de livraison nécessaires à l'interaction avec les systèmes externes au niveau de l'entreprise, y compris la gestion des clients, la gestion des produits, la facturation. gestion, analyse statistique, etc. Fonction.

2. Le rôle du CDN

Les CDN sont généralement utilisés pour héberger des ressources Web (notamment du texte, des images, des scripts, etc.), des ressources téléchargeables (fichiers multimédias, logiciels, documents, etc.) et des applications (portails, etc.). Utilisez un CDN pour accélérer l'accès à ces ressources.

(1) En termes de performances, le rôle de l'introduction du CDN est :

  • Les utilisateurs reçoivent le contenu du centre de données le plus proche, avec une latence plus faible et un chargement de contenu plus rapide.
  • Certaines demandes de ressources sont allouées au CDN, réduisant ainsi la charge sur le serveur

(2) En termes de sécurité, CDN aide à se défendre contre les DDoS, MITM et autres attaques réseau :

  • Pour les DDoS : surveillez et analysez le trafic anormal et limitez sa fréquence de requêtes
  • Pour MITM : communication HTTPS en liaison complète du serveur d'origine vers le nœud CDN vers le FAI (fournisseur d'accès Internet)

De plus, le CDN, en tant que service cloud de base, présente également des avantages en matière d'hébergement de ressources et d'expansion à la demande (peut faire face aux pics de trafic).

3. Principe du CDN

CDN et DNS sont indissociables. Jetons d'abord un coup d'œil au processus de résolution de nom de domaine du DNS. Le processus de résolution de la saisie de www.test.com dans le navigateur est le suivant :

(1) Vérifiez le cache du navigateur

(2) Vérifiez le cache du système d'exploitation, les plus courants tels que le fichier hosts

(3) Vérifiez le cache du routeur

(4) S'il n'est pas trouvé lors des premières étapes, il interrogera le serveur LDNS du FAI (Fournisseur d'Accès Internet)

(5) Si le serveur LDNS n'est pas trouvé, il demandera une résolution au serveur de noms de domaine racine (Root Server), qui est divisée en les étapes suivantes :

  • Le serveur racine renvoie l'adresse du serveur de nom de domaine de premier niveau (TLD), tel que .com, .cn, .orgetc. Dans cet exemple, .coml'adresse sera renvoyée
  • Envoyez ensuite une requête au serveur de noms de domaine de niveau supérieur, puis renvoyez l'adresse du serveur de noms de domaine secondaire (SLD). Dans cet exemple, .testl'adresse renvoyée
  • Envoyez ensuite une requête au serveur de noms de domaine secondaire, puis renvoyez l'adresse IP cible interrogée via le nom de domaine. Dans cet exemple, www.test.coml'adresse renvoyée
  • Le serveur DNS local mettra en cache les résultats et les renverra à l'utilisateur, mis en cache dans le système

Comment fonctionne le CDN :

(1) Le processus des utilisateurs n'utilisant pas CDN pour mettre en cache les ressources :

  1. Le navigateur résout le nom de domaine via DNS (c'est-à-dire le processus de résolution DNS ci-dessus) et obtient à son tour l'adresse IP correspondant au nom de domaine.
  2. Le navigateur envoie une demande de données à l'hébergeur du service du nom de domaine en fonction de l'adresse IP obtenue.
  3. Le serveur renvoie les données de réponse au navigateur

(2) Le processus des utilisateurs utilisant CDN pour mettre en cache les ressources :

  1. Pour l'URL des données cliquées, après analyse par le système DNS local, il s'avère que l'URL correspond à un serveur DNS dédié au CDN. Le système DNS transmettra les droits de résolution du nom de domaine au serveur DNS dédié au CDN pointé. par le CNAME.
  2. Le serveur DNS dédié CND renvoie l’adresse IP globale du périphérique d’équilibrage de charge du CND à l’utilisateur.
  3. Les utilisateurs lancent des demandes de données vers le dispositif d'équilibrage de charge global de CDN
  4. Le périphérique d'équilibrage de charge global du CDN sélectionne un périphérique d'équilibrage de charge régional dans la région de l'utilisateur en fonction de l'adresse IP de l'utilisateur et de l'URL de contenu demandée par l'utilisateur, et indique à l'utilisateur de lancer une demande auprès de ce périphérique.
  5. Le dispositif d'équilibrage de charge régional sélectionne un serveur de cache approprié pour fournir des services et renvoie l'adresse IP du serveur de cache au dispositif d'équilibrage de charge global.
  6. Le dispositif d'équilibrage de charge global renvoie l'adresse IP du serveur à l'utilisateur
  7. L'utilisateur initie une requête au serveur de cache, et le serveur de cache répond à la requête de l'utilisateur et envoie le contenu requis par l'utilisateur au terminal utilisateur.

Si le serveur de cache ne dispose pas du contenu souhaité par l'utilisateur, il demandera le contenu à son serveur de cache de niveau supérieur, et ainsi de suite, jusqu'à ce que les ressources requises soient obtenues. Au final, s'il n'existe toujours pas, il retournera sur son propre serveur pour récupérer les ressources.

image

CNAME (signification : alias) : dans la résolution de nom de domaine, l'adresse IP correspondant au nom de domaine spécifié est effectivement analysée, ou un CNAME du nom de domaine, puis l'adresse IP correspondante est trouvée sur la base de ce CNAME.

4. Scénarios d'utilisation du CDN

  • Utilisez un service CDN tiers. Si vous souhaitez ouvrir certains projets en open source, vous pouvez utiliser un service CDN tiers.
  • Utilisez CDN pour mettre en cache les ressources statiques et placez les ressources statiques de votre site Web sur CDN, telles que js, css, images, etc. L'ensemble du projet peut être placé sur CDN pour terminer le déploiement en un clic.
  • Transmission de diffusion en direct La diffusion en direct utilise essentiellement le streaming multimédia pour la transmission, et CDN prend également en charge la transmission multimédia en streaming, de sorte que la diffusion en direct peut utiliser complètement le CDN pour améliorer la vitesse d'accès. CDN traite le streaming multimédia différemment des fichiers statiques ordinaires. Si un fichier ordinaire n'est pas trouvé au niveau du nœud périphérique, il ira à la couche supérieure pour le trouver. Cependant, la quantité de données dans le streaming multimédia lui-même est très importante. Si vous utiliser le retour à la source Cette méthode entraînera inévitablement des problèmes de performances, c'est pourquoi le streaming multimédia utilise généralement le push actif.

2. Chargement paresseux

1. Le concept de chargement paresseux

Le chargement paresseux est également appelé chargement différé et chargement à la demande. Il fait référence au retardement du chargement des données d'image dans de longues pages Web. Il s'agit d'un meilleur moyen d'optimiser les performances des pages Web. Dans une page Web ou une application relativement longue, s'il y a beaucoup d'images, toutes les images seront chargées et l'utilisateur ne pourra voir que cette partie des données d'image dans la fenêtre visuelle, ce qui gaspille les performances.

Si vous utilisez le chargement paresseux des images, vous pouvez résoudre le problème ci-dessus. Les images en dehors de la zone visuelle ne seront pas chargées avant le défilement de l'écran et ne seront chargées que lorsque l'écran défilera. Cela accélère le chargement des pages Web et réduit la charge sur le serveur. Le chargement paresseux convient aux scénarios dans lesquels il y a de nombreuses images et une longue liste de pages (longue liste).

2. Caractéristiques du chargement paresseux

  • Réduisez le chargement des ressources inutiles : L'utilisation du chargement paresseux réduit considérablement la pression et le trafic sur le serveur, et réduit également la charge sur le navigateur.
  • Améliorer l'expérience utilisateur : Si vous chargez plus d'images en même temps, vous devrez peut-être attendre plus longtemps, ce qui affecte l'expérience utilisateur. L'utilisation du chargement différé peut grandement améliorer l'expérience utilisateur.
  • Empêcher le chargement d'un trop grand nombre d'images d'affecter le chargement d'autres fichiers de ressources : cela affectera l'utilisation normale des applications du site Web.

3. Principe de mise en œuvre du chargement paresseux

Le chargement des images est srcprovoqué par : Lorsqu'une srcvaleur est attribuée, le navigateur demandera la ressource image. Sur la base de ce principe, nous utilisons data-xxxles attributs HTML5 pour stocker le chemin de l'image. Lorsque nous devons charger l'image, nous data-xxxattribuons le chemin à l'image src. Cela permet un chargement des images à la demande, c'est-à-dire un chargement paresseux.

Remarque : data-xxxil xxxpeut être personnalisé, ici nous l'utilisons data-srcpour définir.

Le point clé de l'implémentation du chargement différé est de déterminer quelle image l'utilisateur doit charger. Dans le navigateur, les ressources dans la zone visible sont les ressources dont l'utilisateur a besoin. Ainsi, lorsque l'image apparaît dans la zone visible, obtenez simplement la véritable adresse de l'image et attribuez-la à l'image.

Utilisez JavaScript natif pour implémenter le chargement différé :

Points de connaissances :

(1) window.innerHeightest la hauteur de la zone visuelle du navigateur

(2) document.body.scrollTop || document.documentElement.scrollTopC'est la distance que le navigateur fait défiler

(3) imgs.offsetTopest la hauteur du haut de l'élément au haut du document (y compris la distance de la barre de défilement)

(4) Conditions de chargement des images :img.offsetTop < window.innerHeight + document.body.scrollTop;

Illustration:

image

Code:

<div class="container">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
</div>
<script>
var imgs = document.querySelectorAll('img');
function lozyLoad(){
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        var winHeight= window.innerHeight;
        for(var i=0;i < imgs.length;i++){
            if(imgs[i].offsetTop < scrollTop + winHeight ){
                imgs[i].src = imgs[i].getAttribute('data-src');
            }
        }
    }
  window.onscroll = lozyLoad();
</script>

4. La différence entre le chargement paresseux et le préchargement

Ces deux méthodes sont des moyens d'améliorer les performances des pages Web. La principale différence entre les deux est que l'une se charge tôt et l'autre se charge lentement, voire pas du tout. Le chargement paresseux a un certain effet sur le soulagement de la pression sur le front-end du serveur, tandis que le préchargement augmentera la pression sur le front-end du serveur.

  • Le chargement paresseux est également appelé chargement différé. Il fait référence au retard dans le chargement des images dans de longues pages Web. Lorsque les utilisateurs auront besoin d'y accéder, elles seront chargées à nouveau. Cela peut améliorer la vitesse de chargement du premier écran du site Web, améliorer la expérience utilisateur et réduire la charge sur le serveur. Il convient aux sites Web de commerce électronique comportant de nombreuses images et de longues pages. Le principe de mise en œuvre du chargement paresseux consiste à définir l'attribut src de l'image sur la page sur une chaîne vide, à enregistrer le chemin réel de l'image dans un attribut personnalisé, et lorsque la page défile, il sera jugé si l'image entre dans le zone visible de la page. À l'intérieur, le chemin réel est extrait de l'attribut personnalisé et attribué à l'attribut src de l'image pour obtenir un chargement paresseux de l'image.
  • Le préchargement fait référence à la demande de chargement local des ressources requises à l'avance, afin que les ressources puissent être récupérées directement à partir du cache en cas de besoin ultérieur. Le préchargement peut réduire le temps d'attente de l'utilisateur et améliorer l'expérience utilisateur. La manière la plus courante que je connaisse à propos du préchargement est d'utiliser l'objet image dans js et de définir l'attribut scr pour l'objet image afin de réaliser le préchargement de l'image.

3. Redistribuer et redessiner

1. Concepts et conditions de déclenchement du reflow et du redraw

(1) Reflux

Lorsque la taille, la structure ou les attributs de tout ou partie des éléments de l'arborescence de rendu changent, le processus par lequel le navigateur restitue une partie ou la totalité du document est appelé redistribution .

Les opérations suivantes peuvent provoquer une redistribution :

  • Premier rendu de la page
  • La taille de la fenêtre du navigateur change
  • Le contenu de l'élément change
  • La taille ou la position de l'élément change
  • La taille de la police d'un élément change
  • Activer les pseudo-classes CSS
  • Interroger certaines propriétés ou appeler certaines méthodes
  • Ajouter ou supprimer des éléments DOM visibles

Lorsque la redistribution (réarrangement) est déclenchée, puisque le navigateur restitue la page en fonction d'une mise en page fluide, lorsque la redistribution est déclenchée, les éléments DOM environnants seront réorganisés. Son champ d'influence est de deux types :

  • Portée globale : relayer l'intégralité de l'arborescence de rendu à partir du nœud racine
  • Portée locale : relayer une certaine partie de l'arborescence de rendu ou un objet de rendu

(2) Redessiner

Lorsque le style de certains éléments de la page change, mais n'affecte pas leur position dans le flux de documents, le navigateur redessine les éléments. Ce processus est appelé redessiner .

Les opérations suivantes peuvent provoquer une redistribution :

  • Couleur, propriétés liées à l'arrière-plan : couleur d'arrière-plan, image d'arrière-plan, etc.
  • Attributs liés au contour : couleur du contour, largeur du contour, décoration du texte
  • border-radius、visibilité、box-shadow

Remarque : Lorsque la redistribution est déclenchée, le redessin sera certainement déclenché, mais le redessin ne déclenche pas nécessairement la redistribution.

2. Comment éviter la refusion et le redessinage ?

Mesures pour réduire la refusion et le redessinage :

  • Lorsque vous utilisez le DOM, essayez d'opérer sur des nœuds DOM de bas niveau.
  • N'utilisez pas tablede mises en page, un petit changement peut entraîner une tablenouvelle mise en page entière
  • Expressions utilisant CSS
  • Ne manipulez pas fréquemment le style des éléments. Pour les pages statiques, vous pouvez modifier le nom de la classe au lieu du style.
  • Utilisez absolu ou fixe pour supprimer des éléments du flux de documents afin que leurs modifications n'affectent pas les autres éléments.
  • Pour éviter de manipuler fréquemment le DOM, vous pouvez créer un fragment de document documentFragment, lui appliquer toutes les opérations DOM et enfin l'ajouter au document.
  • Définissez d'abord l'élément display: none, puis affichez-le une fois l'opération terminée. Parce que les opérations DOM effectuées sur des éléments avec un attribut d'affichage nul ne provoqueront pas de redistribution ni de redessinage.
  • Rassemblez plusieurs opérations de lecture (ou opérations d'écriture) du DOM au lieu d'entrecouper les opérations de lecture et d'écriture avec les écritures. Cela est dû au mécanisme de file d'attente de rendu du navigateur .

Le navigateur s'est optimisé pour la redistribution et le redessinage des pages - file d'attente de rendu

Le navigateur mettra toutes les opérations de redistribution et de redessinage dans une file d'attente. Lorsque les opérations dans la file d'attente atteignent un certain nombre ou un certain intervalle de temps, le navigateur regroupera la file d'attente. Cela transformera plusieurs refusions et redessinages en une seule redistribution et redessinage.

Ci-dessus, lorsque plusieurs opérations de lecture (ou opérations d'écriture) sont regroupées, elles seront exécutées une fois que toutes les opérations de lecture entreront dans la file d'attente. De cette façon, au lieu de déclencher plusieurs reflows, un seul reflow est déclenché.

3. Comment optimiser l'animation ?

Quant à la façon d'optimiser l'animation, nous savons qu'en général, l'animation nécessite des manipulations fréquentes du DOM, ce qui entraînera des problèmes de performances sur la page. Nous pouvons définir les propriétés de l'animation positionou absoluteséparer fixedl'animation du flux de documents, afin que sa redistribution ne sera pas Cela affectera la page.

4. Qu'est-ce que documentFragment ? Quelle est la différence entre l’utiliser et manipuler directement le DOM ?

documentFragmentExplication MDN de :

DocumentFragment, interface de fragment de document, un objet de document minimal sans objet parent. Il est utilisé comme une version allégée de Document, tout comme un document standard, stockant une structure de document composée de nœuds. Par rapport au document, la plus grande différence est que DocumentFragment ne fait pas partie de la véritable arborescence DOM. Ses modifications ne déclencheront pas le nouveau rendu de l'arborescence DOM et ne causeront pas de problèmes de performances ou autres.

Lorsque nous insérons un nœud DocumentFragment dans l'arborescence du document, ce qui est inséré n'est pas le DocumentFragment lui-même, mais tous ses nœuds descendants. Lors d'opérations DOM fréquentes, nous pouvons insérer des éléments DOM dans DocumentFragment, puis insérer tous les nœuds descendants dans le document en même temps. Par rapport à l'exploitation directe du DOM, l'insertion d'un nœud DocumentFragment dans l'arborescence DOM ne déclenchera pas le redessinage de la page, ce qui améliore considérablement les performances de la page.

4. Limitation et anti-secousse

1. Compréhension de la limitation et de l'anti-shake

  • La fonction anti-shake signifie exécuter le rappel n secondes après le déclenchement de l'événement. Si l'événement est à nouveau déclenché dans ces n secondes, le temps sera relancé. Cela peut être utilisé sur certains événements de demande de clic pour éviter d'envoyer plusieurs demandes au backend en raison de plusieurs clics d'utilisateur.
  • La limitation des fonctions fait référence à la spécification d'une unité de temps. Dans cette unité de temps, la fonction de rappel qui déclenche l'événement ne peut être exécutée qu'une seule fois. Si un événement est déclenché plusieurs fois dans la même unité de temps, une seule fois peut prendre effet. La limitation peut être utilisée lors de l'écoute d'événements de la fonction de défilement pour réduire la fréquence des appels d'événements grâce à la limitation d'événements.

Scénarios d'application de la fonction anti-secousse :

  • Scénario de soumission de boutons : empêchez les soumissions de boutons multiples et exécutez uniquement la dernière soumission
  • Scénario de vérification côté serveur : La vérification du formulaire nécessite la coopération du serveur. Elle n'exécute que la dernière fois d'un événement de saisie continu. Il existe également une fonction de recherche similaire pour les mots associés dans l'environnement de vie. Veuillez utiliser lodash.debounce.

Les scénarios les plus applicables pour les fonctions de limitation :

  • Scénario glisser-déposer : exécuté une seule fois dans un laps de temps déterminé pour éviter des déclenchements trop fréquents de changements de position.
  • Scénario Zoom : Surveiller le redimensionnement du navigateur
  • Scène d'animation : évitez les problèmes de performances causés par le déclenchement de l'animation plusieurs fois sur une courte période de temps

2. Implémenter la fonction d'étranglement et la fonction anti-secousse

Implémentation de la fonction anti-shake :

function debounce(fn, wait) {
  var timer = null;

  return function() {
    var context = this,
      args = [...arguments];

    // 如果此时存在定时器的话,则取消之前的定时器重新记时
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }

    // 设置定时器,使事件间隔指定事件后执行
    timer = setTimeout(() => {
      fn.apply(context, args);
    }, wait);
  };
}

Implémentation de la limitation des fonctions :

// 时间戳版
function throttle(fn, delay) {
  var preTime = Date.now();

  return function() {
    var context = this,
      args = [...arguments],
      nowTime = Date.now();

    // 如果两次时间间隔超过了指定时间,则执行函数。
    if (nowTime - preTime >= delay) {
      preTime = Date.now();
      return fn.apply(context, args);
    }
  };
}

// 定时器版
function throttle (fun, wait){
  let timeout = null
  return function(){
    let context = this
    let args = [...arguments]
    if(!timeout){
      timeout = setTimeout(() => {
        fun.apply(context, args)
        timeout = null 
      }, wait)
    }
  }
}

5. Optimisation des images

1. Comment optimiser les images du projet ?

  1. Aucune photo nécessaire. Souvent, de nombreuses images modifiées sont utilisées. En fait, ces images modifiées peuvent être remplacées par CSS.
  2. Pour les appareils mobiles, la largeur de l’écran est très petite, il n’est donc pas nécessaire de gaspiller de la bande passante en chargeant l’image originale. Généralement, les images sont chargées à l'aide de CDN, qui peut calculer la largeur pour s'adapter à l'écran, puis demander l'image recadrée correspondante.
  3. Les petites images utilisent le format base64
  4. Consolider plusieurs fichiers d'icônes en une seule image (image Sprite)
  5. Choisissez le bon format d'image :
    • Pour les navigateurs pouvant afficher le format WebP, essayez d'utiliser le format WebP. Étant donné que le format WebP dispose d'un meilleur algorithme de compression des données d'image, il peut réduire la taille de l'image et sa qualité d'image est indiscernable à l'œil nu. L'inconvénient est que la compatibilité n'est pas bonne.
    • Les petites images utilisent PNG. En fait, pour la plupart des icônes et autres images, SVG peut être utilisé à la place.
    • Photos utilisant JPEG

2. Formats d'image courants et scénarios d'utilisation

(1) BMP est un bitmap sans perte qui prend en charge les couleurs indexées et directes. Ce format d'image n'effectue pratiquement aucune compression de données, les images au format BMP sont donc généralement des fichiers plus volumineux.

(2) GIF est un bitmap sans perte utilisant des couleurs indexées. Codé à l'aide de l'algorithme de compression LZW. La petite taille du fichier est l'avantage du format GIF. En même temps, le format GIF présente également l'avantage de prendre en charge l'animation et la transparence. Cependant, le format GIF ne prend en charge que les couleurs indexées sur 8 bits. Il convient donc aux scènes qui n'ont pas d'exigences de couleurs élevées et nécessitent une petite taille de fichier.

(3) JPEG est un bitmap en couleur directe avec perte. L'avantage des images JPEG est qu'elles utilisent des couleurs directes. Grâce à des couleurs plus riches, JPEG est très approprié pour le stockage de photos. Par rapport au GIF, JPEG n'est pas adapté pour stocker des logos d'entreprise et des images filaires. Parce que la compression avec perte rendra l'image floue et la sélection de couleurs directes rendra le fichier image plus grand que le GIF.

(4) PNG-8 est un bitmap sans perte utilisant des couleurs indexées. PNG est un format d'image relativement nouveau et PNG-8 est un très bon substitut au format GIF. Lorsque cela est possible, PNG-8 doit être utilisé à la place de GIF, car sous le même effet d'image, PNG-8 a une taille de fichier plus petite. De plus, PNG-8 prend également en charge l’ajustement de la transparence, contrairement au GIF. À moins que la prise en charge de l'animation ne soit requise, il n'y a aucune raison d'utiliser GIF au lieu de PNG-8.

(5) PNG-24 est un bitmap sans perte utilisant la couleur directe. L'avantage du PNG-24 est qu'il compresse les données de l'image, ce qui rend la taille du fichier au format PNG-24 beaucoup plus petite que celle du BMP pour le même effet. Bien entendu, les images PNG24 sont toujours beaucoup plus grandes que les images JPEG, GIF et PNG-8.

(6) SVG est une image vectorielle sans perte. SVG est un graphique vectoriel signifiant qu'une image SVG est constituée de lignes droites et de courbes et d'une méthode pour les dessiner. Lorsque vous zoomez sur une image SVG, vous voyez toujours des lignes et des courbes, mais aucun pixel. Cela signifie que les images SVG ne seront pas déformées lorsqu'elles sont agrandies, elles sont donc très adaptées pour dessiner des logos, des icônes, etc.

(7) WebP est un nouveau format d'image développé par Google. WebP est un bitmap qui prend en charge la compression avec et sans perte et utilise la couleur directe. Son nom montre qu'il est né pour le Web. Que signifie être né pour le Web ? Autrement dit, pour des images de même qualité, WebP a une taille de fichier plus petite. De nos jours, les sites Web sont remplis d'un grand nombre d'images. Si la taille du fichier de chaque image peut être réduite, la quantité de données transmises entre le navigateur et le serveur sera considérablement réduite, réduisant ainsi le délai d'accès et améliorant l'expérience d'accès. Actuellement, seuls les navigateurs Chrome et Opera prennent en charge le format WebP, et la compatibilité n'est pas très bonne.

  • Dans le cas d'une compression sans perte, la taille du fichier des images WebP de même qualité est 26 % plus petite que celle du PNG ;
  • Dans le cas d'une compression avec perte, la taille du fichier des images WebP avec la même précision d'image est de 25 à 34 % plus petite que celle du JPEG ;
  • Le format d'image WebP prend en charge la transparence de l'image. Une image WebP compressée sans perte ne nécessite que 22 % de la taille du fichier supplémentaire pour prendre en charge la transparence.

6. Optimisation du pack Web

1. Comment améliorer la vitesse de packaging du webpack ?

(1) Optimiser le chargeur

Pour Loader, c’est Babel qui doit supporter le plus gros de l’impact sur l’efficacité de l’emballage. Parce que Babel convertira le code en chaîne pour générer un AST, puis continuera à transformer l'AST et enfin générera un nouveau code. Plus le projet est grand, plus il y aura de code converti et plus l'efficacité sera faible . Bien entendu, cela peut être optimisé.

Tout d’abord, nous optimisons la plage de recherche de fichiers de Loader

module.exports = {
  module: {
    rules: [
      {
        // js 文件才使用 babel
        test: /\.js$/,
        loader: 'babel-loader',
        // 只在 src 文件夹下查找
        include: [resolve('src')],
        // 不会去查找的路径
        exclude: /node_modules/
      }
    ]
  }
}

Pour Babel, j'espère que cela ne fonctionne que sur le code JS et que node_modulesle code utilisé est compilé, il n'est donc pas nécessaire de le traiter à nouveau.

Bien sûr, cela ne suffit pas. Vous pouvez également mettre en cache les fichiers compilés par Babel . La prochaine fois, il vous suffira de compiler les fichiers de code modifiés, ce qui peut considérablement accélérer le temps de packaging.

loader: 'babel-loader?cacheDirectory=true'

(2)HappyPack

Étant donné que Node est exécuté dans un seul thread, Webpack est également monothread pendant le processus d'empaquetage. Surtout lors de l'exécution du Loader, il existe de nombreuses tâches de compilation à long terme, ce qui entraînera une attente.

HappyPack peut convertir l'exécution synchrone de Loader en parallèle , afin que les ressources du système puissent être pleinement utilisées pour accélérer l'efficacité de l'empaquetage.

module: {
  loaders: [
    {
      test: /\.js$/,
      include: [resolve('src')],
      exclude: /node_modules/,
      // id 后面的内容对应下面
      loader: 'happypack/loader?id=happybabel'
    }
  ]
},
plugins: [
  new HappyPack({
    id: 'happybabel',
    loaders: ['babel-loader?cacheDirectory'],
    // 开启 4 个线程
    threads: 4
  })
]

(3)DllPlugin

DllPlugin peut empaqueter des bibliothèques de classes spécifiques à l'avance, puis les introduire . Cette méthode peut réduire considérablement le nombre de fois où la bibliothèque de classes est empaquetée. Ce n'est que lorsque la bibliothèque de classes est mise à jour qu'elle doit être reconditionnée, et elle réalise également la solution d'optimisation consistant à extraire le code public dans des fichiers séparés. Comment utiliser DllPlugin est le suivant :

// 单独配置在一个文件中
// webpack.dll.conf.js
const path = require('path')
const webpack = require('webpack')
module.exports = {
  entry: {
    // 想统一打包的类库
    vendor: ['react']
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].dll.js',
    library: '[name]-[hash]'
  },
  plugins: [
    new webpack.DllPlugin({
      // name 必须和 output.library 一致
      name: '[name]-[hash]',
      // 该属性需要与 DllReferencePlugin 中一致
      context: __dirname,
      path: path.join(__dirname, 'dist', '[name]-manifest.json')
    })
  ]
}

Ensuite, vous devez exécuter ce fichier de configuration pour générer des fichiers de dépendances, puis vous devez DllReferencePluginintroduire les fichiers de dépendances dans le projet en utilisant

// webpack.conf.js
module.exports = {
  // ...省略其他配置
  plugins: [
    new webpack.DllReferencePlugin({
      context: __dirname,
      // manifest 就是之前打包出来的 json 文件
      manifest: require('./dist/vendor-manifest.json'),
    })
  ]
}

(4) Compression des codes

Dans Webpack3, il est généralement utilisé UglifyJSpour compresser le code, mais cela est exécuté dans un seul thread. Afin d'accélérer l'efficacité, vous pouvez utiliser webpack-parallel-uglify-pluginto run in parallel UglifyJS, améliorant ainsi l'efficacité.

Dans Webpack4, ces opérations ne sont plus nécessaires, il vous suffit de modedéfinir sur productionpour activer les fonctions ci-dessus par défaut. La compression de code est également une solution d'optimisation des performances incontournable pour nous. Bien sûr, nous pouvons non seulement compresser le code JS, mais également le code HTML et CSS. Dans le processus de compression du code JS, nous pouvons également implémenter des fonctions telles que la suppression de ce code via la configuration console.log.

(5) Autres

La vitesse de packaging peut être accélérée grâce à quelques petits points d'optimisation

  • resolve.extensions : Utilisé pour indiquer la liste des suffixes de fichiers. L'ordre de recherche par défaut est ['.js', '.json']. Si votre fichier importé n'ajoute pas de suffixe, les fichiers seront recherchés dans cet ordre. Nous devrions réduire autant que possible la longueur de la liste des suffixes, puis classer les suffixes les plus fréquents au début.
  • resolve.alias: Vous pouvez tracer un chemin via un alias, permettant à Webpack de trouver le chemin plus rapidement.
  • module.noParse: Si vous êtes sûr qu'il n'y a pas d'autres dépendances sous un fichier, vous pouvez utiliser cet attribut pour empêcher Webpack d'analyser le fichier. Cette méthode est très utile pour les grandes bibliothèques de classes.

2. Comment réduire la taille de l'emballage Webpack

(1) Chargement sur demande

Lors du développement d'un projet SPA, il y aura de nombreuses pages de routage dans le projet. Si toutes ces pages sont regroupées dans un seul fichier JS, même si plusieurs requêtes sont fusionnées, beaucoup de code inutile sera également chargé, ce qui prendra plus de temps. Afin que la page d'accueil soit présentée plus rapidement aux utilisateurs, nous espérons que la taille du fichier pouvant être chargé sur la page d'accueil soit aussi petite que possible. À l'heure actuelle, vous pouvez utiliser le chargement à la demande pour empaqueter chaque routage page dans un fichier séparé . Bien entendu, non seulement les routes peuvent être chargées à la demande, mais loadashcette fonction peut également être utilisée pour des bibliothèques de classes aussi volumineuses.

L'implémentation du code du chargement à la demande ne sera pas abordée en détail ici, car l'implémentation est différente en raison des différents frameworks utilisés. Bien entendu, même si leur utilisation peut être différente, le mécanisme sous-jacent est le même. Lorsqu'il est utilisé, le fichier correspondant est téléchargé et un autre est renvoyé Promise. En cas Promisede succès, le rappel est exécuté.

(2)Levage de la portée

Scope Hoisting analysera les dépendances entre les modules et fusionnera autant que possible les modules packagés en une seule fonction.

Par exemple, si vous souhaitez empaqueter deux fichiers :

// test.js
export const a = 1
// index.js
import { a } from './test.js'

Dans ce cas, le code packagé ressemblera à ceci :

[
  /* 0 */
  function (module, exports, require) {
    //...
  },
  /* 1 */
  function (module, exports, require) {
    //...
  }
]

Mais si vous utilisez Scope Hoisting, le code sera fusionné dans une fonction autant que possible, et il deviendra similaire à ce code :

[
  /* 0 */
  function (module, exports, require) {
    //...
  }
]

Le code généré par cette méthode de packaging est évidemment bien moindre qu'avant. Si vous souhaitez activer cette fonctionnalité dans Webpack 4, activez- optimization.concatenateModulesla simplement :

module.exports = {
  optimization: {
    concatenateModules: true
  }
}

(3)Secousse des arbres

Tree Shaking peut supprimer du code non référencé dans le projet , tel que :

// test.js
export const a = 1
export const b = 2
// index.js
import { a } from './test.js'

Pour la situation ci-dessus, testles variables du fichier bne seront pas regroupées dans le fichier si elles ne sont pas utilisées dans le projet.

Si vous utilisez Webpack 4, cette fonction d'optimisation sera automatiquement activée lorsque vous ouvrirez l'environnement de production.

3. Comment utiliser Webpack pour optimiser les performances front-end ?

Utiliser Webpack pour optimiser les performances frontales signifie optimiser la sortie de Webpack afin que le résultat final emballé s'exécute rapidement et efficacement dans le navigateur.

  • Compresser le code : supprimer le code redondant, les commentaires, simplifier l'écriture du code, etc. Vous pouvez utiliser UglifyJsPlugin et ParallelUglifyPlugin de webpack pour compresser les fichiers JS et utiliser cssnano (css-loader?minimize) pour compresser les CSS.
  • Utiliser l'accélération CDN : pendant le processus de construction, modifiez le chemin de ressource statique référencé par le chemin correspondant sur le CDN. Vous pouvez utiliser le paramètre de sortie de webpack et le paramètre publicPath de chaque chargeur pour modifier le chemin de la ressource.
  • Tree Shaking : supprimez les sections de code qui ne seront jamais vues. Ceci peut être réalisé en ajoutant le paramètre --optimize-minimize lors du démarrage de Webpack
  • Fractionnement du code : divisez le code en morceaux en fonction des dimensions ou des composants de routage, afin qu'il puisse être chargé à la demande et que le cache du navigateur puisse être pleinement utilisé.
  • Extraire les bibliothèques publiques tierces : plug-in SplitChunksPlugin pour extraire les modules publics et utiliser le cache du navigateur pour mettre en cache ces codes publics qui n'ont pas besoin d'être modifiés fréquemment pendant une longue période.

4. Comment améliorer la vitesse de construction du webpack ?

  1. Dans le cas d'entrées multiples, utilisez CommonsChunkPlugin pour extraire le code commun
  2. Extraire les bibliothèques communes via une configuration externe
  3. Utilisez les modules de ressources précompilés DllPlugin et DllReferencePlugin pour précompiler les packages npm que nous référençons mais que nous ne modifierons jamais via DllPlugin, puis chargez les modules précompilés via DllReferencePlugin.
  4. Utilisez Happypack pour réaliser une compilation accélérée multithread
  5. Utilisez webpack-uglify-parallel pour améliorer la vitesse de compression d'uglifyPlugin. En principe, webpack-uglify-parallel utilise la compression parallèle multicœur pour améliorer la vitesse de compression.
    Le paramètre publicPath du chargeur est utilisé pour modifier le chemin des ressources.
  • Tree Shaking : supprimez les sections de code qui ne seront jamais vues. Ceci peut être réalisé en ajoutant le paramètre --optimize-minimize lors du démarrage de Webpack
  • Fractionnement du code : divisez le code en morceaux en fonction des dimensions ou des composants de routage, afin qu'il puisse être chargé à la demande et que le cache du navigateur puisse être pleinement utilisé.
  • Extraire les bibliothèques publiques tierces : plug-in SplitChunksPlugin pour extraire les modules publics et utiliser le cache du navigateur pour mettre en cache ces codes publics qui n'ont pas besoin d'être modifiés fréquemment pendant une longue période.

4. Comment améliorer la vitesse de construction du webpack ?

  1. Dans le cas d'entrées multiples, utilisez CommonsChunkPlugin pour extraire le code commun
  2. Extraire les bibliothèques communes via une configuration externe
  3. Utilisez les modules de ressources précompilés DllPlugin et DllReferencePlugin pour précompiler les packages npm que nous référençons mais que nous ne modifierons jamais via DllPlugin, puis chargez les modules précompilés via DllReferencePlugin.
  4. Utilisez Happypack pour réaliser une compilation accélérée multithread
  5. Utilisez webpack-uglify-parallel pour améliorer la vitesse de compression d'uglifyPlugin. En principe, webpack-uglify-parallel utilise la compression parallèle multicœur pour améliorer la vitesse de compression.
  6. Utilisez Tree-shaking et Scope Hoisting pour éliminer le code redondant

Acho que você gosta

Origin blog.csdn.net/m0_46374969/article/details/132455539
Recomendado
Clasificación