网站性能优化总结

性能优化宗旨

  1. 文件少加载
  2. 代码少执行

性能优化思路

  1. 性能监控:lighthouse 插件 和浏览器preformance工具
  2. 网络层面性能优化
  • 减少HTTP请求次数(缓存、本地存储)
  • 减少HTTP请求文件体积(文件压缩)
  • 加快HTTP请求速度(CDN)
  1. 渲染层面性能优化
  • DOM 优化
  • CSS 优化
  • JS 优化
  • 首屏渲染
  • 服务端渲染

网络层面性能优化

减少HTTP请求次数

  1. 浏览器缓存
  • Memory Cache
  • HTTP Cache
  • Service Worker Cache
  • Push Cache
  1. 本地存储
  • Web Storage(容量5-10M)
  • indexdb 运行在浏览上的非关系型数据库(容量>100M)
  • Cookies (容量4KB)

浏览器缓存--Memory Cache
MemoryCache,是指存在内存中的缓存。从优先级上来说,它是浏览器最先尝试去命中的一种缓存。从效率上来说,它是响应速度最快的一种缓存。Memory Cache一般存储体积较小的文件。

浏览器缓存--HTTP Cache
设置HTTP Header里面缓存相关的字段,实现HTTP缓存

  • 强缓存:Cache-Control,expires

Cache-Control 的几个取值含义:

private: 仅浏览器可以缓存(HTML文件可以设置避免CDN缓存)
public: 浏览器和代理服务器都可以缓存
max-age=xxx: 过期时间
no-cache: 不进行强缓存
no-store: 禁用任何缓存,每次都会向服务端发起新的请求

在设置强缓存情况下,请求返回Response Headers Cache-Control的值,如果有max-age=xxx秒,则命中强缓存,如果Cache-Control的值是no-cache,说明没命中强缓存,走协商缓存

  • 协商缓存:Etag/If-None-Match,Last-Modified/If-Modified-Since

ETag:每个文件有一个,改动文件了就变了,可以看似md5
Last-Modified:文件的修改时间

协商缓存触发条件: Cache-Control 的值为 no-cache (不强缓存)或者 max-age 过期了 (强缓存,但总有过期的时候)

协商缓存步骤总结:

在设置协商缓存情况下,在第一次请求的时候,返回的Response Headers会带有Etag/Last-Modified值。当再次请求没有命中强制缓存的时候,这个时候我们的Request Headers就会携带If-None-Match/If-Modified-Since字段,它们的值就是我们第一次请求返回给我们的Etag/Last-Modified值。服务端再拿Etag和If-None-Match,Last-Modified和If-Modified-Since来进行比较较,如果相同(命中就直接使 缓存),返回304,浏览器读取本地缓存,如果不同(没有命中)则返回200,再重新从服务端拉取新的资源。 详细内容请看 前端之浏览器缓存,一次搞定

浏览器缓存-Service Worker Cache

Service Worker 是一种独立于主线程之外的 Javascript 线程。它脱离于浏览器窗体,因此无法直接访问 DOM。这样独立的个性使得 Service Worker 的“个人行为”无法干扰页面的性能,这个“幕后工作者”可以帮我们实现离线缓存、消息推送和网络代理等功能。我们借助 Service worker 实现的离线缓存就称为Service Worker Cache ,其实现基于HTTPS。

离线缓存实例

本地存储--Web Storage

Web Storage 又分Local Storage 和 Session Storage,特色容量大5-10M它们的区别是Local Storage 永久缓存除非手动删除,Session Storage浏览器窗口关闭即失效。

减少HTTP请求文件体积

  1. 图片优化
  • 压缩图片

性能优化最有效果主要是图片压缩,因为图片的体积比较大,压缩图片效果比较显著。压缩工具 https://tinypng.com/

  • 使用webP

webP支持透明、支持动态、体积小,缺点是兼容性不好

  • 大图尽量用JPG代替PNG
  • 使用 CSS Sprites雪碧图(HTTP2不需要)
  • 使用iconfont(icon首选)
  • 使用base64(小图解决方案)
  • 复杂图形地图等使用SVG
  • 图片懒加载
  1. 资源打包压缩(webpack打包抽离公共CSS/JS)
  • MiniCssExtractPlugin插件:对CSS进行分离和压缩
  • optimization.splitChunks:抽离公共JS文件
  • optimization.minimizer :文件压缩
  1. 服务端开启gzip压缩
accept-encoding:gzip

Gzip 压缩背后的原理,是在一个文本文件中找出一些重复出现的字符串、临时替换它们,从而使整个文件变小。根据这个原理,文件中代码的重复率越高,那么压缩的效率就越高,使用 Gzip 的收益也就越大,反之亦然。开启Gzip省下了一些传输过程中的时间开销,而其代价是服务器压缩的时间开销和 CPU 开销(以及浏览器解析压缩文件的开销)。

使用CDN(内容分发网络)

CDN (Content Delivery Network,即内容分发网络)指的是一组分布在各个地区的服务器。这些服务器存储着数据的副本,因此服务器可以根据哪些服务器与用户距离最近,来满足数据的请求。 CDN 提供快速服务,较少受高流量影响,

CDN 是静态资源提速的重要手段。

渲染层次性能优化

DOM 优化

1.减少DOM操作

  • 使用虚拟DOM
  • 使用事件委托
  • 使用DOM Fragment

DocumentFragment 接口表示一个没有父级文件的最小文档对象。它被当做一个轻量版的 Document 使用,用于存储已排好版的或尚未打理好格式的XML片段。因为 DocumentFragment 不是真实 DOM 树的一部分,它的变化不会引起 DOM 树的重新渲染的操作(reflow),且不会导致性能等问题。

  • 缓存DOM结点
// 只获取一次container
let container = document.getElementById('container')
for(let count=0;count<10000;count++){ 
  container.innerHTML += '<span>我是一个小测试</span>'
} 

  • 减少使用iframe

JS 优化

  • 使用防抖截流
// 防抖:定时执行
function debounce(fn,wait=2000) {
  let setTime
  return function(...args) {
    if(setTime) clearTimeout(setTime)
     setTime = setTimeout(function() {
       fn.apply(null, args)
       clearTimeout(setTime)
     }, 2000)
  }
}
// 节流:规定时间内只取最后一次执行
 function throttle(fn,wait=3000) {
         let start= new Date()
            return function(...args) {
            if(new Date()- start> wait){
              start= new Date()
              console.log('args', args)
              fn.apply(null, args)
            }
        }
    }  

  • 避免使用全局变量
  • 避免内存泄漏
  • 删除多余代码

Tree-Shaking:ES6的mudule 已经实现的Tree-Shaking,在Webpack打包中会把冗余模块剔除掉栗子:

import { add1, add2 } from './pages'
console.log(add1)
// 本栗子add2模块代码不会被打包bundle文件

CSS 优化

  1. 有效使用选择器,避免使用calc表达式、CSS滤镜
  2. 减少重排和重绘
  • 布局优先使用flex
  • 尽量避免使用getBoundingClientRect,getComputedStyle等属性
  1. 触发渲染层(transform: translateZ(0);backface-visibility: hidden;)

服务端渲染

服务器把需要的组件或页面渲染成 HTML 字符串,然后把它返回给客户端。客户端拿到手的,是可以直接渲染然后呈现给用户的 HTML 内容,不需要为了生成 DOM 内容自己再去跑一遍 JS 代码。

const Vue = require('vue')
// 创建 个express应 
const server = require('express')()
// 提取出renderer实 
const renderer = require('vue-server-renderer').createRenderer()
server.get('*', (req, res) => { // 编写Vue实 (虚拟DOM节点) const app = new Vue({
    data: {
      url: req.url
},
// 编写模板HTML的内容
template: `<div>访问的 URL 是: {{ url }}</div>` })
// renderToString 是把Vue实 转化为真实DOM的关键 法 renderer.renderToString(app, (err, html) => {
    if (err) {
      res.status(500).end('Internal Server Error')
      return
}
// 把渲染出来的真实DOM字符 插 HTML模板中 res.end(`
      <!DOCTYPE html>
      <html lang="en">
        <head><title>Hello</title></head>
        <body>${html}</body>
      </html>
`) })
})
server.listen(8080)

首屏渲染

  1. 内联首屏关键CSS
  2. 异步加载CSS(动态插入)
  3. JS放body 底部,或者异步加载js(defer、async)

defer、async 都不会阻塞页面渲染,他们的区别是async编译完成立刻执行,defer编译完成同时还要等整个文档解析完成、DOMContentLoaded 事件即将被触发才执行

  1. 预加载 preload
<link rel="preload" href="index.js" as="script">
  1. 页面loading动画
  2. 骨架图

使用page-skeleton-webpack-plugin插件

文章参考:

前端性能优化原理与实践

前端之浏览器缓存,一次搞定

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值