Key rendering path optimization principles
The Concept of Critical Rendering Path
The Critical Rendering Path (CRP) is a series of steps the browser takes to convert HTML, CSS, and JavaScript into actual pixels on the screen. Optimizing the critical rendering path can significantly improve page load speed and enhance user experience. The browser's page rendering process mainly includes the following stages:
- DOM Tree Construction: Parsing the HTML document to build the Document Object Model (DOM).
- CSSOM Tree Construction: Parsing CSS stylesheets to build the CSS Object Model (CSSOM).
- Render Tree Construction: Combining the DOM and CSSOM to form the render tree.
- Layout: Calculating the geometric information of each render object.
- Paint: Converting the render tree into actual pixels on the screen.
Optimizing DOM Construction
DOM construction is the first step in the rendering path. Optimizing the DOM structure can speed up parsing:
<!-- Not recommended -->
<div>
<div>
<div>
<p>Deeply nested structure</p>
</div>
</div>
</div>
<!-- Recommended flat structure -->
<div>
<p>Flatter structure is easier to parse</p>
</div>
Optimization suggestions:
- Reduce the number of DOM nodes.
- Avoid deep nesting.
- Use semantic tags.
- Remove unnecessary comments and whitespace characters.
Optimizing CSSOM Construction
CSSOM construction blocks rendering, so optimizing CSS loading is crucial:
/* Avoid @import, as it adds round trips to the critical path */
@import url('styles.css');
/* Recommended: Use link tags to load CSS */
<link rel="stylesheet" href="styles.css">
Optimization strategies:
- Inline critical CSS into the HTML.
- Optimize with media queries:
<link rel="stylesheet" href="print.css" media="print"> <link rel="stylesheet" href="mobile.css" media="(max-width: 600px)">
- Avoid CSS expressions.
- Simplify CSS selector complexity.
JavaScript Loading Optimization
JavaScript blocks DOM construction, so special attention is needed for loading methods:
// Default script loading blocks parsing.
<script src="script.js"></script>
// Use async for asynchronous loading.
<script async src="script.js"></script>
// Use defer for deferred execution.
<script defer src="script.js"></script>
Best practices:
- Place scripts at the bottom of the body.
- Use async/defer attributes.
- Avoid
document.write
. - Use
requestIdleCallback
for non-critical tasks.
Preloading Critical Resources
Use resource hints to fetch critical resources early:
<!-- Preload critical resources -->
<link rel="preload" href="critical.css" as="style">
<link rel="preload" href="main.js" as="script">
<!-- DNS prefetching -->
<link rel="dns-prefetch" href="//cdn.example.com">
<!-- Preconnect -->
<link rel="preconnect" href="https://api.example.com">
Optimizing Font Loading
Font files can cause delays in text rendering:
/* Use font-display to control font rendering behavior */
@font-face {
font-family: 'MyFont';
src: url('myfont.woff2') format('woff2');
font-display: swap;
}
Font optimization tips:
- Use WOFF2 format.
- Subset font files.
- Preload font resources.
- Set an appropriate
font-display
strategy.
Reducing Reflows and Repaints
Layout and paint are the final stages of the rendering path and require optimization:
// Bad practice: Triggers multiple reflows.
const element = document.getElementById('animate');
element.style.width = '100px';
element.style.height = '200px';
element.style.left = '10px';
// Good practice: Use CSS classes or requestAnimationFrame.
element.classList.add('animate');
// Or
requestAnimationFrame(() => {
element.style.transform = 'translateX(100px)';
});
Optimization suggestions:
- Use
transform
andopacity
for animations. - Avoid frequent style manipulations.
- Use virtual DOM libraries.
- Batch DOM operations.
Server-Side Rendering Optimization
Server-side rendering can shorten the critical rendering path:
// Node.js server-side rendering example.
const express = require('express');
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const app = express();
app.get('/', (req, res) => {
const html = ReactDOMServer.renderToString(<App />);
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>SSR Example</title>
</head>
<body>
<div id="root">${html}</div>
<script src="client.js"></script>
</body>
</html>
`);
});
SSR optimization points:
- Stream HTML.
- Preload client-side resources.
- Serialize state.
- Code splitting.
Performance Monitoring Tools
Use tools to measure and optimize the critical rendering path:
// Use the Performance API to measure key timings.
window.addEventListener('load', () => {
const timing = performance.timing;
console.log('DOM load time:', timing.domComplete - timing.navigationStart);
console.log('Time to first byte:', timing.responseStart - timing.navigationStart);
});
Common tools:
- Chrome DevTools Performance panel.
- Lighthouse.
- WebPageTest.
- SpeedCurve.
Mobile Optimization Strategies
Special considerations for mobile devices:
<!-- Set the viewport -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Avoid 300ms click delay -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
Mobile optimization tips:
- Load images on demand.
- Use responsive images.
- Optimize touch events.
- Consider data usage limits.
Cache Strategy Optimization
Leverage caching to reduce network requests:
# Example cache headers.
Cache-Control: public, max-age=31536000, immutable
ETag: "xyz123"
Last-Modified: Wed, 21 Oct 2020 07:28:00 GMT
Cache strategies:
- Long-term caching for static resources.
- Use Service Workers.
- Version resource URLs.
- Set appropriate cache headers.
Image Optimization Techniques
Images are often the largest resources on a page:
<!-- Responsive image example -->
<picture>
<source media="(min-width: 800px)" srcset="large.jpg">
<source media="(min-width: 400px)" srcset="medium.jpg">
<img src="small.jpg" alt="Responsive image">
</picture>
Image optimization methods:
- Choose the right format (WebP/AVIF).
- Lazy-load images.
- Use
srcset
andsizes
. - Progressive JPEGs.
- Image compression.
Code Splitting and Lazy Loading
Reduce the initial code load:
// Dynamic imports for code splitting.
button.addEventListener('click', async () => {
const module = await import('./module.js');
module.doSomething();
});
// React lazy-loaded component.
const LazyComponent = React.lazy(() => import('./LazyComponent'));
Implementation methods:
- Route-level code splitting.
- Component-level lazy loading.
- Webpack
splitChunks
. - Prefetch non-critical resources.
HTTP/2 Optimization
Leverage HTTP/2 features for performance:
# Enable HTTP/2 in Nginx.
server {
listen 443 ssl http2;
server_name example.com;
...
}
HTTP/2 optimization points:
- Multiplexing.
- Server push.
- Header compression.
- Priority control.
Rendering Performance Budget
Establish performance budgets to ensure optimization:
// Example performance budget.
{
"budgets": [
{
"resourceType": "document",
"budget": 18
},
{
"resourceType": "script",
"budget": 120
},
{
"resourceType": "image",
"budget": 300
}
]
}
Budget metrics:
- Number of critical resources.
- Critical path depth.
- Total byte size.
- Time to interactivity.
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:资源缓存策略设计
下一篇:CSS选择器性能优化