一份超级详细的前端优化指北

660 阅读7分钟

网络策略优化

使用dns-prefetch

dns-prefetch 是DNS的预解析技术,浏览网页时,浏览器会在加载网页时对网页中的域名进行解析缓存,这样在单击当前网页中的连接时就无需进行DNS的解析,减少用户等待时间,提高用户体验。
dns预解析是与页面加载是并行处理的,且不会影响到页面加载的性能.
访问以图片为主的移动端网站时,使用DNS预解析的情意中下页面加载时间可以减少5%
设置:

<meta http-equiv="x-dns-prefetch-control" content="on" />
<link rel="dns-prefetch" href="http://www.baidu.com" />

禁止隐式的dns预解析:

<meta http-equiv="x-dns-prefetch-control" content="off">

减少http请求

  • 合并js文件 css文件
  • 使用雪碧图
  • base64编码图片

使用http缓存

  • 强缓存 静态资源文件 使用hash命名 文件没有修改直接从缓存中获取
  • 协商缓存 一般入口index.html 设置协商缓存 每次请求都向服务端发送请求判断资源是否有修改

使用http2.0

  • 多路复用: 数据分帧处理
  • 头部压缩
  • 服务器主动推送

避免重定向

301 302 重定向会降低响应速度

CDN存放静态资源

CDN能非常有效的加快网站静态资源的访问速度

资源压缩

gzip压缩 js css html 图片压缩

合理使用preload prefetch

preload 预加载 当前页面使用的资源 prefetch 页面空闲时间加载 提前加载之后可能会用到的资源 不一定是当前页面使用的

<link rel="preload" as="style" href="index.css">

<link rel="prefetch" as="style" href="index.css">

浏览器渲染优化策略

  • 避免页面的重排重绘
  • 使用css3合成动画 开启gpu加速 减少cpu压力
  • 图片渲染时添加宽高属性 宽高固定 图片不会根据内容动态改变宽高 便不会触发重排重绘
  • 使用will-change: transform;将元素独立为一个单独的图层。(定位、透明、transform、clip都会产生独立图层)

导致重排操作:

  • 页面首次渲染(无可避免)
  • 浏览器窗口大小改变
  • 元素尺寸改变 (宽高 边框 边距)
  • 元素内容发生变化 (文字数量 文字字体大小 图片大小)
  • 添加或者删除可见的元素
  • 激活伪类 :hover
  • 查询属性 或者调用某些方法:(属性和方法都需要返回最新的布局信息,因此浏览器不得不触发回流重绘来返回正确的值) offsetTop getComputedStyle() getBoundingClientRect() scrollIntoView() clientTop() scrollHeight()

如何优化:

  • 合并style样式的修改 使用css统一修改
  • 减少dom的直接获取 dom的直接获取会导致强制重排获取最新的信息
  • 使用transform替代position
  • 使用display:none 隐藏元素后 进行修改 修改完成 设置 显示
  • 通过 documentFragment 创建一个 dom 文档片段,在它上面批量操作 dom,操作完成之后,再添加到文档中,这样只会触发一次重排
  • GPU 加速通常包括以下几个部分:Canvas2D,布局合成, CSS3转换(transitions),CSS3 3D变换(transforms),WebGL和视频(video)。

静态资源优化

合理选择图片格式

  • jpg: 适合色彩丰富的图、Banner图。不适合:图形文字、图标、不支持透明度
  • png: 适合纯色、透明、图标,支持纯透明和半透明。不适合色彩丰富图片,因为无损储存会导致储存体积大于jpeg
  • gif: 适合动画、可以动的图标。支持纯透明但不支持半透明,不适合色彩丰富的图片。埋点信息通常也会使用gif发送,因为1x1的gif图发送的网络请求比普通的get请求要小一些
  • webp: 支持纯透明和半透明,可以保证图片质量和较小的体积,适合Chrome和移动端浏览器。不适合其他浏览器。
  • svg: 矢量格式,大小非常小,但渲染成本过高,适合小且色彩单一的图标

图片优化

  • 减少图片尺寸大小 节约流量
  • 设置alt属性 图片无法显示时会展示的内容
  • srcset size属性在不同设备大小下的设置
  • 使用base64 减少图片请求
  • 雪碧图合并图片

HTML优化

  • 使用语义化标签 meta设置TDK 利于SEO
  • 减少标签嵌套 减少dom数量
  • 避免table布局
  • 提前声明字符编码,让浏览器快速确定如何渲染网页内容
<html lang="en">
    <meta charset="UTF-8">
 </html>
  • 减少iframe,子iframe会阻塞父级的onload事件。可以使用js动态给iframe赋值,就能解决这个问题。

CSS优化

  • 减少伪类选择器,减少选择器层数、减少通配符选择器、减少正则选择器
  • 避免使用css表达式
  • css使用外链 可以使用缓存
  • link标签上添加媒体字段 只加载有效的css
<link href="a.css" media="screnn and (max-width: 600px)">
  • 减少@import 使用 因为他使用串行加载 会等到页面加载完成后再加载,导致页面没有样式出现

JS优化

  • script标签使用defer async 属性 异步加载js文件
  • 减少dom操作 避免反复获取dom 对获取的dom进行缓存(js是js线程 dom是渲染线程 频繁获取dom会造成多次线程之间通信)
  • 使用document.documentFragment。避免频繁访问dom
  • 使用webworker执行复杂的计算
  • 虚拟滚动 懒加载
  • 使用requestAnimationFrame实现动画 requestIdleCallback 进行空闲时任务处理
  • 使用事件委托
  • 尽量使用canvas css3动画
  • 使用节流防抖避免频繁触发事件

webpack优化

减小包体积

  • tree-shaking 删除项目中未被引用的代码 Webpack4 开启生产环境就会自动启动这个优化功能。 静态编译时,在ast中分析哪些没有被使用到,然后删除

  • Scope Hoisting 会分析出模块之间的依赖关系,尽可能的把打包出来的模块合并到一个函数中去 Webpack4 中你希望开启这个功能,只需要启用 optimization.concatenateModules 就可以了。

module.exports = {
  optimization: {
    concatenateModules: true
  }
}
  • purgecss-webpack-plugin 清除无用css

webpack打包构建优化

  • HappyPack 开启多个线程 loader的编译并行执行(webpack5弃用)
  • minicssextractPlugin: 将css抽离 单独打包 支持按需加载 异步加载 不会重复编译 只适用于css
  • hardSourcewebpackPlugin 为模块提供中间缓存 缓存存放路径 node-modules/.cache/hard-source 首次构建无太大变化,二次构建 时间减少约80%

优化resolve配置

  • alias 简化模块的引用
 resolve:{
  alias: {
    '~': resolve('src'),
    '@': resolve('src'),
    'components': resolve('src/components')
  }
}
  • extensions 省略文件后缀 按照数组从左到右顺序解析模块
    注意:高频文件放到前面,手动配置后默认配置会失效 保留默认配置 可使用... 代表
const config = {
//...
resolve: {
  extensions: ['.js', '.json', '.wasm'],
},
};
  • modules 告诉webpack解析模块时应该优先搜索的目录 减少依赖文件查找时间
    webpack 优先查找src下目录,
const path = require('path');

// 路径处理方法
function resolve(dir){
return path.join(__dirname, dir);
}

const config = {
resolve: {
  modules: [resolve('src'), 'node_modules'],
},
};
  • externals 配置从输出的bundle中排除依赖的方法 从cdn引入的jquery不需要打包 直接使用链接
const config = {
 externals: {
   jquery: 'jQuery',
 },
};

Vue优化

  • v-if 和 v-show的合理选择
  • 使用计算属性computed缓存计算结果
  • 使用keep-alive缓存组件状态
  • 保证key的唯一性
  • import() 路由懒加载 按需引入组件
  • 在destroy生命周期销毁 事件监听 定时器

React优化

  • 组件状态变与不变分离
  • React.memo 缓存组件
  • useMemo 缓存大量计算
  • useCallback 缓存函数的引用
  • React.pureComponent 纯组件 自带shouldComponentUpdate功能
  • shouldComponentUpdate 生命周期进行状态比较
  • 避免使用内联对象 react会在每次渲染时重新生成内联对象引用 这会导致此组件prop发生改变 浅比较始终返回false 导致组件重复渲染
  • 避免在组件上使用匿名函数
  • 延迟加载 按需加载组件React.lazy React.suspense
  • 使用React.Fragement 避免生成额外的dom元素