Front‑End Performance Optimization: Loading‑Time and Runtime Techniques
This article explains why front‑end performance optimization is crucial for user retention and conversion, outlines loading‑time and runtime optimization categories, and provides practical techniques such as DNS prefetching, HTTP/2 adoption, resource compression, lazy loading, virtual lists, event delegation, and code‑level best practices with concrete code examples.
Why Performance Optimization Matters
Website performance directly influences user retention and conversion rates, making performance‑optimization skills an essential assessment point for front‑end developers.
Two Main Categories
Loading‑time optimization
Runtime optimization
Loading‑time Performance
Loading‑time optimization aims to make the page load faster, e.g., by reducing white‑screen time and first‑screen (first paint) time.
White‑screen Time Calculation
Placing a script before </head> allows you to capture the white‑screen duration:
<script>
new Date().getTime() - performance.timing.navigationStart
</script>First‑screen Time Calculation
Executing the same calculation inside the window.onload event yields the first‑screen time:
new Date().getTime() - performance.timing.navigationStartKey Loading Optimizations
DNS prefetching – reduce DNS lookup latency (typically 20‑120 ms).
Use HTTP/2 – benefits include multiplexing, header compression, and server push.
Reduce the number of HTTP requests.
Compress and merge files (JS, CSS, HTML, images).
Server‑side rendering.
Serve static assets via CDN.
Resource caching to avoid duplicate loads.
DNS Prefetch Implementation
Inform the browser to pre‑resolve domains using meta tags or <link rel="dns-prefetch" href="..."> :
<meta http-equiv="x-dns-prefetch-control" content="on" /> <link rel="dns-prefetch" href="http://example.com" />Note: Overusing dns‑prefetch can cause redundant DNS queries.
HTTP/2 Advantages
HTTP/2 provides faster parsing, multiplexed streams, header compression (HPACK), and optional server push, offering several times the loading speed of HTTP/1.1.
File Compression & Merging (Webpack Example)
Common webpack plugins for compression:
JS: UglifyPlugin
CSS: MiniCssExtractPlugin
HTML: HtmlWebpackPlugin
Images: image-webpack-loader
Extract common code with splitChunks :
optimization: {
runtimeChunk: { name: 'manifest' },
splitChunks: {
cacheGroups: {
vendor: {
name: 'chunk-vendors',
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: 'chunk-common',
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
}
},SVG Icons & Font Icons
Using vector‑based SVG or icon fonts yields tiny files, fast rendering, and easy styling (size, color).
On‑Demand Code Loading
Split each route into its own bundle and load it dynamically with import() . Use [contenthash] in filenames to enable long‑term caching:
output: {
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].js',
path: path.resolve(__dirname, '../dist')
},Babel Runtime Optimization
Install @babel/plugin-transform-runtime and @babel/runtime to share helper functions instead of duplicating them in every compiled file.
"plugins": ["@babel/plugin-transform-runtime"]Server‑Side Rendering (SSR)
SSR returns ready‑made HTML from the server, improving first‑paint speed and SEO at the cost of added server complexity.
Defer Loading of JavaScript
Place CSS in the <head> and JavaScript at the bottom of the page, or add the defer attribute to scripts to avoid blocking rendering.
CDN for Static Resources
Deploy assets to geographically distributed CDN nodes to shorten the physical distance between user and server, reducing latency.
Image Optimization
Sprite Sheets
Combine many small icons into a single sprite image and display portions via background‑position . Tools such as webpack‑spritesmith or gulp.spritesmith automate this.
Lazy Loading
Delay image loading until the element enters the viewport. Example HTML and JavaScript:
<img original-src="https://example.com/image.png" /> const img = document.querySelector('img');
img.src = img.getAttribute('original-src');Libraries like lazysizes , verlok/lazyload , or tuupola/lazyload simplify this pattern.
Runtime Performance Optimization
Reduce Repaints & Reflows
Reflows (layout) are triggered by DOM changes that affect geometry; they always cause repaints, while repaints alone do not trigger reflows. Strategies include avoiding table layouts, batching read/write DOM operations, changing styles via a single class, and using position: absolute or fixed where possible.
// Bad – multiple reads/writes cause several reflows
div.style.left = div.offsetLeft + 1 + 'px';
div.style.top = div.offsetTop + 1 + 'px';
// Good – cache values, trigger only one reflow
var curLeft = div.offsetLeft;
var curTop = div.offsetTop;
div.style.left = curLeft + 1 + 'px';
div.style.top = curTop + 1 + 'px';Avoid Page Jank
Browsers aim for 60 FPS (≈16.6 ms per frame). Any JavaScript or style work that exceeds this budget causes jank. Only the necessary steps (style → layout → paint → composite) are executed; avoiding unnecessary layout or paint work helps maintain smooth frames.
Long List Optimization
Render only visible items using virtual lists. Determine container size, item size, and render only the subset that falls within the viewport. Popular libraries: react-virtualized , vue-virtual-scroll-list , ngx-virtual-scroller .
Scroll Event Performance
Throttle or debounce scroll handlers to limit execution frequency. Throttling runs the handler at a fixed interval (e.g., every 300 ms); debouncing runs it after the user stops scrolling for a set delay.
Web Workers
Offload CPU‑intensive tasks to a background thread using Web Workers, communicating via postMessage and onmessage , thus keeping the UI thread responsive.
Code‑Level Tips
Event Delegation
// Good – single listener on parent
document.querySelector('ul').onclick = (event) => {
const target = event.target;
if (target.nodeName === 'LI') {
console.log(target.innerHTML);
}
};
// Bad – many listeners on each
document.querySelectorAll('li').forEach(e => {
e.onclick = function() { console.log(this.innerHTML); };
});If‑else vs. Switch
When many discrete cases exist, a switch statement typically evaluates faster than a chain of if‑else statements.
if (state == 0) { console.log('Pending'); }
else if (state == 1) { console.log('Learning'); }
// …
switch (state) {
case 0: console.log('Pending'); break;
case 1: console.log('Learning'); break;
// …
}Use Flexbox for Layout
Modern flexbox layouts generally perform better than older float‑based or table‑based layouts.
In summary, careful attention to loading strategies, resource handling, DOM manipulation patterns, and leveraging modern browser features can dramatically improve front‑end performance.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.