当前位置: 首页 > news >正文

前端老旧项目全面性能优化指南与面试攻略

前端老旧项目全面性能优化指南与面试攻略

目录

  1. 项目性能分析与诊断
  2. 代码层面优化
  3. 资源加载优化
  4. 运行时性能优化
  5. 网络请求优化
  6. 构建与部署优化
  7. 监控与持续优化
  8. 面试回答技巧
  9. 实战案例分析

项目性能分析与诊断

1. 性能指标了解

核心 Web Vitals

  • LCP (Largest Contentful Paint): 最大内容绘制时间

    • 良好: ≤ 2.5s
    • 需要改进: 2.5s - 4s
    • 差: > 4s
  • FID (First Input Delay): 首次输入延迟

    • 良好: ≤ 100ms
    • 需要改进: 100ms - 300ms
    • 差: > 300ms
  • CLS (Cumulative Layout Shift): 累积布局偏移

    • 良好: ≤ 0.1
    • 需要改进: 0.1 - 0.25
    • 差: > 0.25

其他重要指标

  • FCP (First Contentful Paint): 首次内容绘制
  • TTI (Time to Interactive): 可交互时间
  • TBT (Total Blocking Time): 总阻塞时间
  • SI (Speed Index): 速度指数

2. 性能分析工具使用

浏览器开发者工具

// Performance API 分析
const observer = new PerformanceObserver((list) => {list.getEntries().forEach((entry) => {console.log('Performance entry:', entry);});
});observer.observe({entryTypes: ['navigation', 'resource', 'paint', 'largest-contentful-paint']
});// 手动标记关键时间点
performance.mark('component-start');
// ... 组件渲染逻辑
performance.mark('component-end');
performance.measure('component-render', 'component-start', 'component-end');

Lighthouse 自动化分析

// lighthouse-ci.js 配置
module.exports = {ci: {collect: {url: ['http://localhost:3000'],numberOfRuns: 3,},assert: {assertions: {'categories:performance': ['warn', { minScore: 0.9 }],'categories:accessibility': ['error', { minScore: 0.9 }],},},upload: {target: 'lhci',serverBaseUrl: 'https://your-lhci-server.com',},},
};

WebPageTest 分析

  • 多地区测试
  • 真实设备测试
  • 网络条件模拟
  • 详细的瀑布图分析

3. 性能问题诊断清单

加载性能问题

  • 资源文件过大(JS、CSS、图片)
  • 关键资源未优先加载
  • 阻塞渲染的资源
  • 网络请求过多
  • 缓存策略不合理

运行时性能问题

  • JavaScript 执行时间过长
  • 频繁的 DOM 操作
  • 内存泄漏
  • 未优化的事件监听器
  • 重复的计算或渲染

代码层面优化

1. JavaScript 优化

代码分割与懒加载

// 路由级别的代码分割
const routes = [{path: '/home',component: () => import('./views/Home.vue')},{path: '/profile',component: () => import('./views/Profile.vue')}
];// 组件级别的懒加载
const LazyComponent = React.lazy(() => import('./LazyComponent'));function App() {return (<Suspense fallback={<div>Loading...</div>}><LazyComponent /></Suspense>);
}

避免阻塞主线程

// 使用 requestIdleCallback 进行任务调度
function performHeavyTask(data) {const chunks = chunkArray(data, 100);function processChunk(index = 0) {if (index >= chunks.length) return;requestIdleCallback((deadline) => {while (deadline.timeRemaining() > 0 && index < chunks.length) {processDataChunk(chunks[index]);index++;}if (index < chunks.length) {processChunk(index);}});}processChunk();
}// Web Workers 处理CPU密集型任务
// main.js
const worker = new Worker('calculation-worker.js');
worker.postMessage({ data: largeDataSet });
worker.onmessage = (e) => {console.log('计算结果:', e.data);
};// calculation-worker.js
self.onmessage = function(e) {const result = heavyCalculation(e.data);self.postMessage(result);
};

内存优化

// 防止内存泄漏
class ComponentManager {constructor() {this.timers = new Set();this.observers = new Set();this.eventListeners = new Map();}addTimer(id) {this.timers.add(id);}addObserver(observer) {this.observers.add(observer);}addEventListener(element, event, handler) {element.addEventListener(event, handler);if (!this.eventListeners.has(element)) {this.eventListeners.set(element, []);}this.eventListeners.get(element).push({ event, handler });}cleanup() {// 清理定时器this.timers.forEach(id => clearInterval(id));this.timers.clear();// 清理观察者this.observers.forEach(observer => observer.disconnect());this.observers.clear();// 清理事件监听器this.eventListeners.forEach((events, element) => {events.forEach(({ event, handler }) => {element.removeEventListener(event, handler);});});this.eventListeners.clear();}
}

2. CSS 优化

关键 CSS 提取

// 使用 critical 包提取关键CSS
const critical = require('critical');critical.generate({inline: true,base: 'dist/',src: 'index.html',target: {css: 'critical.css',html: 'index-critical.html'},width: 1300,height: 900,minify: true
});

CSS 优化技巧

/* 避免深层嵌套和复杂选择器 */
/* 不好的做法 */
.header .nav .menu li a:hover {color: blue;
}/* 好的做法 */
.nav-link:hover {color: blue;
}/* 使用 CSS containment 优化渲染性能 */
.card {contain: layout style paint;
}/* 使用 will-change 提示浏览器优化 */
.animated-element {will-change: transform;
}.animated-element.done {will-change: auto; /* 动画完成后移除 */
}/* 使用 CSS 变量减少重复计算 */
:root {--primary-color: #007bff;--border-radius: 4px;--shadow: 0 2px 4px rgba(0,0,0,0.1);
}

CSS 加载优化

<!-- 预加载关键字体 -->
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin><!-- 异步加载非关键CSS -->
<link rel="preload" href="/css/non-critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/non-critical.css"></noscript>

资源加载优化

1. 图片优化

现代图片格式

<!-- 使用 picture 元素支持多种格式 -->
<picture><source srcset="image.avif" type="image/avif"><source srcset="image.webp" type="image/webp"><img src="image.jpg" alt="描述" loading="lazy">
</picture>

响应式图片

<!-- 基于视口宽度的响应式图片 -->
<img src="small.jpg"srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"sizes="(max-width: 480px) 100vw, (max-width: 800px) 50vw, 33vw"alt="响应式图片">

图片懒加载实现

// 使用 Intersection Observer 实现懒加载
class LazyImageLoader {constructor() {this.imageObserver = new IntersectionObserver(this.onImageIntersection.bind(this),{ rootMargin: '50px' });this.init();}init() {const lazyImages = document.querySelectorAll('img[data-src]');lazyImages.forEach(img => this.imageObserver.observe(img));}onImageIntersection(entries) {entries.forEach(entry => {if (entry.isIntersecting) {this.loadImage(entry.target);this.imageObserver.unobserve(entry.target);}});}loadImage(img) {img.src = img.dataset.src;img.onload = () => img.classList.add('loaded');img.onerror = () => img.classList.add('error');}
}new LazyImageLoader();

2. 字体优化

字体加载策略

/* 字体显示策略 */
@font-face {font-family: 'CustomFont';src: url('/fonts/custom.woff2') format('woff2');font-display: swap; /* 立即显示后备字体 */
}/* 字体预加载 */
<link rel="preload" href="/fonts/critical.woff2" as="font" type="font/woff2" crossorigin>

字体子集化

// 使用 fonttools 进行字体子集化
const fontSubset = require('font-subset');fontSubset({font: 'source-font.ttf',text: '需要的文字内容',output: 'subset-font.woff2'
});

3. 资源预加载策略

<!-- DNS 预解析 -->
<link rel="dns-prefetch" href="//api.example.com"><!-- 预连接 -->
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin><!-- 资源预加载 -->
<link rel="preload" href="/critical.css" as="style">
<link rel="preload" href="/hero-image.jpg" as="image"><!-- 预获取下一页资源 -->
<link rel="prefetch" href="/next-page.html"><!-- 模块预加载 -->
<link rel="modulepreload" href="/modules/app.js">

运行时性能优化

1. DOM 操作优化

批量 DOM 操作

// 使用 DocumentFragment 减少重排重绘
function batchUpdateDOM(items) {const fragment = document.createDocumentFragment();items.forEach(item => {const element = document.createElement('div');element.textContent = item.text;element.className = item.className;fragment.appendChild(element);});// 一次性插入所有元素document.getElementById('container').appendChild(fragment);
}// 使用 requestAnimationFrame 优化动画
function animateElement(element, from, to, duration) {const start = performance.now();function update(currentTime) {const elapsed = currentTime - start;const progress = Math.min(elapsed / duration, 1);const current = from + (to - from) * progress;element.style.transform = `translateX(${current}px)`;if (progress < 1) {requestAnimationFrame(update);}}requestAnimationFrame(update);
}

虚拟滚动实现

class VirtualScroller {constructor(container, itemHeight, items) {this.container = container;this.itemHeight = itemHeight;this.items = items;this.visibleCount = Math.ceil(container.clientHeight / itemHeight) + 2;this.startIndex = 0;this.init();}init() {this.container.style.height = `${this.items.length * this.itemHeight}px`;this.container.addEventListener('scroll', this.onScroll.bind(this));this.render();}onScroll() {const scrollTop = this.container.scrollTop;const newStartIndex = Math.floor(scrollTop / this.itemHeight);if (newStartIndex !== this.startIndex) {this.startIndex = newStartIndex;this.render();}}render() {const endIndex = Math.min(this.startIndex + this.visibleCount,this.items.length);const visibleItems = this.items.slice(this.startIndex, endIndex);this.container.innerHTML = visibleItems.map((item, index) => `<div class="item" style="position: absolute;top: ${(this.startIndex + index) * this.itemHeight}px;height: ${this.itemHeight}px;">${item.content}</div>`).join('');}
}

2. 事件优化

事件委托

// 使用事件委托减少事件监听器数量
class EventDelegator {constructor(container) {this.container = container;this.handlers = new Map();this.container.addEventListener('click', this.handleClick.bind(this));}register(selector, handler) {if (!this.handlers.has(selector)) {this.handlers.set(selector, []);}this.handlers.get(selector).push(handler);}handleClick(event) {this.handlers.forEach((handlers, selector) => {if (event.target.matches(selector)) {handlers.forEach(handler => handler(event));}});}
}// 使用示例
const delegator = new EventDelegator(document.body);
delegator.register('.button', (e) => console.log('Button clicked'));
delegator.register('.link', (e) => console.log('Link clicked'));

防抖和节流

// 防抖函数
function debounce(func, wait, immediate = false) {let timeout;return function executedFunction(...args) {const later = () => {timeout = null;if (!immediate) func.apply(this, args);};const callNow = immediate && !timeout;clearTimeout(timeout);timeout = setTimeout(later, wait);if (callNow) func.apply(this, args);};
}// 节流函数
function throttle(func, limit) {let inThrottle;return function(...args) {if (!inThrottle) {func.apply(this, args);inThrottle = true;setTimeout(() => inThrottle = false, limit);}};
}// 使用示例
const debouncedSearch = debounce((query) => {// 执行搜索
}, 300);const throttledScroll = throttle(() => {// 处理滚动
}, 100);window.addEventListener('scroll', throttledScroll);

网络请求优化

1. HTTP 优化

请求合并与缓存

// 请求缓存管理器
class RequestCacheManager {constructor() {this.cache = new Map();this.pendingRequests = new Map();}async get(url, options = {}) {const cacheKey = this.getCacheKey(url, options);// 检查缓存if (this.cache.has(cacheKey)) {const cached = this.cache.get(cacheKey);if (!this.isExpired(cached)) {return cached.data;}}// 检查是否有pending请求if (this.pendingRequests.has(cacheKey)) {return this.pendingRequests.get(cacheKey);}// 发起新请求const request = this.makeRequest(url, options);this.pendingRequests.set(cacheKey, request);try {const data = await request;this.cache.set(cacheKey, {data,timestamp: Date.now(),ttl: options.ttl || 60000 // 默认1分钟});return data;} finally {this.pendingRequests.delete(cacheKey);}}getCacheKey(url, options) {return `${url}:${JSON.stringify(options)}`;}isExpired(cached) {return Date.now() - cached.timestamp > cached.ttl;}async makeRequest(url, options) {const response = await fetch(url, options);return response.json();}
}

批量请求优化

// 请求批处理器
class BatchRequestProcessor {constructor(batchSize = 10, delay = 100) {this.batchSize = batchSize;this.delay = delay;this.queue = [];this.processing = false;}add(request) {return new Promise((resolve, reject) => {this.queue.push({ request, resolve, reject });this.process();});}async process() {if (this.processing || this.queue.length === 0) return;this.processing = true;while (this.queue.length > 0) {const batch = this.queue.splice(0, this.batchSize);try {const promises = batch.map(({ request }) => request());const results = await Promise.allSettled(promises);results.forEach((result, index) => {const { resolve, reject } = batch[index];if (result.status === 'fulfilled') {resolve(result.value);} else {reject(result.reason);}});} catch (error) {batch.forEach(({ reject }) => reject(error));}// 批次间延迟if (this.queue.length > 0) {await new Promise(resolve => setTimeout(resolve, this.delay));}}this.processing = false;}
}

2. 数据预加载

智能预加载策略

// 路由预加载器
class RoutePreloader {constructor() {this.preloadedRoutes = new Set();this.observer = new IntersectionObserver(this.onLinkVisible.bind(this),{ rootMargin: '100px' });this.init();}init() {// 监听所有路由链接const links = document.querySelectorAll('a[href^="/"]');links.forEach(link => this.observer.observe(link));// 鼠标悬停预加载document.addEventListener('mouseover', this.onLinkHover.bind(this));}onLinkVisible(entries) {entries.forEach(entry => {if (entry.isIntersecting) {const href = entry.target.getAttribute('href');this.preloadRoute(href);}});}onLinkHover(event) {if (event.target.tagName === 'A' && event.target.href) {const href = new URL(event.target.href).pathname;this.preloadRoute(href);}}async preloadRoute(href) {if (this.preloadedRoutes.has(href)) return;this.preloadedRoutes.add(href);try {// 预加载路由组件const module = await import(/* webpackChunkName: "[request]" */ `./views${href}`);console.log(`预加载路由: ${href}`);} catch (error) {console.warn(`预加载路由失败: ${href}`, error);this.preloadedRoutes.delete(href);}}
}

构建与部署优化

1. Webpack 构建优化

配置优化示例

// webpack.config.js
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');module.exports = {mode: 'production',// 入口优化entry: {app: './src/main.js',vendor: ['react', 'react-dom', 'lodash'] // 提取第三方库},// 输出优化output: {path: path.resolve(__dirname, 'dist'),filename: '[name].[contenthash:8].js',chunkFilename: '[name].[contenthash:8].chunk.js',clean: true},// 优化配置optimization: {// 代码分割splitChunks: {chunks: 'all',cacheGroups: {vendor: {test: /[\\/]node_modules[\\/]/,name: 'vendors',chunks: 'all',priority: 10},common: {name: 'common',minChunks: 2,chunks: 'all',priority: 5}}},// 压缩优化minimizer: [new TerserPlugin({terserOptions: {compress: {drop_console: true, // 移除consoledrop_debugger: true // 移除debugger}},parallel: true // 并行压缩})],// 运行时代码提取runtimeChunk: 'single'},// 插件配置plugins: [// Gzip压缩new CompressionPlugin({algorithm: 'gzip',test: /\.(js|css|html|svg)$/,threshold: 8192,minRatio: 0.8}),// 包分析process.env.ANALYZE && new BundleAnalyzerPlugin()].filter(Boolean),// 模块解析优化resolve: {alias: {'@': path.resolve(__dirname, 'src')},extensions: ['.js', '.jsx', '.ts', '.tsx'],modules: ['node_modules'] // 限制模块查找范围},// 外部化依赖externals: {'react': 'React','react-dom': 'ReactDOM'}
};

2. 现代构建工具优化

Vite 配置优化

// vite.config.js
import { defineConfig } from 'vite';
import { resolve } from 'path';export default defineConfig({// 构建优化build: {target: 'es2015',minify: 'terser',terserOptions: {compress: {drop_console: true,drop_debugger: true}},// 代码分割rollupOptions: {output: {manualChunks: {vendor: ['react', 'react-dom'],utils: ['lodash', 'dayjs']}}},// 资源大小限制chunkSizeWarningLimit: 1000},// 开发服务器优化server: {hmr: {overlay: false // 关闭错误遮罩层}},// 插件配置plugins: [// ... 插件配置],// 依赖预构建optimizeDeps: {include: ['react', 'react-dom'],exclude: ['@vueuse/core']}
});

3. CDN 与缓存策略

缓存策略配置

# nginx 配置示例
server {listen 80;server_name example.com;# 静态资源缓存location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {expires 1y;add_header Cache-Control "public, immutable";add_header Vary "Accept-Encoding";# 启用 gzipgzip on;gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;}# HTML 文件缓存策略location ~* \.(html|htm)$ {expires 1h;add_header Cache-Control "public, must-revalidate";}# API 缓存location /api/ {proxy_pass http://backend;proxy_cache my_cache;proxy_cache_valid 200 5m;proxy_cache_key $request_uri;}
}

监控与持续优化

1. 性能监控实现

Real User Monitoring (RUM)

// 性能监控类
class PerformanceMonitor {constructor(apiUrl) {this.apiUrl = apiUrl;this.metrics = {};this.init();}init() {// 监听页面加载完成window.addEventListener('load', () => {this.collectPageMetrics();});// 监听 CLSthis.observeCLS();// 监听 LCPthis.observeLCP();// 监听 FIDthis.observeFID();// 定期发送数据setInterval(() => this.sendMetrics(), 30000);}collectPageMetrics() {const navigation = performance.getEntriesByType('navigation')[0];this.metrics = {...this.metrics,dns: navigation.domainLookupEnd - navigation.domainLookupStart,tcp: navigation.connectEnd - navigation.connectStart,request: navigation.responseStart - navigation.requestStart,response: navigation.responseEnd - navigation.responseStart,dom: navigation.domContentLoadedEventEnd - navigation.domContentLoadedEventStart,load: navigation.loadEventEnd - navigation.loadEventStart,fcp: this.getFCP(),ttfb: navigation.responseStart - navigation.requestStart};}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);}}this.metrics.cls = clsValue;});observer.observe({ type: 'layout-shift', buffered: true });}observeLCP() {const observer = new PerformanceObserver((list) => {const entries = list.getEntries();const lastEntry = entries[entries.length - 1];this.metrics.lcp = lastEntry.startTime;});observer.observe({ type: 'largest-contentful-paint', buffered: true });}observeFID() {const observer = new PerformanceObserver((list) => {for (const entry of list.getEntries()) {this.metrics.fid = entry.processingStart - entry.startTime;}});observer.observe({ type: 'first-input', buffered: true });}getFCP() {const fcpEntry = performance.getEntriesByName('first-contentful-paint')[0];return fcpEntry ? fcpEntry.startTime : null;}async sendMetrics() {if (Object.keys(this.metrics).length === 0) return;try {await fetch(this.apiUrl, {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({url: location.href,userAgent: navigator.userAgent,timestamp: Date.now(),metrics: this.metrics})});} catch (error) {console.error('发送监控数据失败:', error);}}
}// 初始化监控
new PerformanceMonitor('/api/metrics');

2. 错误监控

错误收集与上报

class ErrorMonitor {constructor(apiUrl) {this.apiUrl = apiUrl;this.errorQueue = [];this.maxQueueSize = 10;this.init();}init() {// JavaScript 错误监听window.addEventListener('error', this.handleError.bind(this));// Promise 未捕获错误window.addEventListener('unhandledrejection', this.handlePromiseError.bind(this));// 资源加载错误window.addEventListener('error', this.handleResourceError.bind(this), true);// 定期发送错误setInterval(() => this.flushErrors(), 10000);}handleError(event) {this.addError({type: 'javascript',message: event.message,filename: event.filename,lineno: event.lineno,colno: event.colno,stack: event.error?.stack,timestamp: Date.now()});}handlePromiseError(event) {this.addError({type: 'promise',message: event.reason.toString(),stack: event.reason.stack,timestamp: Date.now()});}handleResourceError(event) {if (event.target !== window) {this.addError({type: 'resource',message: `Failed to load ${event.target.tagName}`,source: event.target.src || event.target.href,timestamp: Date.now()});}}addError(error) {this.errorQueue.push(error);if (this.errorQueue.length >= this.maxQueueSize) {this.flushErrors();}}async flushErrors() {if (this.errorQueue.length === 0) return;const errors = [...this.errorQueue];this.errorQueue = [];try {await fetch(this.apiUrl, {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({url: location.href,userAgent: navigator.userAgent,errors})});} catch (error) {// 发送失败,重新加入队列this.errorQueue.unshift(...errors);}}
}

面试回答技巧

1. 回答框架

STAR 方法

  • Situation: 描述项目背景和遇到的性能问题
  • Task: 说明你的任务和目标
  • Action: 详细描述你采取的优化措施
  • Result: 量化优化结果和效果

2. 常见面试问题及回答要点

问题1: 如何分析老旧项目的性能问题?

回答要点:

1. 性能指标分析- 使用 Lighthouse 进行综合评估- Chrome DevTools 分析加载时间线- 监控 Core Web Vitals 指标2. 代码质量审查- 分析 bundle 大小和组成- 检查无用代码和重复依赖- 评估代码分割情况3. 网络性能分析- 检查资源加载策略- 分析缓存配置- 评估 CDN 使用情况4. 运行时性能分析- 使用 Performance 面板分析主线程阻塞- 检查内存使用和泄漏- 分析重排重绘频率

问题2: 具体实施了哪些优化措施?

回答示例:

我负责的项目是一个电商后台管理系统,页面加载时间超过8秒,用户体验很差。优化措施:1. 构建优化 (40% 性能提升)- 实施代码分割,将第三方库单独打包- 启用 Tree Shaking 删除无用代码- 配置 Gzip 压缩,资源大小减少60%2. 资源优化 (30% 性能提升)- 图片格式现代化,使用 WebP- 实施图片懒加载- 字体预加载和子集化3. 代码优化 (20% 性能提升)- 实施虚拟滚动解决长列表性能问题- 使用 React.memo 和 useMemo 减少不必要渲染- 优化事件处理,使用防抖节流4. 缓存策略 (10% 性能提升)- 配置合理的 HTTP 缓存策略- 实施接口缓存和预加载结果:页面加载时间从8秒降到2.5秒,Lighthouse 分数从30分提升到85分。

问题3: 如何保证优化效果的持续性?

回答要点:

1. 性能监控体系- 部署 RUM 监控收集真实用户数据- 设置性能预警阈值- 定期生成性能报告2. 开发流程集成- CI/CD 中集成 Lighthouse 检查- Bundle 分析报告- 性能回归测试3. 团队规范建立- 制定性能开发规范- 代码审查中关注性能- 定期技术分享和培训4. 持续优化机制- 月度性能回顾会议- 新技术调研和应用- 用户反馈收集和处理

3. 面试加分技巧

展示技术深度

  • 能够解释优化原理,不只是列举方法
  • 提及新技术和最佳实践的应用
  • 展示对浏览器工作原理的理解

展示业务思维

  • 将技术优化与业务价值关联
  • 提及用户体验改善和转化率提升
  • 展示成本效益分析能力

展示团队协作

  • 说明如何推动团队采用新的优化方案
  • 分享知识传递和培训经验
  • 展示跨部门沟通协调能力

实战案例分析

案例1: 电商网站首页优化

优化前状况:

  • 首屏加载时间: 6.8秒
  • Lighthouse 分数: 32分
  • 资源总大小: 3.2MB
  • JavaScript 执行时间: 2.1秒

优化措施:

  1. 关键资源优化
// 首屏关键CSS内联
const criticalCSS = `.header { height: 60px; background: #fff; }.hero { height: 400px; background: #f5f5f5; }
`;// 非关键CSS异步加载
const loadCSS = (href) => {const link = document.createElement('link');link.rel = 'preload';link.as = 'style';link.href = href;link.onload = () => link.rel = 'stylesheet';document.head.appendChild(link);
};
  1. 图片优化
<!-- 首屏轮播图优化 -->
<picture><source srcset="hero-mobile.webp" media="(max-width: 768px)" type="image/webp"><source srcset="hero-desktop.webp" type="image/webp"><img src="hero-desktop.jpg" alt="首页轮播" loading="eager">
</picture>
  1. JavaScript 优化
// 路由懒加载
const routes = [{path: '/product/:id',component: () => import(/* webpackChunkName: "product" */ './Product.vue')}
];// 第三方脚本延迟加载
const loadScript = (src, defer = true) => {const script = document.createElement('script');script.src = src;script.defer = defer;document.head.appendChild(script);
};// 页面加载完成后加载非关键脚本
window.addEventListener('load', () => {loadScript('/js/analytics.js');loadScript('/js/chat-widget.js');
});

优化结果:

  • 首屏加载时间: 2.1秒 (提升69%)
  • Lighthouse 分数: 89分 (提升178%)
  • 资源总大小: 1.8MB (减少44%)
  • 用户转化率提升15%

案例2: 后台管理系统优化

优化前问题:

  • 列表页渲染1000条数据卡顿严重
  • 内存占用持续增长,存在泄漏
  • 频繁的接口请求导致服务器压力大

优化方案:

  1. 虚拟滚动实现
<template><div class="virtual-list" ref="container" @scroll="onScroll"><div class="virtual-list-phantom" :style="{ height: totalHeight + 'px' }"></div><div class="virtual-list-content" :style="getContentStyle()"><divv-for="item in visibleItems":key="item.id"class="virtual-list-item":style="{ height: itemHeight + 'px' }"><slot :item="item"></slot></div></div></div>
</template><script>
export default {props: {items: Array,itemHeight: { type: Number, default: 50 }},data() {return {startIndex: 0,endIndex: 0,containerHeight: 0};},computed: {totalHeight() {return this.items.length * this.itemHeight;},visibleCount() {return Math.ceil(this.containerHeight / this.itemHeight) + 2;},visibleItems() {return this.items.slice(this.startIndex, this.endIndex);}},methods: {onScroll() {const scrollTop = this.$refs.container.scrollTop;this.startIndex = Math.floor(scrollTop / this.itemHeight);this.endIndex = this.startIndex + this.visibleCount;},getContentStyle() {return {transform: `translateY(${this.startIndex * this.itemHeight}px)`};}}
};
</script>
  1. 内存泄漏修复
// 组件清理机制
export default {data() {return {timers: [],observers: [],subscriptions: []};},methods: {addTimer(id) {this.timers.push(id);},addObserver(observer) {this.observers.push(observer);},addSubscription(subscription) {this.subscriptions.push(subscription);}},beforeDestroy() {// 清理定时器this.timers.forEach(clearInterval);// 清理观察者this.observers.forEach(observer => observer.disconnect());// 清理订阅this.subscriptions.forEach(sub => sub.unsubscribe());}
};
  1. 接口请求优化
// 请求去重和缓存
class APIManager {constructor() {this.cache = new Map();this.pendingRequests = new Map();}async request(url, options = {}) {const key = `${url}:${JSON.stringify(options)}`;// 检查缓存if (this.cache.has(key)) {const cached = this.cache.get(key);if (Date.now() - cached.timestamp < 30000) {return cached.data;}}// 防止重复请求if (this.pendingRequests.has(key)) {return this.pendingRequests.get(key);}const request = fetch(url, options).then(res => res.json());this.pendingRequests.set(key, request);try {const data = await request;this.cache.set(key, { data, timestamp: Date.now() });return data;} finally {this.pendingRequests.delete(key);}}
}

优化结果:

  • 列表渲染性能提升90%,支持10万条数据流畅滚动
  • 内存使用稳定,无泄漏现象
  • 接口请求减少70%,服务器响应时间提升50%

总结

老旧项目性能优化是一个系统工程,需要从分析、优化、监控三个维度进行全面考虑:

关键成功因素

  1. 全面的性能分析 - 使用合适的工具找出真正的性能瓶颈
  2. 分层次的优化策略 - 从构建到运行时的全链路优化
  3. 持续的监控体系 - 确保优化效果的可持续性
  4. 团队协作和知识传承 - 让优化成果在团队中延续

面试要点

  • 体现技术深度和实战经验
  • 强调业务价值和用户体验改善
  • 展示系统思维和持续改进能力
  • 准备具体的数据和案例支撑

性能优化不仅是技术问题,更是工程问题。在面试中展现你的全面思考能力,会让你在众多候选人中脱颖而出。

http://www.dtcms.com/a/407210.html

相关文章:

  • 破局与进化:火山引擎Data Agent从落地实践到架构未来
  • 网站不用工具开发建设易语言怎么做ifa网站填表
  • 云手机出现的意义都有哪些
  • 网站 设计 文档wordpress 打开速度
  • Python 基于 MinIO 的文件上传服务与图像处理核心实践
  • 余姚网站开发什么是手机网站
  • 9.25 深度学习7
  • 成都网站制作成都网站维护
  • 上传的网站打不开网站建设公司有哪些原
  • 【论文阅读】纯视觉语言动作(VLA)模型:全面综述
  • python做网站的优势网络营销推广方法ppt
  • 未来工厂构建蓝图:从IT/OT割裂到数据驱动的实践全解析
  • wamp:phpmyadmin访问被拒
  • 一级a做爰电影免费观看网站wordpress 评论邮箱改成电话
  • Excel——常用函数三
  • gitlab runner 里面使用harbor私仓
  • gitlab操作技巧
  • 番禺网站优化平台搜索公众号
  • 20250925让荣品RD-RK3588-MID开发板的Android13系统在长按3s才弹出关机对话框
  • 做视频资源网站有哪些内容学仿网站
  • Asymptotic Notation: Big-Oh, Big-Omega, Big-Theta, Small-Oh, Small-Omega
  • Bugku-TLS
  • 焦作住房和城乡建设厅网站做网站网站代理的犯法么
  • MTK调试-PLsensor
  • 番禺区建设网站seo手机优化方法
  • 网站建设服务器都有哪些旅游网站首页设计
  • LVS TUN隧道模式
  • 使用Docker将PyQt深度学习项目打包成镜像
  • 腾讯 CodeBuddy 与国内主流 AI 编程工具深度对比
  • 浏览网站怎么用手机做网站开发用什么语言比较好