小薛同学个人博客,XXTX的个人主页,acnb,ACNB,www.acnb.cn,个人主页,技术博客,编程学习,代码分享,性能优化,前端优化,网页性能,加载优化,渲染优化,缓存策略,LCP,FID,CLS,Web性能指标,性能监控,性能测试,性能分析,小薛同学博客,acnb
2025年10月5日
性能优化
阅读时间:16分钟

前端性能优化策略

打造快速响应的现代Web应用

性能指标

理解核心性能指标是优化的第一步:

核心Web指标: LCP(最大内容绘制)、FID(首次输入延迟)、CLS(累积布局偏移)。

1. 加载性能优化

1.1 资源优化

<!-- 图片优化 --> <picture> <source srcset="image.webp" type="image/webp"> <source srcset="image.avif" type="image/avif"> <img src="image.jpg" alt="示例图片" loading="lazy" decoding="async"> </picture> <!-- 字体优化 --> <link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin> <!-- 脚本优化 --> <script src="app.js" defer></script> <!-- 或 --> <script src="app.js" async></script> <!-- 样式优化 --> <link rel="preload" href="style.css" as="style"> <link rel="stylesheet" href="style.css">

1.2 代码分割

// Webpack动态导入 const module = await import('./module.js'); // React懒加载 const LazyComponent = React.lazy(() => import('./LazyComponent')); // Vue懒加载 const LazyComponent = () => import('./LazyComponent.vue'); // 路由懒加载(React Router v6) const router = createBrowserRouter([ { path: '/', element: <Layout />, children: [ { index: true, element: <Home /> }, { path: 'about', lazy: () => import('./pages/About') }, { path: 'dashboard', lazy: () => import('./pages/Dashboard') } ] } ]);

2. 渲染性能优化

2.1 减少重排重绘

// 避免频繁操作DOM const fragment = document.createDocumentFragment(); for (let i = 0; i < 1000; i++) { const div = document.createElement('div'); div.textContent = `Item ${i}`; fragment.appendChild(div); } document.getElementById('container').appendChild(fragment); // 使用虚拟DOM const items = Array.from({length: 1000}, (_, i) => `Item ${i}`); const list = items.map(item => <div key={item}>{item}</div> ); // 避免强制同步布局 // 错误示例 function resizeAllParagraphsToMatchBlockWidth() { const paragraphs = document.querySelectorAll('p'); for (let i = 0; i < paragraphs.length; i++) { paragraphs[i].style.width = `${paragraphs[i].offsetWidth}px`; } } // 正确示例 function resizeAllParagraphsToMatchBlockWidth() { const paragraphs = document.querySelectorAll('p'); const width = paragraphs[0].offsetWidth; // 只读取一次 for (let i = 0; i < paragraphs.length; i++) { paragraphs[i].style.width = `${width}px`; } }

2.2 使用Web Workers

// main.js const worker = new Worker('worker.js'); // 发送数据到Worker worker.postMessage({ type: 'calculate', data: largeDataset }); // 接收Worker结果 worker.onmessage = function(event) { const result = event.data; console.log('计算结果:', result); }; // worker.js self.onmessage = function(event) { const { type, data } = event.data; if (type === 'calculate') { // 执行耗时计算 const result = performHeavyCalculation(data); // 返回结果 self.postMessage(result); } }; function performHeavyCalculation(data) { // 复杂的计算逻辑 return data.map(item => item * 2); }

3. 缓存策略

// Service Worker缓存策略 const CACHE_NAME = 'my-site-cache-v1'; const urlsToCache = [ '/', '/styles/main.css', '/scripts/main.js', '/images/logo.png' ]; self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME) .then(cache => { return cache.addAll(urlsToCache); }) ); }); self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(response => { if (response) { return response; // 缓存命中 } // 克隆请求(请求体只能使用一次) const fetchRequest = event.request.clone(); return fetch(fetchRequest).then(response => { // 检查是否是有效响应 if (!response || response.status !== 200 || response.type !== 'basic') { return response; } // 克隆响应(响应体只能使用一次) const responseToCache = response.clone(); caches.open(CACHE_NAME) .then(cache => { cache.put(event.request, responseToCache); }); return response; }); }) ); });

4. 网络优化

// HTTP/2 Server Push配置 # nginx.conf http2_push /style.css; http2_push /app.js; // 使用preconnect和prefetch <link rel="preconnect" href="https://api.example.com"> <link rel="dns-prefetch" href="https://api.example.com"> // 资源提示 <link rel="prefetch" href="/next-page.html"> <link rel="prerender" href="/next-page.html"> // 压缩配置 # nginx gzip配置 gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json image/svg+xml; // Brotli压缩(更高效) brotli on; brotli_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json; brotli_static on;

5. 监控与分析工具

5.1 性能监控

// 使用Performance API const measurePerformance = () => { const navigationEntries = performance.getEntriesByType('navigation'); const paintEntries = performance.getEntriesByType('paint'); if (navigationEntries.length > 0) { const navEntry = navigationEntries[0]; console.log('页面加载时间:', navEntry.loadEventEnd - navEntry.startTime); console.log('DNS查询时间:', navEntry.domainLookupEnd - navEntry.domainLookupStart); console.log('TCP连接时间:', navEntry.connectEnd - navEntry.connectStart); console.log('首字节时间:', navEntry.responseStart - navEntry.requestStart); } if (paintEntries.length > 0) { const firstPaint = paintEntries.find(entry => entry.name === 'first-paint'); const firstContentfulPaint = paintEntries.find(entry => entry.name === 'first-contentful-paint'); if (firstPaint) console.log('首次绘制:', firstPaint.startTime); if (firstContentfulPaint) console.log('首次内容绘制:', firstContentfulPaint.startTime); } // 监听长任务 const observer = new PerformanceObserver(list => { for (const entry of list.getEntries()) { console.log('长任务:', entry); } }); observer.observe({ entryTypes: ['longtask'] }); }; // 监听核心Web指标 const observeCLS = () => { let clsValue = 0; let clsEntries = []; const observer = new PerformanceObserver(list => { for (const entry of list.getEntries()) { if (!entry.hadRecentInput) { clsValue += entry.value; clsEntries.push(entry); console.log('CLS增加:', entry.value, '总CLS:', clsValue); } } }); observer.observe({ type: 'layout-shift', buffered: true }); }; // 监听LCP const observeLCP = () => { const observer = new PerformanceObserver(list => { const entries = list.getEntries(); const lastEntry = entries[entries.length - 1]; console.log('LCP:', lastEntry.startTime, lastEntry); }); observer.observe({ type: 'largest-contentful-paint', buffered: true }); };

6. 框架特定优化

6.1 React优化

// 使用React.memo避免不必要的渲染 const MemoizedComponent = React.memo(MyComponent, (prevProps, nextProps) => { return prevProps.id === nextProps.id; }); // 使用useMemo和useCallback const expensiveValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); const memoizedCallback = useCallback(() => { doSomething(a, b); }, [a, b]); // 虚拟列表优化 import { FixedSizeList as List } from 'react-window'; function MyList({ items }) { return ( <List height={400} itemCount={items.length} itemSize={50} width={300} > {({ index, style }) => ( <div style={style}> Item {items[index]} </div> )} </List> ); } // 代码分割 const OtherComponent = React.lazy(() => import('./OtherComponent'));

7. 构建工具优化

// webpack.config.js优化示例 module.exports = { mode: 'production', // 代码分割 optimization: { splitChunks: { chunks: 'all', cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', chunks: 'all' }, common: { minChunks: 2, name: 'common', chunks: 'async', minSize: 0 } } }, runtimeChunk: 'single', minimize: true, minimizer: [ new TerserPlugin({ parallel: true, terserOptions: { compress: { drop_console: true } } }) ] }, // 模块配置 module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { cacheDirectory: true } } } ] }, // 插件配置 plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }), new CompressionPlugin({ algorithm: 'gzip', test: /\.(js|css|html|svg)$/, threshold: 10240, minRatio: 0.8 }), new BundleAnalyzerPlugin({ analyzerMode: 'static', openAnalyzer: false }) ], // 性能提示 performance: { hints: 'warning', maxEntrypointSize: 512000, maxAssetSize: 512000 } };

总结

前端性能优化是一个持续的过程,需要从多个维度综合考虑。关键是测量、分析、优化、再测量,形成一个良性循环。

关键建议:

  1. 始终以用户为中心,关注核心Web指标
  2. 实施渐进式优化策略
  3. 建立持续的性能监控机制
  4. 团队协作,性能优化人人有责