Problem when using defer
to load external script is when you have inline script that depends on the external script. This because inline script is executed immediately while deferred script is loaded after the whole page has beed parsed.
Take this script for example:-
<!doctype html>
<html>
<head>
<script>
console.log('Start ...');
</script>
<script defer src="https://unpkg.com/htmx.org@1.9.10" integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC" crossorigin="anonymous"></script>
<script>
htmx.logger = function(elt, event, data) {
if(console) {
console.log(event, elt, data);
}
}
</script>
<script>
htmx.logger("Inside head");
</script>
</head>
<body>
<h1>Javascript DOMContentLoaded</h1>
<script type="module">
htmx.logger("Inside body");
</script>
<script>
window.addEventListener('DOMContentLoaded', function() {
console.log('Inline JS');
});
</script>
</body>
</html>
The inline script will failed:-
Start ... localhost:9000:5:17
Uncaught ReferenceError: htmx is not defined
<anonymous> http://localhost:9000/:9
localhost:9000:9:5
Uncaught ReferenceError: htmx is not defined
<anonymous> http://localhost:9000/:16
localhost:9000:16:9
Uncaught TypeError: htmx.logger is not a function
<anonymous> http://localhost:9000/:23
localhost:9000:23:14
Inline JS localhost:9000:28:21
GET
http://localhost:9000/favicon.ico
[HTTP/1 404 File not found 1ms]
Fortunately script of type module is deferred automatically. This will work as expected:-
<!doctype html>
<html>
<head>
<script>
console.log('Start ...');
</script>
<script defer src="https://unpkg.com/htmx.org@1.9.10" integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC" crossorigin="anonymous"></script>
<script type="module">
htmx.logger = function(elt, event, data) {
if(console) {
console.log(event, elt, data);
}
}
</script>
<script type="module">
htmx.logger("Inside head");
</script>
</head>
<body>
<h1>Javascript DOMContentLoaded</h1>
<script type="module">
htmx.logger("Inside body");
</script>
<script>
window.addEventListener('DOMContentLoaded', function() {
console.log('Inline JS');
});
</script>
</body>
</html>
Start ... localhost:9000:5:17
undefined Inside head undefined localhost:9000:11:17
undefined Inside body undefined localhost:9000:11:17
htmx:beforeProcessNode
<body>
Object { elt: body }
localhost:9000:11:17
Inline JS localhost:9000:28:21
GET
http://localhost:9000/favicon.ico
[HTTP/1 404 File not found 1ms]
htmx:load
<body>
Object { elt: body }
localhost:9000:11:17
Browsers support is 96.81% so I think it's pretty good.
Original code taken from https://cylab.be/blog/188/defer-async-and-inline-javascript
Top comments (0)