Skip to content

<script> - JavaScript Embedding Element

Scripting HTML5

The <script> element is used to embed or reference executable code, typically JavaScript. It’s the fundamental way to add interactivity, dynamic behavior, and application logic to web pages. Understanding script loading strategies is crucial for optimal performance and user experience.

Result
<!-- Inline script -->
<script>
// JavaScript code here
</script>
<!-- External script -->
<script src="path/to/file.js"></script>
<!-- ES Module -->
<script type="module" src="path/to/module.js"></script>
AttributeValueDescription
srcURLPath to external script file
typeMIME typetext/javascript (default), module, or importmap
asyncBooleanDownload asynchronously, execute when ready
deferBooleanDownload asynchronously, execute after parsing
crossoriginanonymous/use-credentialsCORS mode for cross-origin requests
integrityHashSubresource Integrity hash for security
nomoduleBooleanExecute only in browsers that don’t support modules
referrerpolicyPolicyHow much referrer information to send

The <script> element supports all global attributes.

async vs defer vs Default (CRITICAL UNDERSTANDING)

Section titled “async vs defer vs Default (CRITICAL UNDERSTANDING)”

Understanding script loading strategies is essential for performance:

DEFAULT (blocking):
HTML Parsing: ━━━━━━━━⏸️━━━━━━━━━━━━━━━━━━
Script Download: ⬇️⬇️⬇️
Script Execute: ⚡
ASYNC:
HTML Parsing: ━━━━━━━━━━⏸️━━━━━━━━━━━━━━━
Script Download: ⬇️⬇️⬇️⬇️⬇️
Script Execute: ⚡
DEFER:
HTML Parsing: ━━━━━━━━━━━━━━━━━━━━━━━━⏸️
Script Download: ⬇️⬇️⬇️⬇️⬇️
Script Execute: ⚡
TYPE="module" (deferred by default):
HTML Parsing: ━━━━━━━━━━━━━━━━━━━━━━━━⏸️
Script Download: ⬇️⬇️⬇️⬇️⬇️
Script Execute: ⚡

Modern JavaScript with import/export syntax:

Result

SRI ensures that files from CDNs haven’t been tampered with:

Result

Controls CORS for script requests:

Result
<!DOCTYPE html>
<html>
<head>
<!-- Critical inline styles -->
<style>
/* Above-the-fold CSS */
</style>
<!-- Preconnect to external domains -->
<link rel="preconnect" href="https://cdn.example.com">
<!-- Critical JavaScript (rare) -->
<script>
// Only absolutely essential code
window.APP_CONFIG = { version: '1.0.0' };
</script>
</head>
<body>
<!-- Page content -->
<!-- Non-critical scripts at end with defer -->
<script defer src="/js/app.js"></script>
<script defer src="/js/analytics.js"></script>
</body>
</html>

Load scripts programmatically:

Result
<!-- Set CSP via meta tag -->
<meta http-equiv="Content-Security-Policy"
content="script-src 'self' https://cdn.example.com;">
<!-- Or via HTTP header (preferred) -->
<!--
Content-Security-Policy: script-src 'self' https://cdn.example.com;
-->
<!-- This will load (allowed origin) -->
<script src="https://cdn.example.com/library.js"></script>
<!-- This will be blocked (different origin) -->
<script src="https://malicious.com/script.js"></script>
<!-- Inline scripts blocked by default -->
<script>
// This won't execute without 'unsafe-inline' or nonce
console.log('Blocked!');
</script>
Result
Result
Result

Universal Support

The <script> element is supported in all browsers:

  • Basic support: All browsers
  • async/defer: All modern browsers (IE10+)
  • type=“module”: Chrome 61+, Firefox 60+, Safari 11+, Edge 16+
  • integrity (SRI): Chrome 45+, Firefox 43+, Safari 11.1+, Edge 17+
  • nomodule: Chrome 61+, Firefox 60+, Safari 11+, Edge 16+

Fallback: Use nomodule for legacy browser support.

  1. Load strategy: Use defer for most scripts, async for independent scripts
  2. Placement: Put scripts at end of <body> or use defer
  3. Use modules: Prefer type="module" for modern applications
  4. Security: Always use SRI for CDN scripts
  5. CSP: Implement Content Security Policy
  6. Performance: Minimize, bundle, and compress scripts
  7. Lazy load: Load non-critical scripts on demand
  8. Error handling: Always handle script loading errors
  9. No inline handlers: Avoid onclick etc., use addEventListener
  10. Validate inputs: Never trust user input in scripts

Learn More: