Browser Execution Process - How Browsers Run JS
Learn exactly how browsers parse, compile, and execute JavaScript, including the critical rendering path!
Introduction
What happens from when a browser receives HTML/CSS/JS to when you see the page? Let's break down the entire browser execution process step by step!
What You Will Learn
- The Critical Rendering Path
- How browsers parse HTML
- How browsers parse and execute JS
- Layout (Reflow) and Paint
- How to optimize this process
Prerequisites
The Critical Rendering Path
Here are the steps!
graph LR
A[HTML Received] --> B[Parse HTML DOM]
C[CSS Received] --> D[Parse CSS CSSOM]
B --> E[Combine DOM + CSSOM]
D --> E
E --> F[Render Tree]
F --> G[Layout Reflow Calculate positions/sizes]
G --> H[Paint Pixels to screen]
Step 1: Parsing HTML to DOM
The browser starts parsing HTML to build the Document Object Model (DOM)!
<!DOCTYPE html>
<html>
<head><title>Hi</title></head>
<body><p>Hello!</p></body>
</html>
DOM Tree:
html
├── head
│ └── title
│ └── "Hi"
└── body
└── p
└── "Hello!"
Step 2: Parsing CSS to CSSOM
Similarly, browser parses CSS into CSS Object Model (CSSOM)!
body { font-size: 16px; }
p { color: blue; }
CSSOM Tree:
body (font-size: 16px)
└── p (color: blue)
Step 3: JavaScript Execution - The Parser-Blocker!
JavaScript execution is parser-blocking and render-blocking! When the HTML parser hits a <script> tag:
- It stops parsing HTML
- It downloads the JS file (if external)
- It executes the JS (which can modify DOM/CSSOM!)
- Then continues parsing!
Why? Because JS can modify the DOM!
<p>First!</p>
<script>
document.write('<p>JS inserted!</p>');
</script>
<p>Second!</p>
Step 4: Render Tree
Combine DOM and CSSOM to make the Render Tree - only visible elements! (No <head>, display: none elements)
Step 5: Layout (Reflow)
The browser calculates exact positions and sizes of every element!
Step 6: Paint
The browser actually paints pixels to the screen - colors, images, text, shadows, etc.
How to Optimize
- Put
<script>at end of<body>: Let HTML/CSS load first! - Use
async/deferon scripts:<script async src="analytics.js"></script> <!-- Runs when downloaded, doesn't block --> <script defer src="app.js"></script> <!-- Runs after HTML is parsed --> - Minify and compress files: Smaller files = faster download!
- Inline critical CSS: Avoid render-blocking requests!
- Avoid layout thrashing: Don't read layout then write repeatedly!
Visualizing the Whole Process
graph TB
subgraph "Network"
A1[HTML Request]
A2[CSS Request]
A3[JS Request]
end
subgraph "Parsing"
B1[Parse HTML DOM]
B2[Parse CSS CSSOM]
end
subgraph "Execution"
C1[Execute JS]
end
subgraph "Rendering"
D1[Render Tree]
D2[Layout Reflow]
D3[Paint]
end
A1 --> B1
A2 --> B2
A3 --> C1
B1 --> D1
B2 --> D1
C1 --> D1
D1 --> D2
D2 --> D3
D3 --> E[Page Visible!]
Code Examples: Bad vs Good
Bad (Script in Head, Blocking)
<!DOCTYPE html>
<html>
<head>
<!-- BAD! Blocks HTML/CSS parsing! -->
<script src="app.js"></script>
<link rel="stylesheet" href="styles.css">
</head>
<body>...</body>
</html>
Good (Script at End, Defer)
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="styles.css">
</head>
<body>
...
<!-- GOOD! At end, or use defer! -->
<script src="app.js"></script>
</body>
</html>
Industry Use Cases
- E-commerce sites: Speed is crucial! Slow pages lose sales!
- SPAs (React/Vue): Need to optimize loading and re-rendering!
- News sites: Lots of content, need to load fast!
Best Practices
- Use
defer: For scripts that need DOM, execute after HTML parsed - Use
async: For independent scripts (like analytics) - Avoid
document.write(): It can erase page if used after load - Use CDNs: Serve static files faster
- Optimize images: Largest assets usually!
Common Mistakes
- Too many render-blocking scripts/styles: Head full of
<script>and<link>! - Layout thrashing: Reading and writing layout properties in a loop!
- Giant JS bundles: Split them with code splitting!
Performance Notes
Every millisecond counts! Use Lighthouse in Chrome DevTools to audit performance!
Security Notes
- Only load trusted scripts!
- Use
integrityhash for external scripts:<script integrity="sha256-..." src="..."> - Content Security Policy (CSP) headers prevent XSS!
SEO Notes
Fast pages rank better! Optimize the critical rendering path for better SEO!
FAQs
Q: Why is JS render-blocking? A: Because JS can modify the DOM/CSSOM! Browser needs to run it first to get correct page!
Q: What's the difference between async and defer? A: Async runs as soon as downloaded (order not guaranteed), defer runs after HTML parsed (order preserved)!
Q: What is layout thrashing? A: Reading then writing layout properties repeatedly, causing browser to recalculate layout many times!
Summary
The browser execution process goes from network → parsing → JS execution → render tree → layout → paint! Optimize this for fast, smooth pages!
Related Articles
Previous Tutorial
← Client Side vs Server Side JavaScript
Next Tutorial
Let's write our first JS program! → First JavaScript Program