前端性能优化 面试如何完美回答
前言
性能优化是目前在面试中被问到非常多的问题,主要就是通过各种算和技术来提高页和应用的速度和用户体前端性能优化的问题并不好回答
在回答的时候干万不要掉进一个误区,认为性能优化只是几个技术点而已,事实上性能优化涉及到的是多方面的
我们首先需要知道,当一个项目出现性能问题时,并不是突然发生了,而是日积月累的结果,所以对于一个项目来说,最好的性能优化应该是从平时开发过程中就要去注意和实现的
三个层面
所以接下来我们会从三个层面来聊一聊性能优化的内容,包括
- 项目架构
- 项目开发
- 项目部署
项目架构
为什么架构设计会影响性能呢?
俗话说如果战略如果错误那么在战术再怎么优秀也无法弥补失败。在真实开发中,性能优化并不是一朝一夕的事情,如果等到我们的项目出现严重的性能问题,再去解决,往往会成为一坨大粪代码
那么架构设计需要考虑哪些因素
主要是两方面的因素协同开发、模块解耦。
项目架构的因素
协同开发
这是指多个开发人员能够有效地一起工作,减少冲突和重复工作
良好的架构可以帮助团队成员独立开发各自的模块,而不必过于依赖其他人
另外当我们出现人员流动时(有人入职或者离职),可以快速的应对。
有人入职,可以快速分配任务,协作开发。
有人离职,不影响其他模块的迭代,项目有序推进。
这是一个好的项目架构的前提
模块解耦
解耦是指在设计和开发过程中,使各模块之间的依赖最小化
能够使代码更加灵活 易于维护和扩展 这对于大型项目或者长期维护项目非常重要,因为它降低了修改某个模块时对其他模块的影响
尽量每个模块需要做到高内聚 低耦合
项目架构的实现(一)采用模块化的架构设计
Utils工具封装模块:
- 将项目中通用的工具函数封装在utils目录中,比如日期格式化函数、数据处理函数等
- 这些工具函数应该是纯函数,保证输入相同输出相同,不依赖于外部状态
- 将工具函数分模块管理,并在index.js中集中导出,以便在项目的其他地方直接导入使用
Store状态管理模块:
- 在Vue项目中,可以通过Pinia的模块化设计来管理状态
- 每个页面或功能模块有自己的store模块,如userStorejs、productStorejs等
- 同时,可以创建一个公共store模块commonStore.js用于存放应用级别的状态,如全局loading状态等
- 组件、页面的模块开发
Vue源码相关架构
- 从大的模块来说,它的渲染器、编译器、响应式系统是划分清晰的
- 响应式系统和编译器可以作为独立的模块来开发和使用,渲染器依赖于响应式系统和编译器
- 从小的模块来说,它的调度系统、watch、watchEffect等又单独做了分离,包括keep-alive、suspense、teleport都可以作为一个独立的模块来开发,再集成到整个Vue项目中。
项目架构的实现二 其他方面的设计
Webpack和Vite的优化
代码分割(CodeSplitting):Webpack和Vite都支持代码分割,这有助于只加载需要的模块,减少初始加载时间并提高性能
动态导入(DynamicImport):使用动态导入可以根据需要懒加载模块,进一步降低加载时间。
TreeShaking:通过去除未使用的代码来优化最终输出文件的大小。Webpack和Vite都有内置的支持
使用版本控制和分支策略
Git工作流:团队可以采用Git工作流,比如GitFlow,以确保开发人员在不同的分支上独立工作,然后通过合并请求(pullrequests)进行代码审查和集成
代码审查codereview:代码审查是协同开发的重要部分,确保代码质量和一致性,同时让团队成员对代码变更保持透明(包括ESlint、Prettier等)
其他方面的考虑
持续集成/持续部署(CI/CD)工具的使用:利用CI/CD管理和自动化部署流程,确保团队开发的一致性,提高测试和部署的效率
文档和沟通:良好的文档、沟通机制来确保团队协同工作,特别是在项目架构和代码约定方面
项目开发
项目开发框架相关优化(Vue)
合理使用v-if和v-show
v-if用于条件变化不频繁的场景,避免不必要的组件创建和销毁
v-show用于频繁切换显示状态的场景,通过控制CSS的display属性来提升性能避免不必要的组件染:
避免不必要的组件重渲染
使用key确保组件唯一性,避免不必要的DOM更新
使用v-once指令确保不变的数据只渲染一次。
合理使用Vue生命周期勾子,控制组件是否需要重新渲染
组件懒加载(LazyLoading)
使用动态import实现按需加载组件,减少初始加载时间
使用Vue的computed
使用computed属性缓存计算结果,避免重复计算
状态下沉
根据虚拟DOM更新特性,将状态下沉到子组件,避免全局或父组件频繁更新
合理使用Keep-Alive
使用<keep-alive>组件缓存动态组件,避免不必要的组件销和创建
项目开发-公共开发代码优化
减少不必要的计算
避免在染过程中进行大量计算,将重计算操作放在适当位置,如computed或方法调用
抖动(Debouncing)和节流(Throttling)
在频繁触发的事件(如滚动、输入)上使用去抖动和节流,减少事件处理频率
优化循环和选代
优化循环使用,比如获取长度在外部获取arr.length,避免在循环中创建新对象和数组等
使用WebWorkers
将繁重计算任务移到WebWorkers中,避免阻塞主线程,保持流畅性
避免内存泄漏
在组件销毁时清理定时器、事件监听器,闭包小心内存泄漏等资源,避免内存泄漏
使用现代图片格式和精图
使用WebP、AVIF等格式减少图片文件大小,加快加载速度,对图片进行压缩处理。
精灵图的使用,页面只需要发送一次请求来加载这张大图,而不是为每个小图标发送多个请求,这可以显著减少HTTP请求的数量,降低网络开销。
图片懒加载
使用懒加载技术只加载可视区域的图片,减少初始加载时间和带宽消耗CSS选择器优化
使用简单有效的选择器,避免复杂的选择器链,提高染性能
避免回流和重绘
尽量减少DOM操作,使用批量更新,优化回流和重绘性能。
使用transform和opacity进行动画效果,避免触发回流
使用CSS动画
优先使用CSS动画而JavaScript动画,提升性能
项目开发-其他方面优化
服务端渲染(SSR):
SSR(服务端染)是在服务器端预先染页面,并将完整的HTML发送到客户端SSR提高了首屏染速度,特别适用于SEO需求强的项目和需要快速加载的应用
代码压缩和混滑
使用Terser等工具压缩JavaScript,减少文件大小
压缩CSS和HTML文件,优化代码传输速度
按需加载和代码拆分
使用Webpack、vite等工具实现代码拆分,按需加载模块
第三方包按需引入
使用Babel插件或Vite配置,按需引入UI库组件,减小打包体积
使用虚拟列表等技术
在处理长列表时,使用虚拟滚动技术,只染可视区域的元素,提升性能
项目部署 优化手段
CDN使用和配置
CDN(内容分发网络)是一组分布在多个地理位置的服务器,用于加速静态资源(如图片、CSS、JavaScript文件等)的传输通过将资源缓存到离用户更近的服务器上,CDN可以显著减少资源加载时间,提升用户体验 。选择可靠的CDN提供商,根据目标用户群体的位置选择最佳的CDN服务器节点。
将静态资源托管到CDN提供商(如阿里云、腾讯云、Cloudflare、AWSCloud等)上
配置构建工具(如Webpack或vite)输出静态资源的路径
首屏渲染速度优化
将首屏染所需的关键CSS内联到HTML中,减少CSS阻塞染的时间,也可以整合网络请求。
使用async或defer属性来异步加载JavaScript脚本,避免阻塞染
通过按需加载(LazyLoading)和代码分割(CodeSplitting)技术,将非关键代码分 减少初始加载时间。
当然也包括我们前面架构中提到的SSR技术。
HTTP缓存策略
HTTP缓存策路通过在客户端缓存静态资源 避免重复请求,减少服务器负载和页面加载时间。
设置适当的HTTP缓存头(如Cache-Control、ETag和Expires),为静态资源设置缓存策略
根据文件的特性,设置强制缓存(Cache-Control和Expires),比如JS文件、CSS文件等(可以结合文件指纹hash,在文件更新时文件生成新的文件名,让客户端可以加载新的文件)。
对于频繁更新的文件,使用协商缓存((ETag和Last-Modified)),比如如果HTML页面经常变更(可以让浏览器根据页面内容变化判断是否需要重新加载)。
代码压缩和优化
代码压缩和优化是通过去除多余的空格、注、代码缩 (例如将变量名缩短) 当然也包括Treeshaking等方式减少文件大小 加快传输速度
使用构建工具(如Webpack ite)压缩插件(如Terser)对JavaScript代码行压缩和优化 玉缩CSS和HTML文件,减少文件体积。
可以使用诸如TinyPNG、mageoptim、 squoosh等工具对图片进行压缩 减少图片文件的大小
对图标和简单的图形 可以使用SVG格式 这种格式不仅文件小 而且可以无损缩放。
文件压缩是通过压缩算法(如gzip、减少文件体积的技术,可以显著减少文本文件(如HTML、CSS、JavaScript)和部分图像文件的体积,降低网络传输时间(实现也非常简单,在服务器中中启用gzip或Brotli压缩即可)。
减少和优化资源请求
减少DNS查询 通过将多个资源托管在一域名下,减少DNS查询的时间。
对于必须跨域的资源,使用DNS预解析(<link rel=dns-prefetch”href=//zhaimou.com”>)
通过异步加载或延加载(如使用async或defer)减少第三方脚本对页面加载速度的影响。
预加载(Preload)和预获取(Prefetch):
使用<linkrel=“preload href=”/path/to/resourceas=script/style>来预加载关键资源
使用<linkrel=“prefetch” href=”/path/to/resource">来预获取未来可能需要的资源!
文章到这里就结束了,更多作为自我学习,也希望对你有所帮助
相关文章:

前端性能优化 面试如何完美回答
前言 性能优化是目前在面试中被问到非常多的问题,主要就是通过各种算和技术来提高页和应用的速度和用户体前端性能优化的问题并不好回答 在回答的时候干万不要掉进一个误区,认为性能优化只是几个技术点而已,事实上性能优化涉及到的是多方面的…...

程序猿成长之路之设计模式篇——设计模式简介
无论是对于代码质量还是代码可维护性、可扩展性,使用合适的设计模式都能够起到促进提升的作用,此外在软考的软件工程师、系统架构师职称考试中,设计模式也是必考的一块内容,因此我打算开拓一个新的专栏简单介绍一下设计模式&#…...

基于Node2Vec的图嵌入实现过程
目录 一、引言二、Node2Vec(原理)2.1 随机游走(Random Walk)2.2 嵌入学习2.3 Node2Vec 的优势 三、使用 Node2Vec 进行图嵌入(实践)3.1 读取和转换 JSON 文件为 Graph 对象3.2 训练 Node2Vec 模型3.3 二维嵌…...

国庆刷题(day4)
C语言: C:...

如何在 Python 3 中制作一个计算器程序
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 Python 编程语言是处理数字和求解数学表达式的强大工具。这种特性可以用来制作有用的程序。 本教程介绍了如何在 Python 3 中制作…...

搭建shopify本地开发环境
虽然shopify提供了在线编辑器的功能,但是远不及本地编辑器方便高效,这篇文章主要介绍如何在本地搭建shopify开发环境: 1、安装nodejs 18.2 2、安装git 3、安装shopify cli ,使用指令: npm install -g shopify/clilatest 4、安装ruby 5、…...

【在Linux世界中追寻伟大的One Piece】进程信号
目录 1 -> 信号入门 1.1 -> 生活角度的信号 1.2 -> 技术应用角度的信号 1.3 -> 注意 2 -> 信号的概念 2.1 -> 用kill -l命令可以查看系统定义的信号列表 2.2 -> 信号处理常见方式 3 -> 产生信号 3.1 -> Core Dump 3.2 -> 调用系统函数…...

MySQL中NULL值是否会影响索引的使用
MySQL中NULL值是否会影响索引的使用 为何写这一篇文章 🐭🐭在面试的时候被问到NULL值是否会走索引的时候,感到有点不理解,于是事后就有了这篇文章 问题: 为name建立索引,name可以为空select * from user …...

Chrome 浏览器:现代网络浏览的先锋
Chrome 浏览器:现代网络浏览的先锋 Chrome 浏览器,由谷歌公司开发的一款快速、简单且安全的网络浏览器,自2008年发布以来,已经成为全球最受欢迎的浏览器之一。本文将深入探讨 Chrome 浏览器的特点、功能、发展历程以及其对现代网…...

蓝牙定位的MATLAB仿真程序(基于信号强度,平面内的定位,四个蓝牙基站)
这段代码通过RSSI信号强度实现了蓝牙定位,展示了如何使用锚点位置和测量的信号强度来估计未知点的位置。它涵盖了信号衰减模型、距离计算和最小二乘法估计等基本概念。通过图形化输出,用户可以直观地看到真实位置与估计位置的关系。 文章目录 蓝牙定位原理蓝牙定位的原理优缺…...

解决docker一直出现“=> ERROR [internal] load metadata for docker.io/library/xxx“的问题
docker拉取镜像时报错,除标题外,还报如下信息 此时想到是不是拉取超时呢,然后配置了一下docker拉取镜像源 vm /etc/docker/daemon.json { "registry-mirrors": ["https://jq794zz5.mirror.aliyuncs.com"] } # 重新加载配…...

Django学习笔记五:templates使用详解
Django的模板系统是一个强大的工具,用于将动态数据渲染到HTML页面中。以下是Django模板系统的详细用法: 模板的基本概念 Django模板使用一个特殊的语法来插入变量、标签和过滤器。 创建模板 创建模板目录:在你的Django应用中创建一个名为…...

PriorityQueue分析
概述 PriorityQueue,优先级队列,一种特殊的队列,作用是能保证每次取出的元素都是队列中权值最小的(Java的优先队列每次取最小元素,C的优先队列每次取最大元素)。元素大小的评判可以通过元素本身的自然顺序…...

Hive数仓操作(六)
一、 Hive 分区表 Hive 的分区表通过在 HDFS 中以不同的目录存储不同的分区数据,来提高查询性能并减少数据扫描量。分区表可以根据特定的列(如 性别 列的男/女)将数据划分为多个部分,使得查询时只需要扫描相关的分区,…...

centos7安装配置python3环境
1、wget https://www.python.org/ftp/python/3.11.2/Python-3.11.2.tgz 2、安装python依赖环境 切换到root用户,然后执行下面命令: 3、安装gcc,用于后续安装Python时编译源码: yum install gcc -y 4、安装Python3相关依赖&#…...

用 LoRA 微调 Stable Diffusion:拆开炼丹炉,动手实现你的第一次 AI 绘画
总得拆开炼丹炉看看是什么样的。这篇文章将带你从代码层面一步步实现 AI 文本生成图像(Text-to-Image)中的 LoRA 微调过程,你将: 了解 Trigger Words(触发词)到底是什么,以及它们如何影响生成结…...

手机实时提取SIM卡打电话的信令声音-(题外、插播一条广告)
手机实时提取SIM卡打电话的信令声音-(题外、插播一条广告) 前言 在去年的差不多这个时候,我们做了一遍外置配件的选型,筛选过滤了一批USB蓝牙配件和type-c转usb的模块。详情可参考《外置配件的电商价格和下载链接的选型.docx》一文:蓝牙电话…...

Linux基于CentOS学习【进程状态】【进程优先级】【调度与切换】【进程挂起】【进程饥饿】
目录 进程状态 状态决定了什么 进程等待方式——队列 进程状态的表现 挂起状态 基于阻塞的挂起——阻塞挂起 swap分区 进程状态表示 Z僵尸状态 进程的优先级 什么是进程的优先级 为什么会有进程的优先级 进程饥饿 Linux的调度与切换 切换 调度 queue [ 140 ]&am…...

Golang | Leetcode Golang题解之第456题132模式
题目: 题解: func find132pattern(nums []int) bool {candidateI, candidateJ : []int{-nums[0]}, []int{-nums[0]}for _, v : range nums[1:] {idxI : sort.SearchInts(candidateI, 1-v)idxJ : sort.SearchInts(candidateJ, -v)if idxI < idxJ {ret…...

回归预测|基于哈里斯鹰优化最小二乘支持向量机的数据回归预测Matlab程序HHO-LSSVM 多特征输入单输出含基础程序
回归预测|基于哈里斯鹰优化最小二乘支持向量机的数据回归预测Matlab程序HHO-LSSVM 多特征输入单输出含基础程序 文章目录 一、基本原理一、基本原理二、HHO-LSSVM的流程三、优缺点四、应用场景 二、实验结果三、核心代码四、代码获取五、总结 一、基本原理 HHO-LSSVM回归预测结…...

【Android 源码分析】Activity生命周期之onStop-1
忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。 – 服装…...

【Unity】本地化实现
个人向笔记。 1 前言 记录一下自己的本地化实现思路,暂时只讲本文的本地化实现。 2 文本本地化方案-个人 本地化实现是基于Luban的。自己使用Luban实现了一个“配置表模块”,又实现了一个“全局配置模块”,之后再基于这两个模块实现了“文本…...

Django一分钟:在Django中怎么存储树形结构的数据,DRF校验递归嵌套模型的替代方案
引言 在开发过程中我们可能需要这样的树形结构: [{"data": {"name": "牛奶"},"children": [{"data": {"name": "蒙牛"}, },{"data": {"name": "伊利"}, }]},{"da…...

【Docker从入门到进阶】06.常见问题与解决方案 07.总结与资源
6. 常见问题与解决方案 在使用Docker进行开发和部署过程中,可能会遇到各种问题。以下是一些常见问题及其解决方案: 容器启动失败和调试 在使用 Docker 时,容器启动失败或立即退出可能会导致一定的困扰,以下是进一步深入解决该问…...

快速排序的非递归实现:借助栈实现、借助队列实现
目录 用栈实现快速排序 1.用栈实现非递归快速排序的思路步骤 1.1.思路步骤 2.用栈实现非递归快速排序的代码 3.用栈实现非递归快速排序的整个工程 3.1.QuickSortNonR.h 3.2.QuickSortNonR.c 3.3.Stack.h 3.4.Stack.c 用队列实现非递归快速排序 1.用队列实现非递归快…...

Finops成本优化企业实践-可视化篇
引言:上一章讨论了finops的一些方法论,笔者在拿到finops官方认证finops-engineer certificate之后,将方法论运用到所在项目组中,并于今年完成了40%的费用节省。在此将这些实践方法总结沉淀,与大家分享。实践包括三篇&a…...

Spring Boot中线程池使用
说明:在一些场景,如导入数据,批量插入数据库,使用常规方法,需要等待较长时间,而使用线程池可以提高效率。本文介绍如何在Spring Boot中使用线程池来批量插入数据。 搭建环境 首先,创建一个Spr…...

Python机器学习:自然语言处理、计算机视觉与强化学习
📘 Python机器学习:自然语言处理、计算机视觉与强化学习 目录 ✨ 自然语言处理(NLP) 文本预处理:分词、去停用词词向量与文本分类:使用Word2Vec与BERT 🌆 计算机视觉基础 图像预处理与增强目标…...

Vue2 + ElementUI + axios + VueRouter入门
之前没有pc端开发基础,工作需要使用若依框架进行了一年的前端开发.最近看到一个视频框架一步步集成,感觉颇受启发,在此记录一下学习心得。视频链接:vue2element ui 快速入门 环境搭建和依赖安装 安装nodejs安装Vue Cli使用vue create proje…...

GO网络编程(四):海量用户通信系统2:登录功能核心【重难点】
目录 一、C/S详细通信流程图二、消息类型定义与json标签1. 消息类型定义2. JSON标签3.结构体示例及其 JSON 表示:4.完整代码与使用说明 三、客户端发送消息1. 连接到服务器2. 准备发送消息3. 创建 LoginMes 并序列化4. 将序列化后的数据嵌入消息结构5. 序列化整个 M…...