Scripts attach behavior: <script> either references external files or embeds source inline. Placement and attributes determine blocking behavior.
Classic scripts
defer: download in parallel, execute after HTML parsing in order.async: download in parallel, execute as soon as ready (order not preserved among async siblings).- No attribute: fetch and execute immediately, blocking parsing unless deferred by browser heuristics.
Modules
<script type="module" src="/app.js"></script>
ES modules defer by default and run in strict mode. Use nomodule fallbacks only when supporting obsolete browsers.
noscript
Provides alternate content when scripting is disabled—still ensure critical information appears in HTML even when scripts run.
Progressive enhancement
- Ship readable markup first.
- Layer JS for enhanced UX.
- Avoid hard dependency on script-rendered text for SEO.
Where teams lose hours
- Mixed scripts: some defer, some async—race conditions flip depending on caching; document script graph.
- Libraries expecting specific insertion order violating CSP nonces/hash strategies—coordinate build pipeline.
- Third-party snippets injected late blocking render—defer and measure RUM.
Modules vs classic
type="module" files defer implicitly; forgetting that changes execution order versus legacy bundles—migrate gradually with explicit deps.
noscript fallback markup
<script defer src="/app.js"></script>
<noscript>
<p>This experience requires JavaScript. <a href="/lite">Use the lite version</a>.</p>
</noscript>
Users with extensions may still execute JS—provide essential content in HTML regardless.
Important interview questions and answers
- Q: What is the practical difference between `id` and `class`?
A: `id` must be unique and is used for fragments/labeling; `class` is reusable for styling and behavior grouping. - Q: Why is `defer` commonly preferred for scripts?
A: It preserves HTML parsing, executes after parse, and avoids blocking rendering unlike classic synchronous scripts. - Q: How do `srcset` and `sizes` work together?
A: `srcset` provides candidate files and `sizes` tells expected rendered width so the browser can pick an optimal resource.
Next: Prefer defer on external scripts; avoid blocking parsing when possible.