**`<script>`** either contains inline JavaScript directly between its tags, or points to an external file via **`src`**. By default, a script blocks HTML parsing while it downloads and runs. Two attributes change that: **`defer`** downloads the script in the background and runs it only after the HTML is fully parsed (in document order, if multiple), while **`async`** downloads in the background too but runs it AS SOON AS it's ready, potentially interrupting parsing and out of order relative to other scripts. Modern JavaScript modules use `type="module"`, which is deferred by default.
1Understanding <script>
`<script>` either contains inline JavaScript directly between its tags, or points to an external file via `src`. By default, a script blocks HTML parsing while it downloads and runs. Two attributes change that: `defer` downloads the script in the background and runs it only after the HTML is fully parsed (in document order, if multiple), while `async` downloads in the background too but runs it AS SOON AS it's ready, potentially interrupting parsing and out of order relative to other scripts. Modern JavaScript modules use type="module", which is deferred by default.
For most cases, defer is the safer default: your script runs after the DOM is fully built, and multiple deferred scripts still execute in the order they appear in the HTML.
<head>
<script src="/main.js" defer></script>
</head>
<body>
<button id="btn">Click me</button>
</body>2Practical Example
Here is a real-world application of <script> showing how it is used in production HTML.
<!-- Loading an ES module -->
<script type="module">
import { greet } from './greet.js';
greet('World');
</script>3Best Practices
Follow these guidelines when working with <script>:
1. Use defer for scripts that need the full DOM or must run in a predictable order
2. Use async only for independent scripts with no dependency on DOM order (e.g. some analytics snippets)
3. Use type="module" for modern ES module JavaScript, which is deferred by default and supports import/export
Tip: For most cases, defer is the safer default: your script runs after the DOM is fully built, and multiple deferred scripts still execute in the order they appear in the HTML.
<head>
<script src="/main.js" defer></script>
</head>
<body>
<button id="btn">Click me</button>
</body>