Le chargement de ressources JavaScript volumineuses a un impact important sur la vitesse des pages. Division... votre JavaScript en fragments plus petits et ne télécharger que ce qui est nécessaire pour qu'une page fonctionne au démarrage peut considérablement améliorer le chargement de votre page la réactivité, ce qui peut améliorer le nombre d'interactions avec les éléments suivants de votre page ; Peinture (INP).
Lorsqu'une page télécharge, analyse et compile des fichiers JavaScript volumineux, elle peut devenir qui ne répondent pas pendant certaines périodes. Les éléments de la page sont visibles, fait partie du code HTML initial d'une page avec un style CSS. Toutefois, comme le code JavaScript nécessaires pour alimenter ces éléments interactifs, ainsi que d'autres scripts chargés par la page, peuvent analyser et exécuter le code JavaScript pour qu'ils fonctionnent. La l'utilisateur peut avoir l'impression que l'interaction était significative retardés, voire complètement cassés.
Cela se produit souvent parce que le thread principal est bloqué pendant l'analyse du code JavaScript. et compilées sur le thread principal. Si ce processus prend trop de temps, il est possible que certains éléments de la page ne répondent pas assez rapidement aux entrées utilisateur. Une solution pour éviter cela consiste à ne charger que le code JavaScript nécessaire au fonctionnement de la page, tandis que reportant le chargement d'autres éléments JavaScript par la suite à l'aide d'une technique connue sous le nom de code le fractionnement. Ce module se concentre sur la dernière de ces deux techniques.
Réduire l'analyse et l'exécution JavaScript au démarrage grâce au fractionnement du code
Lighthouse génère un avertissement lorsque l'exécution de JavaScript prend plus de secondes et échoue lorsqu'elle prend plus de 3, 5 secondes. Utilisation excessive de JavaScript l'analyse et l'exécution constituent un problème potentiel à n'importe quel point de la page. car il peut augmenter le délai d'entrée d'une interaction. si le moment où l'utilisateur interagit avec la page coïncide avec le moment les principales tâches des threads responsables du traitement et de l'exécution de JavaScript sont en cours d'exécution.
En outre, l'exécution et l'analyse excessives de JavaScript sont particulièrement lors du chargement initial de la page, car il s'agit du point de la page cycle de vie que les utilisateurs sont très susceptibles d’interagir avec la page. En fait, Le temps de blocage total (TBT), qui est une métrique de réactivité de chargement, est fortement corrélé. avec INP, ce qui suggère que les utilisateurs ont une forte tendance à tenter d'interagir lors du chargement initial de la page.
L'audit Lighthouse qui indique le temps passé à exécuter chaque fichier JavaScript que les demandes de page sont utiles, car elles peuvent vous aider à identifier les scripts peuvent être candidats à la scission du code. Vous pouvez ensuite aller plus loin en à l'aide de l'outil de couverture disponible dans les outils pour les développeurs Chrome afin d'identifier le code JavaScript d'une page n'est plus utilisé lors de son chargement.
Le fractionnement de code est une technique utile qui permet de réduire le code JavaScript initial d'une page. charges utiles. Il vous permet de diviser un bundle JavaScript en deux parties:
- Le code JavaScript requis au chargement de la page et ne peut donc être chargé à aucun autre moment en temps réel.
- JavaScript restant pouvant être chargé ultérieurement, le plus souvent au moment où l'utilisateur interagit avec un élément interactif donné sur la page.
Le fractionnement du code peut être effectué à l'aide de la syntaxe import()
dynamique. Ce
contrairement aux éléments <script>
, qui demandent une ressource JavaScript donnée.
Au démarrage : demande une ressource JavaScript ultérieurement
tout au long du cycle de vie de la page.
document.querySelectorAll('#myForm input').addEventListener('blur', async () => {
// Get the form validation named export from the module through destructuring:
const { validateForm } = await import('/validate-form.mjs');
// Validate the form:
validateForm();
}, { once: true });
Dans l'extrait JavaScript précédent, le module validate-form.mjs
est
téléchargée, analysée et exécutée uniquement lorsqu'un utilisateur floute l'une des
<input>
. Dans ce cas, la ressource JavaScript chargée de
qui pilote la logique de validation du formulaire n'intervient sur la page que lorsqu'elle
a plus de chances d'être réellement utilisée.
Les bundles JavaScript tels que webpack, Parcel, Rollup et esbuild peuvent être
configurés pour diviser les groupes JavaScript en fragments plus petits chaque fois qu'ils
un appel import()
dynamique dans votre code source s'affiche. La plupart de ces outils
automatiquement. Toutefois, pour créer des versions en particulier, vous devez l'activer
l'optimisation.
Remarques utiles sur le fractionnement du code
Bien que le fractionnement du code soit une méthode efficace pour réduire les conflits dans le thread principal lors du chargement initial de la page, gardez à l'esprit quelques points si vous décidez pour identifier les opportunités de fractionnement du code dans votre code source JavaScript.
Si possible, utilisez un bundler
Les développeurs utilisent souvent des modules JavaScript pendant le de développement d'applications. C'est une excellente amélioration de l'expérience développeur améliore la lisibilité et la gestion du code. Cependant, certaines les caractéristiques de performance non optimales qui peuvent se produire lors de l'envoi de code JavaScript modules en production.
Surtout, vous devez utiliser un bundler pour traiter et optimiser votre source. du code, y compris les modules que vous souhaitez diviser. Les Bundlers sont très efficaces des optimisations au code source JavaScript, mais aussi est très efficace pour équilibrer les considérations de performances, telles que la taille du bundle par rapport au taux de compression. L'efficacité de la compression augmente avec la taille du bundle. mais les bundles essaient également de s'assurer que les lots ne sont pas trop volumineux de longues tâches dues à l'évaluation de scripts.
Les fournisseurs de services de bundle évitent également d'envoyer un grand nombre de modules dégroupés.
sur le réseau. Les architectures qui utilisent des modules JavaScript
ont tendance à avoir des
les arborescences de modules complexes. Lorsque les arborescences de modules sont dégroupées, chaque module représente
une requête HTTP distincte et l'interactivité dans votre application Web peuvent être retardées
et non les modules. Bien qu'il soit possible d'utiliser le
Indice de ressource <link rel="modulepreload">
pour charger les arborescences de modules volumineux le plus tôt possible
Il est toujours préférable d'utiliser les bundles JavaScript
point de vue.
Ne pas désactiver par inadvertance la compilation en flux continu
Le moteur JavaScript V8 de Chromium offre un certain nombre d'optimisations prêtes à l'emploi pour vous assurer que votre code JavaScript de production se charge aussi efficacement que possible. L'une de ces optimisations est connue sous le nom de compilation en flux continu : l'analyse incrémentielle du code HTML transmis au navigateur et compile des blocs de JavaScript lorsqu'ils arrivent du réseau.
Il existe plusieurs façons de procéder à la compilation en flux continu pour votre application Web dans Chromium:
- Transformez votre code de production pour éviter d'utiliser des modules JavaScript. Bundlers transformer votre code source JavaScript en fonction d'une cible de compilation ; la cible est souvent spécifique à un environnement donné. V8 appliquera le streaming vers tout code JavaScript qui n'utilise pas de modules, et vous pouvez configurer votre bundler pour transformer le code de votre module JavaScript en syntaxe qui n'utilise pas les modules JavaScript et leurs fonctionnalités.
- Si vous souhaitez envoyer des modules JavaScript en production, utilisez la classe
.mjs
. Que votre code JavaScript de production utilise ou non des modules, il existe Aucun type de contenu spécial pour JavaScript utilisant des modules plutôt que JavaScript ce qui n'est pas le cas. En ce qui concerne V8, vous désactivez les flux de données lorsque vous fournissez des modules JavaScript en production à l'aide de.js
. Si vous utilisez l'extension.mjs
pour les modules JavaScript, V8 peut vous assurer que la compilation par flux du code JavaScript basé sur des modules n'est pas cassées.
Ne laissez pas ces considérations vous dissuader d'utiliser le fractionnement du code. Coder la division est un moyen efficace de réduire les charges utiles JavaScript initiales pour les utilisateurs, mais en utilisant un bundler et en sachant comment préserver les flux de V8 de compilation, vous pouvez vous assurer que votre code JavaScript de production est aussi vite que possible pour les utilisateurs.
Démonstration de l'importation dynamique
Webpack
webpack est fourni avec un plug-in nommé SplitChunksPlugin
, qui vous permet
configurer la façon dont le bundler divise les fichiers JavaScript. webpack reconnaît à la fois
les instructions import()
dynamiques et import
statiques. Le comportement
SplitChunksPlugin
peut être modifié en spécifiant l'option chunks
dans ses
configuration:
chunks: async
est la valeur par défaut et fait référence aux appelsimport()
dynamiques.chunks: initial
fait référence à des appelsimport
statiques.chunks: all
couvre à la fois les importationsimport()
dynamiques et statiques, ce qui vous permet pour partager des fragments entre les importationsasync
etinitial
.
Par défaut, chaque fois que webpack rencontre une instruction import()
dynamique. cette
crée un bloc distinct pour ce module:
/* main.js */
// An application-specific chunk required during the initial page load:
import myFunction from './my-function.js';
myFunction('Hello world!');
// If a specific condition is met, a separate chunk is downloaded on demand,
// rather than being bundled with the initial chunk:
if (condition) {
// Assumes top-level await is available. More info:
// https://v8.dev/features/top-level-await
await import('/form-validation.js');
}
La configuration webpack par défaut pour l'extrait de code précédent génère deux résultats. des fragments distincts:
- Le fragment
main.js
, que webpack classe comme un fragmentinitial
, qui inclut les modulesmain.js
et./my-function.js
. - Le fragment
async
, qui ne comprend queform-validation.js
(avec un élément hachage de fichier dans le nom de ressource, le cas échéant). Ce fragment n'est téléchargé si et quandcondition
est truthy.
Cette configuration vous permet de reporter le chargement du fragment form-validation.js
jusqu'à
c’est réellement nécessaire. Cela peut améliorer la réactivité au chargement en réduisant les
l'évaluation lors du chargement initial de la page. Téléchargement et évaluation du script
pour le fragment form-validation.js
se produit lorsqu'une condition spécifiée est remplie,
Dans ce cas, le module importé dynamiquement est téléchargé. Il peut s'agir, par exemple,
condition où un polyfill n'est téléchargé que pour un navigateur particulier ou, comme dans
Dans l'exemple précédent, le module importé est nécessaire pour une interaction de l'utilisateur.
D'autre part, modifier la configuration SplitChunksPlugin
pour spécifier
chunks: initial
garantit que le code n'est divisé que sur les fragments initiaux. Il s'agit
des fragments tels que ceux importés de manière statique ou répertoriés dans le fichier entry
de webpack
. Si l'on considère l'exemple précédent, le fragment obtenu serait
combinaison de form-validation.js
et main.js
dans un seul fichier de script,
ce qui peut nuire aux performances
de chargement initial de la page.
Les options de SplitChunksPlugin
peuvent également être configurées pour séparer les grands
en plusieurs scripts plus petits, par exemple en utilisant l'option maxSize
.
pour demander à webpack de diviser les fragments en fichiers distincts s'ils dépassent la limite
spécifié par maxSize
. Diviser les fichiers de script volumineux en fichiers plus petits peut
améliorer la réactivité de chargement, comme dans certains cas l'évaluation de scripts nécessitant une utilisation intensive du processeur ;
le travail est divisé en tâches plus petites, qui sont moins susceptibles de bloquer
sur des périodes plus longues.
De plus, la génération de fichiers JavaScript plus volumineux signifie également que les scripts plus de risques de subir l'invalidation du cache. Par exemple, si vous livrez un contenant à la fois du code de framework et d'application propriétaire, l'intégralité Le bundle peut être invalidé si seul le framework est mis à jour, mais rien d'autre dans la ressource groupée.
D'un autre côté, des fichiers de script plus petits augmentent la probabilité qu'un retour visiteur récupère les ressources du cache, ce qui accélère le chargement des pages sur visites répétées. Cependant, la compression est moins efficace pour les fichiers de petite taille. ce qui peut augmenter le délai aller-retour du réseau pour les chargements de page le cache du navigateur. Il faut veiller à trouver un équilibre entre la mise en cache l'efficacité, l'efficacité de la compression et le temps d'évaluation du script.
<ph type="x-smartling-placeholder">démo webpack
<ph type="x-smartling-placeholder">démonstration SplitChunksPlugin
de webpack.
Tester vos connaissances
Quel type d'instruction import
est utilisé lors de l'exécution du code
le fractionnement ?
import()
dynamique.import
statique.
Quel type d'instruction import
doit se trouver en haut
d'un module JavaScript et à aucun autre emplacement ?
import()
dynamique.import
statique.
Lorsque vous utilisez SplitChunksPlugin
dans webpack, quelle est la valeur
différence entre un fragment async
et un
Fragment initial
?
async
sont chargés à l'aide d'import
statiques
et les fragments initial
sont chargés
import()
async
sont chargés à l'aide de la méthode dynamique import()
et les fragments initial
sont chargés à l'aide de fragments
import
À suivre: Images à chargement différé et éléments <iframe>
Bien qu'il s'agisse généralement d'un type de ressource relativement coûteux, JavaScript n'est pas le
seul type de ressource dont vous pouvez différer le chargement. Image et éléments <iframe>
sont des ressources potentiellement coûteuses
à part entière. Comme pour JavaScript, vous
Vous pouvez différer le chargement des images et de l'élément <iframe>
grâce au chargement différé.
les uns des autres, ce qui est expliqué dans le module suivant de ce cours.