Progressive performance optimization strategy
Core Objectives of Performance Optimization
The essence of performance optimization lies in balancing resource consumption with user experience. Over-optimization may increase development costs, while insufficient optimization can negatively impact user retention. The key is to identify critical performance metrics (such as First Contentful Paint, Time to Interactive) and make targeted improvements.
Performance Benchmarking
// Use Performance API to capture key metrics
const measurePerf = () => {
const [entry] = performance.getEntriesByType('navigation');
console.log('TTFB:', entry.responseStart - entry.requestStart);
console.log('FCP:', entry.domContentLoadedEventStart);
console.log('LCP:', performance.getEntriesByName('largest-contentful-paint')[0].startTime);
};
window.addEventListener('load', measurePerf);
In real-world scenarios, establish continuous monitoring systems. Recommended tools:
- Lighthouse panel in Chrome DevTools
- Multi-location testing via WebPageTest.org
- Real User Monitoring (RUM) tools like Sentry
Static Resource Optimization Strategies
Progressive Image Loading
<img
src="placeholder.jpg"
data-src="full-image.jpg"
class="lazyload"
alt="Example image"
/>
<script>
document.addEventListener("DOMContentLoaded", () => {
const lazyImages = [].slice.call(document.querySelectorAll("img.lazyload"));
if ("IntersectionObserver" in window) {
const lazyImageObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImage.classList.remove("lazyload");
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach((lazyImage) => {
lazyImageObserver.observe(lazyImage);
});
}
});
</script>
Font Loading Optimization
@font-face {
font-family: 'CustomFont';
src: url('font.woff2') format('woff2'),
url('font.woff') format('woff');
font-display: swap;
font-weight: 400;
}
Key strategies:
- Use
font-display: swap
to avoid layout shifts - Preload critical fonts:
<link rel="preload" href="font.woff2" as="font" crossorigin>
- Subset font files (e.g., using glyphhanger tool)
Code Splitting and Lazy Loading
Dynamic Import Implementation
// Route-level code splitting
const ProductPage = () => import('./pages/ProductPage.vue');
// Component-level lazy loading
const ChatWidget = () => ({
component: import('./components/ChatWidget.vue'),
loading: LoadingComponent,
delay: 200 // Delay loading indicator
});
// Webpack magic comments
import(/* webpackPrefetch: true */ './analytics.js');
Webpack Chunking Strategy
// webpack.config.js
optimization: {
splitChunks: {
chunks: 'all',
maxSize: 244 * 1024, // 244KB
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
Runtime Performance Optimization
Virtual Scroll Implementation
function VirtualList({ items, itemHeight, containerHeight }) {
const [scrollTop, setScrollTop] = useState(0);
const startIdx = Math.floor(scrollTop / itemHeight);
const endIdx = Math.min(
items.length - 1,
startIdx + Math.ceil(containerHeight / itemHeight)
);
return (
<div
style={{ height: containerHeight, overflow: 'auto' }}
onScroll={(e) => setScrollTop(e.target.scrollTop)}
>
<div style={{ height: items.length * itemHeight }}>
{items.slice(startIdx, endIdx + 1).map((item, i) => (
<div
key={startIdx + i}
style={{
height: itemHeight,
position: 'absolute',
top: (startIdx + i) * itemHeight
}}
>
{item}
</div>
))}
</div>
</div>
);
}
Animation Performance Optimization
/* Prioritize transform and opacity */
.box {
will-change: transform; /* Inform browser in advance */
transform: translateZ(0); /* Force hardware acceleration */
transition: transform 0.3s ease-out;
}
/* Avoid layout thrashing */
.animated-element {
position: fixed;
/* Or */
position: absolute;
}
Advanced Caching Strategies
Service Worker Caching
// sw.js
const CACHE_NAME = 'v1';
const OFFLINE_URL = '/offline.html';
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => cache.addAll([
'/styles/main.css',
'/scripts/app.js',
OFFLINE_URL
]))
);
});
self.addEventListener('fetch', (event) => {
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request)
.catch(() => caches.match(OFFLINE_URL))
);
} else {
event.respondWith(
caches.match(event.request)
.then((response) => response || fetch(event.request))
);
}
});
ETag Optimization
# nginx configuration
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 1y;
add_header Cache-Control "public, no-transform";
etag on;
}
Build-Time Optimization
Deep Tree Shaking Configuration
// babel.config.js
module.exports = {
presets: [
['@babel/preset-env', {
modules: false, // Preserve ES module syntax
targets: '> 0.25%, not dead'
}]
],
plugins: [
['@babel/plugin-transform-runtime', {
corejs: 3
}]
]
};
// package.json
{
"sideEffects": [
"*.css",
"*.scss",
"@babel/polyfill"
]
}
Visualization Tools
# Generate analysis report
webpack --profile --json > stats.json
# Use analysis tool
npx webpack-bundle-analyzer stats.json
Network Layer Optimization
HTTP/2 Server Push
# nginx configuration
http2_push /static/js/main.js;
http2_push /static/css/styles.css;
# Or via Link header
add_header Link "</static/js/main.js>; rel=preload; as=script";
QUIC Protocol Optimization
# Enable HTTP/3
listen 443 quic reuseport;
listen [::]:443 quic reuseport;
add_header Alt-Svc 'h3=":443"; ma=86400';
Rendering Performance Optimization
Avoiding Forced Synchronous Layout
// Anti-pattern - causes layout thrashing
function resizeAllParagraphs() {
for (let i = 0; i < paragraphs.length; i++) {
paragraphs[i].style.width = box.offsetWidth + 'px';
}
}
// Optimized solution
function resizeAllParagraphs() {
const width = box.offsetWidth;
requestAnimationFrame(() => {
for (let i = 0; i < paragraphs.length; i++) {
paragraphs[i].style.width = width + 'px';
}
});
}
Using content-visibility
.long-list {
content-visibility: auto;
contain-intrinsic-size: 500px; /* Estimated height */
}
.hidden-section {
content-visibility: hidden; /* Better performance than display:none */
}
Mobile-Specific Optimization
Touch Event Optimization
// Use passive event listeners
document.addEventListener('touchstart', onTouchStart, {
passive: true
});
// Avoid 300ms click delay
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Memory Management Strategies
// Prevent memory leaks
window.addEventListener('load', () => {
const app = new App();
window.addEventListener('beforeunload', () => {
app.cleanup(); // Manual cleanup
app = null;
});
});
// Use WeakMap for large objects
const largeData = new WeakMap();
largeData.set(targetElement, bigData);
Building Performance Culture
Establish performance budgets:
- Critical resource size limits (e.g., main JS ≤170KB)
- Third-party script limits (≤5 scripts)
- Maximum DOM nodes (e.g., 1500 nodes)
// Integrate performance tests in CI
module.exports = {
ci: {
collect: {
staticDistDir: './dist',
numberOfRuns: 3
},
assert: {
assertions: {
'categories:performance': ['error', {minScore: 0.9}],
'first-contentful-paint': ['error', {maxNumericValue: 2000}]
}
}
}
};
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:性能优化中的常见误区
下一篇:性能与功能开发的平衡