<script src="script.js"></script>Il le télécharge et l'exécute, puis continue de parser le HTML.
Si le script est très volumineux ou le réseau un peu lent, la page restera blanche jusqu'à ce que le script soit chargé et exécuté.
1re solution mettre le script en bas de la page, pour que tout le HTML soit chargé avant de charger le JS.
2e solution L'attribut async force à télécharger le script en parallèle, puis l'exécuter avant de continuer sur le HTML: async est bloquant.
Defer télécharge en parallèle, mais n'exécute pas le script. Il l'exécute quand tout le HTML est parsé (après domInteractive). D'où le nom d'exécution différée.
En précisant les deux sur un navigateur moderne,
<script src="script.js" async defer></script>Async prend la précédence, alors qu'un navigateur plus ancien passera en defer s'il le supporte.
La meilleure façon de charger un script est donc de le mettre dans le head en defer
<script defer src="script.js"></script>