Cos’è il rendering di una pagina web
Il rendering della pagina è il processo attraverso cui il browser trasforma il codice HTML, CSS e JavaScript in una pagina visibile e interattiva per l’utente.
Come funziona il rendering step by step
- Parsing dell’HTML – Il browser legge il file HTML e costruisce una struttura interna chiamata DOM (Document Object Model), che rappresenta gli elementi della pagina.
- Parsing del CSS – I file CSS vengono letti e trasformati in una struttura chiamata CSSOM (CSS Object Model), che definisce lo stile di ogni elemento.
- Costruzione del render tree – Il browser combina DOM e CSSOM per capire cosa deve essere disegnato e come.
- Layout – Calcola posizioni e dimensioni di tutti gli elementi (es. dove va il testo, quanto è largo un div, ecc.).
- Painting – Il browser disegna pixel sullo schermo in base al layout e agli stili.
- Compositing – Se ci sono elementi sovrapposti, animazioni o effetti, il browser li compone correttamente nel risultato finale.
Primo problema: effetti del caricamento degli script sul rendering della pagina
Abbiamo detto che, quando riceve l’HTML di una pagina, il browser inizia a leggerlo riga per riga (parsing) e a costruire il DOM, Ma cosa succede quando incontra uno <script>?
- Il browser interrompe il parsing dell’HTML.
- Scarica lo script.
- Lo esegue subito.
- Solo dopo riprende a costruire il DOM.
L’effetto sul rendering è che il caricamento della pagina viene bloccato fino al termine dell’esecuzione dello script. Se quest’ultimo è lento o pesante, l’utente vede una pagina bianca più a lungo.
Secondo problema: se posizionati nell'<head>, gli script che manipolano il DOM possono andare in errore
L’organizzazione semantica dell’HTML prevede che i file CSS egli script vengano inseriti all’interno dell’elemento <head>.
Per quanto riguarda il CSS questo posizionamento è obbligatorio: i fogli di stile devono essere caricati prima del rendering, allo scopo di evitare che l’utente veda un “flash” di contenuto non stilizzato (FOUC).
Per quanto riguarda gli script inseriti nell’<head>, oltre al già citato problema di interruzione del rendering della pagina, esiste anche il problema che il DOM non è ancora stato creato e se lo script cerca di manipolare il DOM (ad esempio per aggiungere o togliere una classe CSS ad un elemento) potrebbe andare in errore.
Le possibili soluzioni a questi due problemi
1. Spostare gli script al termine della pagina
Ad esempio dopo la chiusura del footer (</footer>) o del body (</body>). I problemi vengono entrambi risolti ed infatti questa soluzione è ampiamente utilizzata, non mi sento di suggerirla perché contravviene alle regole semantiche dell’HTML.
Tutte le soluzioni successive prevedono pertanto di lasciare gli script nell’<head>.
2. Ritardare l’esecuzione degli script
E’ possibile vincolare l’esecuzione di uno script al termine del caricamento del DOM. Questo risultato si ottiene inserendo lo script all’interno dell’evento DOMContentLoaded:
document.addEventListener('DOMContentLoaded', function () {
// Il DOM è pronto, si può eseguire il codice
});
Se si utilizza jQuery, lo stesso risutato si ottiene tramite il seguente codice:
$(document).ready(function () {
// Il DOM è pronto, si può eseguire il codice
});
oppure attraverso la scorciatoia equivalente (e più diffusa):
$(function () {
// Il DOM è pronto, si può eseguire il codice
});
Questa soluzione, però, risolve solo il secondo problema e può essere utilizzata solo se lo script è semplice e non blocca in modo significativo il rendering.
Questa soluzione può inoltre essere utilizzata nel caso di script interni all’HTML.
Ritardare ulteriormente l’esecuzione dello script
Abbiamo visto che è possibile vincolare l’esecuzione dello script all’evento DOMContentLoaded, ovvero quando il DOM è completamente caricato. Quando questo evento viene attivato, però, alcuni elementi non sono ancora stati caricati nella pagina, si tratta di immagini, video, iframe.
Per attivare uno script solo dopo che tutti i contenuti della la pagina sono stati caricati (e non solo il DOM), si deve utilizzare window.onload:
window.onload = function () {
// Tutto è pronto: DOM + immagini + media
};
3. Usare l’attributo async (script esterni)
<script src="script.js" async>
Se si aggiunge l’attributo async all’elemento HTML <script>, si ottengono questi risultati:
- Il browser scarica lo script in parallelo (ovvero non interrompe il parsing).
- Lo esegue appena è pronto, anche se il DOM non è ancora completo.
Questa soluzione non interrompe il parsing, ma non risolve il problema della dipendenza dello script da elementi HTML non ancora inseriti nel DOM. Inoltre l’ordine di esecuzione non è garantito se ci sono più script async.
Questa soluzione perciò può essere utilizzata solo per script indipendenti (es. analytics, pubblicità).
4. Usare l’attributo defer (script esterni)
<script src="script.js" defer>
Se si aggiunge l’attributo defer all’elemento HTML <script>, si ottengono questi risultati:
- Il browser scarica lo script in parallelo al parsing dell’HTML (così come faceva il parametro async).
- Ma rimanda l’esecuzione fino a quando il DOM è completamente costruito (al completamento del parsing di tutto il documento HTML, ma prima dell’evento
DOMContentLoaded).
In questo modo: Il DOM viene costruito senza interruzioni; gli script vengono eseguiti solo quando il DOM è pronto; l’ordine di esecuzione è garantito (rispetta l’ordine in cui gli script compaiono nel codice HTML). Questa soluzione è quindi quella ottimale per gli script esterni.
Risorse online
- developer.mozilla.org <script>: The Script element
- www.w3.org HTML5: Edition for Web Authors – 4.3.1 The
scriptelement

0 commenti