前端性能优化指南:从加载到交互的每一毫秒

前言

上个月,我们的产品被反馈"页面加载太慢"。用户在3G网络下需要等待8秒才能看到内容。

经过一个月的优化,我们把首屏加载时间从8秒降到了1.2秒。这篇文章分享我们的优化实践。


一、性能指标体系

1.1 核心Web指标(Core Web Vitals)

javascript

// LCP(Largest Contentful Paint)- 最大内容绘制// 目标:2.5秒内const observer = new PerformanceObserver((list) => { list.getEntries().forEach((entry) => { console.log('LCP:', entry.renderTime || entry.loadTime); });});observer.observe({entryTypes: ['largest-contentful-paint']});// FID(First Input Delay)- 首次输入延迟// 目标:100毫秒内new PerformanceObserver((list) => { list.getEntries().forEach((entry) => { console.log('FID:', entry.processingDuration); });}).observe({entryTypes: ['first-input']});// CLS(Cumulative Layout Shift)- 累积布局偏移// 目标:0.1以下let clsValue = 0;new PerformanceObserver((list) => { list.getEntries().forEach((entry) => { if (!entry.hadRecentInput) { clsValue += entry.value; console.log('CLS:', clsValue); } });}).observe({entryTypes: ['layout-shift']});

1.2 性能指标采集

javascript

// 采集所有关键指标const getMetrics = () => { const navigation = performance.getEntriesByType('navigation')[0]; const paint = performance.getEntriesByType('paint'); return { // 时间相关指标 DNS: navigation.domainLookupEnd - navigation.domainLookupStart, TCP: navigation.connectEnd - navigation.connectStart, TTFB: navigation.responseStart - navigation.requestStart, // 首字节时间 DomReady: navigation.domInteractive - navigation.fetchStart, LoadComplete: navigation.loadEventEnd - navigation.fetchStart, // 渲染相关指标 FP: paint.find(p => p.name === 'first-paint')?.startTime, // 首次绘制 FCP: paint.find(p => p.name === 'first-contentful-paint')?.startTime, // 首次内容绘制 // 资源加载 Resources: performance.getEntriesByType('resource').length, };};console.log(getMetrics());

二、网络优化

2.1 HTTP/2与CDN

javascript

// 配置CDN的关键资源const cdnConfig = { // 使用CDN加速静态资源 images: 'https://cdn.example.com/images', scripts: 'https://cdn.example.com/scripts', styles: 'https://cdn.example.com/styles',};// 使用HTTP/2的服务器推送// 在服务器侧配置const http2Push = { '/index.html': [ '/styles/main.css', '/scripts/app.js', '/fonts/roboto.woff2', ]};

2.2 资源压缩

bash

# Gzip压缩gzip -9 static/bundle.js -c > static/bundle.js.gz# Brotli压缩(更高的压缩率)brotli -q 11 static/bundle.js -o static/bundle.js.br# WebP图片格式cwebp original.jpg -o optimized.webp -q 80

2.3 缓存策略

javascript

// 服务器配置缓存头const express = require('express');const app = express();// 不变资源:带hash的JS、CSS、图片app.use('/static', (req, res, next) => { res.set('Cache-Control', 'public, max-age=31536000, immutable'); next();});// HTML文件:始终检查新版本app.get('/', (req, res) => { res.set('Cache-Control', 'no-cache, must-revalidate'); res.sendFile('index.html');});// API响应:短期缓存app.get('/api/*', (req, res) => { res.set('Cache-Control', 'private, max-age=300'); // 5分钟 next();});

三、代码分割与懒加载

3.1 Webpack代码分割

javascript

// webpack.config.jsmodule.exports = { optimization: { splitChunks: { chunks: 'all', cacheGroups: { // 分离第三方库 vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', priority: 10, reuseExistingChunk: true, }, // 分离公共模块 common: { minChunks: 2, priority: 5, reuseExistingChunk: true, } } } }};

3.2 动态导入与懒加载

javascript

// React懒加载示例import React, { Suspense, lazy } from 'react';const Dashboard = lazy(() => import('./Dashboard'));const Settings = lazy(() => import('./Settings'));function App() { return ( <Suspense fallback={<Loading />}> <Router> <Route path="/dashboard" component={Dashboard} /> <Route path="/settings" component={Settings} /> </Router> </Suspense> );}

3.3 路由懒加载

javascript

// Vue路由懒加载const router = new VueRouter({ routes: [ { path: '/home', component: () => import('./views/Home.vue') }, { path: '/about', component: () => import('./views/About.vue') }, { path: '/products', component: () => import('./views/Products.vue') } ]});

四、图片优化

4.1 响应式图片

html

<!-- 使用srcset适配不同屏幕 --><img src="image.jpg" srcset=" image-320w.jpg 320w, image-640w.jpg 640w, image-1280w.jpg 1280w " sizes="(max-width: 320px) 280px, (max-width: 640px) 600px, 1200px" alt="Responsive image"/><!-- 使用picture元素支持多种格式 --><picture> <source srcset="image.webp" type="image/webp" /> <source srcset="image.jpg" type="image/jpeg" /> <img src="image.jpg" alt="Fallback" /></picture>

4.2 图片懒加载

javascript

// 使用Intersection Observer懒加载const imageObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; img.classList.add('loaded'); observer.unobserve(img); } });});document.querySelectorAll('img[data-src]').forEach(img => { imageObserver.observe(img);});

html

<!-- HTML使用 --><img>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1179282.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode热题100】Java详解:二叉树的右视图(含BFS/DFS双解法与工程实践)

【LeetCode热题100】Java详解&#xff1a;二叉树的右视图&#xff08;含BFS/DFS双解法与工程实践&#xff09; 面向人群 正在准备技术面试&#xff08;尤其是大厂后端、算法岗&#xff09;的开发者已掌握基础二叉树操作&#xff0c;希望深入理解层序遍历与空间优化技巧的学习…

Docker容器化实战:从入门到生产环境部署

前言 两年前&#xff0c;我们公司的部署流程是这样的&#xff1a;开发在本地调试好代码&#xff0c;打包发给运维&#xff0c;运维在服务器上配置环境&#xff0c;然后发现"在我机器上能跑"。 引入Docker后&#xff0c;一切都变了。这篇文章分享我们的容器化实践经…

栈的一个magic gadget的运用以及数组越界

the end???.text:0000000000400658 add [rbp-3Dh], ebx .text:000000000040065B nop .text:000000000040065C retn这个gadget就比较常见了,就是把ebx的值加给…

亲测好用!自考论文必备TOP9 AI论文工具深度测评

亲测好用&#xff01;自考论文必备TOP9 AI论文工具深度测评 一、不同维度核心推荐&#xff1a;9款AI工具各有所长 自考论文写作是一个系统性工程&#xff0c;从选题到开题、初稿撰写、查重降重再到最终排版&#xff0c;每一个环节都需要合适的工具辅助。而市面上的AI论文工具功…

【LeetCode热题100】Java详解:二叉树展开为链表(含O(1)空间原地解法与工程实践)

【LeetCode热题100】Java详解&#xff1a;二叉树展开为链表&#xff08;含O(1)空间原地解法与工程实践&#xff09; 面向人群 正在准备技术面试&#xff08;尤其是大厂后端、算法岗&#xff09;的开发者已掌握二叉树基本操作&#xff0c;希望深入理解原地算法与指针操作技巧的…

文献阅读:Class-incremental Learning for Time Series:Benchmark and Evaluation

摘要 现实世界的环境本质上是不稳定的&#xff0c;随着时间的推移经常引入新的类别。 这在时间序列分类中尤其常见&#xff0c;例如医疗保健中新疾病分类的出现或人类活动识别中添加新活动。 在这种情况下&#xff0c;需要一个学习系统来有效地吸收新的类&#xff0c;同时避免…

Day84(10)-F:\硕士阶段\Java\课程资料\7、Redis入门到实战教程\Redis-笔记资料\03-高级篇\资料\item-service-多级缓存

安装和配置Canal 下面我们就开启mysql的主从同步机制,让Canal来模拟salve 1.开启MySQL主从 Canal是基于MySQL的主从同步功能,因此必须先开启MySQL的主从功能才可以。 这里以之前用Docker运行的mysql为例: 1.1.开启b…

【LeetCode热题100】Java详解:二叉搜索树中第K小的元素(含进阶优化与面试延伸)

【LeetCode热题100】Java详解&#xff1a;二叉搜索树中第K小的元素&#xff08;含进阶优化与面试延伸&#xff09; 面向人群 正在准备技术面试&#xff08;尤其是大厂算法岗、后端开发岗&#xff09;的程序员已掌握基础数据结构&#xff0c;希望深入理解二叉搜索树及其应用场…

如何提高图像识别的准确率?

你想了解的是如何提升图像识别(以MNIST手写数字识别为例)的准确率,核心是从数据、模型、训练策略、正则化四个维度优化,解决“欠拟合”(准确率低)、“过拟合”(训练准、测试差)两大核心问题。下面我会结合MNIS…

数据结构入门:时间复杂度与排序和查找 - 详解

数据结构入门:时间复杂度与排序和查找 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &q…

STM32单片机16*16汉字点阵广告牌75(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

STM32单片机16*16汉字点阵广告牌75(设计源文件万字报告讲解)&#xff08;支持资料、图片参考_相关定制&#xff09;_文章底部可以扫码 产品功能描述&#xff1a; 本系统由STM32F103C8T6单片机核心板、16*16点阵屏显示模块、按键及电源组成。 1、通过按键可以切换点阵屏显示内容…

Meta 收购 Manus:AI 智能体由对话转向执行的转折点

在 2025 年的最后一天&#xff0c;Meta 公司通过官方渠道确认了对 AI 初创企业 Manus 的收购计划。根据相关分析机构披露的数据&#xff0c;这笔交易涉及金额预计超过 20 亿美元。这一变动不仅是 Meta 在人工智能领域扩张的延续&#xff0c;也反映出全球科技巨头正在将研发重点…

Python+django的旅游景点交通酒店预订网的设计与实现

目录设计背景与目标系统功能模块技术实现方案系统特色与创新应用价值与总结开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;设计背景与目标 随着旅游业的快速发展&#xff0c;游客对便捷的景…

【时频分析】基于matlab面向相交群延迟多分量信号的时频重分配同步挤压频域线性调频小波变换【含Matlab源码 14985期】复现含文献

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到海神之光博客之家&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49…

如何通过数据分析实现精准产品定位

如何通过数据分析实现精准产品定位 关键词:数据分析、精准产品定位、市场细分、用户画像、数据挖掘 摘要:本文旨在探讨如何利用数据分析来实现精准的产品定位。通过对市场数据、用户数据等多源数据的深入分析,我们可以更好地了解市场需求、用户偏好和竞争态势,从而为产品找…

day141—递归—二叉树的最大深度(LeetCode-104)

题目描述给定一个二叉树 root &#xff0c;返回其最大深度。二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。示例 1&#xff1a;输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例 2&#xff1a;输入&#xff1a;root [1,null,2] 输…

STM32-270-多功能水质监测系统(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

STM32-270-多功能水质监测系统(设计源文件万字报告讲解)&#xff08;支持资料、图片参考_相关定制&#xff09;_文章底部可以扫码 产品功能描述&#xff1a; 本系统由STM32F103C8T6单片机核心板、TFT1.44寸彩屏液晶显示电路、&#xff08;无线蓝牙/无线WIFI/无线视频监控模块-可…

基于图像模糊度统计和盲卷积滤波的图像去模糊算法matlab仿真

1.前言 基于图像模糊度统计和盲卷积滤波的图像去模糊算法,结合了对图像模糊程度的量化评估和无需预先知道模糊核的图像恢复技术,能够在一定程度上自动分析图像的模糊特性并进行有效复原。 2.算法运行效果图预览 (完整…

Python+django的同城社区篮球队管理系统 体育运动篮球赛事预约系统

目录同城社区篮球队管理系统摘要开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;同城社区篮球队管理系统摘要 该系统基于PythonDjango框架开发&#xff0c;旨在为社区篮球爱好者提供便捷的球…

Python+django的图书资料借阅信息管理系统的设计与实现

目录摘要开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;摘要 随着信息化时代的快速发展&#xff0c;图书资料的管理效率成为图书馆和各类机构关注的重点。传统的纸质记录方式效率低下且容易…