美文网首页
性能优化探索

性能优化探索

作者: halowyn | 来源:发表于2021-03-15 17:29 被阅读0次

性能优化指标

  • 加载指标
    • speedIndex速度指数:代表页面内容渲染所消耗的时间
    • TTFB:是 Time to First Byte 的缩写,指的是浏览器开始收到服务器响应数据的时间(后台处理时间+重定向时间),是反映服务端响应速度的重要指标,TTFB 时间如果超过了 500 ms,用户在打开网页的时候就会感觉到明显的等待
    • 页面加载时间
    • 首次渲染: 渐进式加载
  • 响应指标
    • 交互动作的反馈时间
    • 帧率FPS :是指画面每秒传输[帧数],通俗来讲就是指动画或视频的画面数,每秒钟帧数越多,所显示的动作就会越流畅
    • 异步请求的完成时间

RAIL测量模型(量化性能优化指标/RAIL评估标准)

  1. Response 响应:处理事件应在50ms以内完成,这样给用户的感受是瞬间就完成了

    • 事件处理函数在50ms内完成,考虑到idle task的情况,事件会排队,等待时间大概在50ms。适用于click,toggle,starting animations等,不适用于drag和scroll。
    • 复杂的js计算尽可能放在后台,如web worker,避免对用户输入造成阻塞
    • 超过50ms的响应,一定要提供反馈,比如倒计时,进度百分比等。
  2. Animation 动画:每10ms产生一帧

    • 在一些高压点上,比如动画,不要去挑战cpu,尽可能地少做事,如:取offset,设置style等操作。尽可能地保证60帧的体验。
    • 在渲染性能上,针对不同的动画做一些特定优化
  3. Idle 空闲:尽可能增加空闲时间

    • 用空闲时间来完成一些延后的工作,如先加载页面可见的部分,然后利用空闲时间加载剩余部分,此处可以使用 requestIdleCallback API
    • 在空闲时间内执行的任务尽量控制在50ms以内,如果更长的话,会影响input handle的pending时间
    • 如果用户在空闲时间任务进行时进行交互,必须以此为最高优先级,并暂停空闲时间的任务
  4. Load 加载:在5s内完成内容的加载并可以交互

分析RAIL用的性能测量工具

  1. chrome DevTools开发调试、性能评测
    audit Lighthouse
    throttling 调整网络吞吐量
    performance
    network

  2. Lighthouse网站整体质量评估,也可以直接使用chrome DevTools中的lighthouse

        npm i -g lighthouse
        lighthouse http://www.bilibili.com
    
  1. WebpageTest多测试地点、全面性能报告解读
    • waterfall chart请求瀑布图
    • first view 首次访问
    • repeat view 二次访问(反映缓存的优化情况)
    • WebpageTest在线配置
    • 本地配置WebpageTest(安装docker)

性能优化策略

一、渲染优化


  1. 关键渲染路径:

    • javascript(触发视觉变化)
    • style计算样式
    • layout布局
    • paint绘制
    • composite复合
  2. 影响回流的操作 reflow

    1. 添加/删除元素
    2. 操作styles
    3. display: none
    4. offsetLeft, scrollTop, clientWidth
    5. 移动元素位置
    6. 修改浏览器大小,字体
  3. 避免布局抖动(layout thrashing )

    1. 避免回流
      • transform/translate进行复合
    2. 读写分离
      • 解决方案FastDom
      • measure和mutate方法的使用
  4. 复合线程(compositor thread)与图层(layer)
    将页面拆分图层进行绘制再进行复合
    利用DevTools了解网页的图层拆分情况
    哪些样式仅影响复合

  5. 减少重绘的方案
    利用devTools发现paint的瓶颈
    will-change创建新的图层

  6. 高频事件处理函数 防抖 (requestAnimationFrame)

二、 代码优化


  1. code splitting代码拆分,按需加载
  2. tree shaking 代码减重
  3. 减少主线程工作量
    避免长任务
    避免超过1kb的行间脚本
    使用rAF和rIC进行实践调度
  • V8优化机制(js代码优化原理)
    • 脚本流
    • 字节码缓存
    • 懒解析
  1. 函数优化

  2. 函数解析方式

    • lazy parsing VS eager parsing
    • 利用optimize.js优化初次加载时间
    • 直接使用uglify.js优化
  3. 对象优化

    • 以相同顺序初始化对象成员,避免隐藏类的调整
    • 实例化后避免添加新属性
    • 尽量使用Array代替array-like对象
    // bad
    Array.prototype.forEach.call(arrObj, (value, index) => {
        console.log(`${index}:${value}`)
    })
    
    // good
    const arr = Array.prototype.slice.call(arrObj, 0)
    arr.prototype.forEach.call(arrObj, (value, index) => {
        console.log(`${index}: finger ${value}`)
    })
    
    • 避免读取超过数组的长度
    functon foo (arr) {
        for(let i = 0; i <= arr.length; i++) { // 越界
            if (arr[i] > 1000) { // 1. 造成undefined跟数组进行比较 2.造成沿原型链的额外查找
            console.log(arr[i])}
        }
    }
    // 10, 100, 1000[]
    
    • 避免元素类型转换
    const arr = [3, 2, 1] // PACKED_SMI_ELEMENTS
    arr.push(4.4) // PACKED_DOUBLE_ELEMENTS 优化降级
    

三、HTML优化


  1. 减少iframes的使用(可以延迟加载)

    <iframe id='a'></iframe>
    document.getElementById('a').setAttribute('src', 'url')
    
  2. 压缩空白符

  3. 避免节点深层级嵌套

  4. 避免使用table布局

  5. 删除注释

  6. CSS&Javascript尽量外链

  7. 删除元素的默认属性

  • 借助工具
    html-minifier

四、 CSS优化


自右向左过滤样式

  1. 降低css对渲染的阻塞
  2. 利用GPU进行完成动画
  3. 使用contain: layout(对元素单独处理不会影响其他元素)
  4. 使用font-display属性

五、 资源的压缩与合并


  1. 减少http请求数量
  2. 减少请求资源本身的大小

HTML压缩

  • 使用在线工具进行压缩
  • 使用html-minifier等npm压缩工具

CSS压缩

  • 使用在线工具进行压缩
  • 使用clean-css等npm工具

JS压缩与混淆

  • 使用在线工具进行压缩
  • 使用webpack对js在构建时压缩

CSS JS文件合并

  • 若干小文件
  • 无冲突,服务相同的模块ok
  • 优化加载NO

六、 图片优化方案


  1. 图片JPG/JPEG(压缩比高)
    • 工具imagemin
    • 使用场景:保证画质和色彩
    • 缺陷:纹理和边缘比较粗糙
  2. png
    • 体积比较大,适合图标和logo
    • imagemin-pngquant
  3. webP
  4. svg

图片加载优化

1.懒加载

* 原生图片懒加载
* 第三方图片懒加载方案(verlok/lazyload、yall.js\Blazy)

2.渐进式图片(清晰度由低到高)

* progressive-image
* imageMagick
* libjpeg
* jpegtran
* jpeg-recompress
* imagemin
  1. 响应式图片

    • srcset属性的使用(提供多个尺寸下对应的图片)
    • sizes属性的使用()
    • picture的使用

字体优化

  • @font-face
  • font-display: auto/block/swap/fallback/optional
  • ajax+base64:解决了兼容性问题

七、webpack优化


  1. tree-shaking
    • 上下文未用到的代码
    • 基于es6 import export
    • 全局作用于sideEffects: ['*.css']
    • 注意babel默认配置的影响
  2. js压缩
    • webpack4后引入uglifyjs-webpack-plugin
    • 支持es6替换为terser-webpack-plugin
    • 减小js文件体积
  3. 作用域提升
  4. babel7优化配置
    • 在需要的地方引入polyfill, useBultIns: usage
    • 辅助函数的按需引入
    • 根据目标浏览器按需转换代码

webpack依赖优化

  1. noParse

    • 提高构建速度
    • 直接通知webpack忽略较大的库
    • 被忽略的库不能用import、require、define的引入方式
  2. dllPlugin(主要用在开发环境打包)

    • 避免打包时对不变的库重复构建
    • 提高构建速度

基于webpack的代码拆分

把单个bundle文件拆分成多个小的bundle/chunk
提高首屏加载速度

  1. 手工定义人口
  2. 动态加载改造
  3. split-chunks提取共有代码,拆分业务代码与第三方库
optimizaton: {
    splitChunks: {
        cacheGroups: {
            vendor: {
                name: 'vendor',
                test: [匹配node_modules],
                minsize: 0,
                minChunks: 1, // 最少段数
                priority: 10, // 拆分优先级
                chunks: 'initial'
            }
        } 
    }
},
common: {
    name:'common',
    test: [匹配src],
    chunks: 'all'
    minsize: 0,
    minChunks: 1 // 最少段数
}

基于webpack的资源压缩(minification)

  1. terser压缩js
  2. mini-css-extract-plugin 压缩css
  3. HtmlWebpackPlugin-minify压缩HTML

基于webpack的资源持久化缓存

  1. 每个打败的资源文件有唯一的hash值
  2. 修改后只有受影响的文件hash变化
  3. 充分利用浏览器缓存
output: {
    path: `${__dirname}/build`,
    filename: '[name].[hash].bundle.js'
    chunkFilename: '[name].[chunkhash:8].bundle.js'
}

基于webpack应用的监测与分析

  1. stats分析与可视化图,webpack chart

    webpack --profile --json >stats.json
    
  2. webpack-bundle-analyzer进行体积分析

    source-map-explorer(基于sourcemap生成)

  3. speed-measure-webpack-plugin速度分析

react按需加载

  1. React router基于webpack动态引入
  2. 使用reloadable高级组件

八、传输加载优化

  1. nginx配置启用压缩gzip, 对传输资源进行提及压缩,可高达90%
    gzip on
    gzip_min_length 1k // 最小文件
    gzip_comp_level 6 // 压缩级别
    gzip_types text/plain applicaton/javascript text/css text/javascript
  1. http启用Keep Alive
    • 一个持久的TCP连接,节省了连接创建时间
    • 基于nginx的配置默认开启
# keepalive_timeout 0 // 不开启
keepalive_timeout 65 // 开启
keepalive_requests 100 // 利用这个tcp链接可以发起的请求上限
  1. http缓存
    • 提高重复访问时资源加载的速度
    • 强缓存和协商缓存
      协商缓存ETag和if-no-match
      cache-control/expires
      last-modify/if-modify-since


      image.png
  2. service workers作用
    • 加速重复访问
    • 离线支持
      注意
    • 延长了首屏时间,但页面总加载时间减少
    • 兼容性
    • 只能在localhost或https下使用
  3. http/2的提升
    • 二进制传输(提高传输效率,对头部进行压缩)

    • 请求响应多路复用
      nginx配置http2


      image.png image.png image.png
      配置自己生成签名的证书
      image.png
      - 重启nginx
      • https形式的localhost
      • thisisunsafe
      • nginx配置http2
    • server push 服务器推送

      image.png image.png
  • 只能工作在https下
  • 适合较高的请求量
  1. 服务端渲染
    • 首屏渲染优化
    • 利于seo
    • react react-dom next(服务端渲染插件)

九、前沿优化解决方案

  1. 拯救移动端图片-svg
    1. 从png到iconfont
      • 多个图标一套字体,减少获取的请求数量和体积
      • 矢量图形可伸缩
      • 可以通过css修改大小和颜色
    2. 从iconfont到svg
      • 保存了图片能力,支持多色彩
      • 独立的矢量图形
      • xml语法,搜索引擎seo和无障碍读屏软件读取
  2. 使用flexbox优化布局
    • 更高性能的实现方案(相对于float:render和paint的时间更短)
    • 容器有能力决定自元素的大小、顺序、对齐、间隔等
    • 双向布局
  3. 优化资源加载顺序
    • 浏览器默认安排资源加载优先级(html解析)
    • 使用preload、prefetch调整优先级
      • preload:提前加载较晚出现,但对当前页面比较重要的资源
      • prefetch:提前加载后续路由需要的资源,优先级低
      • webpack中也可以设置preload/prefetch
  4. 预渲染页面
    • react-snap
      • (配置postbuild)
      • 使用ReactDom-hydrate
      • 内敛样式,避免明显的FOUC(样式闪动)
    • 大型单页应用的性能瓶颈:js下载+解析+执行
    • ssr的主要问题:牺牲TTFB来补救Firdt Paint;实现复杂
    • Pre-rendering打包时提前渲染页面,没有服务端参与
  5. windowing(窗口化)提高列表性能
    • 加载大列表、大表单严重影响性能
    • lazy loading仍然会让DOM变得过大
    • windowing只渲染可建行,渲染和滚动的性能都会提升
      react-window:可避免因为数据的更新而导致大量的重新渲染。
      • 配置一个一位列表List
      • 配置一个二维列表Grid
      • 配置滚动到指定元素
  6. 使用骨架组件减少布局移动(Layout Shift)
    • skeleton/Placeholder 的作用
      • 占位
      • 提升用户感知性能
      • react-placeholder


        image.png

相关文章

  • iOS 性能优化探索

    iOS 性能优化探索

  • 2017GMTC 性能优化

    性能优化专场一共有四场分享,包括“Instagram Direct ⾼性能聊天产品”, “⼿淘iOS性能优化探索”...

  • 性能优化探索

    性能优化指标 加载指标speedIndex速度指数:代表页面内容渲染所消耗的时间TTFB:是 Time to Fi...

  • Android目录集

    Android组件化Android面试Android MVP探索Android 性能优化Android measu...

  • Android性能优化 - 消除卡顿

    性能优化系列阅读 Android性能优化 性能优化 - 消除卡顿 性能优化 - 内存优化 性能分析工具 - Tra...

  • Android性能优化 - 内存优化

    性能优化系列阅读 Android性能优化 性能优化 - 消除卡顿 性能优化- 内存优化 性能分析工具 - Trac...

  • 前端性能优化(中)

    性能优化调研系列文章 《前端性能优化(上)》 《前端性能优化(中)》 《前端性能优化(下)》 《前端性能优化(上)...

  • 前端性能优化(下)

    性能优化调研系列文章 《前端性能优化(上)》 《前端性能优化(中)》 《前端性能优化(下)》 《前端性能优化(中)...

  • Awesome Extra

    性能优化 性能优化模式 常见性能优化策略的总结 Spark 性能优化指南——基础篇 Spark 性能优化指南——高...

  • 常用的后端性能优化六种方式:缓存化+服务化+异步化等

    性能优化专题 前端性能优化 数据库性能优化 jvm和多线程优化 架构层面优化 缓存性能优化 常用的后端性能优化六大...

网友评论

      本文标题:性能优化探索

      本文链接:https://www.haomeiwen.com/subject/yzpkcltx.html