前端性能优化(六):传输加载优化

news2024/11/18 6:15:57

目录

一:启用压缩 Gzip

二:启用 Keep Alive

三:HTTP 资源缓存

3.1.HTTP 缓存方案

3.2.各大网站缓存策略参考

四:Service Worker

五:HTTP2 的性能提升

5.1.HTTP2 优势

5.2.开启 HTTP2

5.3.Server Push(服务器推送)

六:服务端渲染 SSR

 6.1.基于 React Next.js 实现SSR

6.2.是否使用 SSR


一:启用压缩 Gzip

Gzip 是用来做网络资源压缩,帮助我们减少资源文件在网络传输大小的技术,可以高达 90%

如下是 MacOs安装方法,Windows 安装方法及使用可以参考:nginx for Windows

安装 homebrew:Homebrew

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

安装 nginx

brew install nginx

运行 ngix

sudo brew services start nginx

查看配置文件

vim /usr/local/etc/nginx/nginx.conf
server
{ 
  charset utf-8;                                        # 字符编码
  listen 8080;                                          # 端口
  server_name localhost;
  root E:/project;                                         # 资源文件路径
  location / { 											# 对所有路由生效的配置
    add_header Access-Control-Allow-Origin *;			# 防止跨域(生产环境需改为实际域名)
  }
}

配置 gzip:

http {
  // 开启gzip
  gzip on;
  // 文件至少1k才进行压缩
  gzip_min_length 1k;
  // 压缩级别,有1-9,压缩比例越高,对cpu的消耗也越高,权衡下取6,比较合适的值
  gzip_comp_level 6;
  // 压缩文件类型,通常会对文本类文件进行压缩,图片类一般不进行压缩
  gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/xml text/javascript application/json;
  // 对gzip已经压缩的静态资源直接利用
  gzip_static on;
  // 会在响应头部添加vary的属性,告诉客户端我们是否启用了gzip压缩
  gzip_vary on;
  // buffer优化压缩过程
  gzip_buffers 4 16k;
  // 压缩使用的http版本
  gzip_http_version 1.1;
}

此时,再次打开浏览器即可看到项目文件的传输大小比之前小了很多

二:启用 Keep Alive

这个技术可以帮助我们对 TCP 链接进行复用,也就是说当我们和一台服务器进行 TCP 建立连接之后,接下来的请求就都不需要重复建立链接。Nginx 默认开启 Keep Alive

  • 它是 HTTP 标准中的一部分,多数情况是有益无害的,所以在 HTTP1.1 以后,Keep Alive 默认开启
  • Initial connection 为 TCP 链接的建立,后续资源加载就没有 Initial connection

 可以在 Request Headers 中看到 Keep Alive 参数

如果不通过浏览器,我们还可以通过如下命令查看请求/响应的详细信息

curl -v http://127.0.0.1:8080

 同时,在 nginx.conf 配置文件中可以对Keep Alive进行配置

http {
  #keepalive_timeout  0; // 不启用Keep Alive
  keepalive_timeout  65; // 超时时间,65s内没使用TCP链接就会断掉
  keepalive_requests 100; // 客户端和服务端进行TCP链接后,会开始计数,第101个请求就需要重新建立 TCO链接
}

三:HTTP 资源缓存

作用:提高重复访问时资加载的速度

3.1.HTTP 缓存方案

  • Cache-Control/Expires
  • Last-Modified + If-Modified-Since
  • Etag + If-None-Match

Cache-Control/Expires

  • HTTP 1.0 中通过 Pragma 控制页面缓存,通常设置为 no-cache 并加上 expires: 0(立即过期,下次再用时去服务端拿)
  • HTTP 1.1 中启用 Cache-Control 来控制页面是否缓存,常用参数:no-cache、public、no-store、must-revalidate,配置后两个add_header主要是为了兼容性问题
  • 因为 JS 和 CSS 在 Webpack 里都使用 Hash 命名放,这也可以保证 HTML 更新到最新,拿到的 JS 和 CSS 也是最新的
server
{
  location / {
    index index.html index.htm;
    try_files $uri /index.html;
    if ($request_filename ~* .*\.(?:htm|html)$) {
      add_header Cache-Control "no-cache, must-revalidate";
	  add_header "Pragma" "no-cache";
	  add_header "Expires" "0";
	}
	if ($request_filename ~* .*\.(?:js|css)$) {
      expires 7d;
	}
    if ($request_filename ~* .*\.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm)$) {
      expires 7d;
	}
  }
}

客户端第一次请求一个 URL,服务器返回状态是 200,同时有一个 Last-Modified 报头的属性标记

Last-Modified:Tue, 24 Feb 2019 08:01:04 GMT

客户端第二次请求此 URL,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间是否被修改过。如果服务器资源没有变化,自动返回 304,内容为空,客户端直接从缓存中取内容即可;如果资源有变化,则向客户端发送最新资源

If-Modified-Since:Tue, 24 Feb 2019 08:01:04 GMT

现在更多的是使用Etag技术,因为Last-Modified跟时间相关,存在精准性的问题(客户端、服务端时间可能不同步),但一般使用没啥问题,且对http1.0更兼容

Etag 同理,第一次请求会服务器会返回 Etag 报头

Etag:“5d8c72a5edda8d6a:3239“

第二次请求会向服务器传送 If-None-Match 报头

If-None-Match:“5d8c72a5edda8d6a:3239“

3.2.各大网站缓存策略参考

天猫

  • max-age:设置缓存存储的周期,单位秒

  • s-maxage:只用于共享缓存,比如:CDN 缓存(s -> share)

    max-age 用于普通缓存,s-maxage 用于代理缓存

  • 它会跟服务器进行重新确认(携带 if-none-match )去确认

知乎

  • public:响应可以被任何对象(发送的客户端、代理服务器)缓存
  • private:响应只能被单个用户缓存,不能作为共享缓存(代理服务器不能缓存)
  • no-store:绝对禁止缓存
  • no-cache:资源不进行缓存,但是设置了这个不代表浏览器不缓存,而是缓存前要向服务器确认资源是否被更改,因为有时为了保险起见还会加上 private 指令或将过期时间设为过去的时间

Google 开发者

Google 开发者

  • must-revalidate:缓存必须在使用之前验证旧资源的状态,并且不可使用过期资源
  • 由于通过了 service worker,它并没有真正和服务器进行确认,可以直接去使用

四:Service Worker

  • 加速重复访问

  • 离线支持

    用户在没有网络的情况下(offline)也可以让用户访问我们的网页

serviceWorker 也有自己的生命周期,首先要注册安装激活才能使用,打包后的目录里会生成 asset-manifest.json ,里面定义了哪些资源要进行缓存、缓存文件的文件名,相关的版本信息会存在 precache-manifest 里,每个文件都有先关版本信息

同时需要使用两个插件生成 serviceWorker,一个叫 WorkboxWebpackPlugin,另一个叫 ManifestPlugin(生成 asset-manifest.json)它会决定哪些资源进行缓存,通常会把所有静态资源 HTML、CSS、JS 都进行缓存,图片或视频资源一般不会缓存

const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
const smp = new SpeedMeasurePlugin()
const WorkboxWebpackPlugin = require('workbox-webpack-plugin')
const ManifestPlugin = require('webpack-manifest-plugin')

module.exports = smp.wrap({
  plugins: [
    new WorkboxWebpackPlugin.GenerateSW({
      clientsClaim: true,
      exclude: [/\.map$/, /asset-manifest\.json$/],
      importWorkboxFrom: 'cdn',
      navigateFallback: paths.publicUrlOrPath + 'index.html',
      navigateFallbackBlacklist: [
        new RegExp('^/_'),
        new RegExp('/[^/?]+\\.[^/]+$'),
      ],
    }),

    new ManifestPlugin({
      fileName: 'asset-manifest.json',
      publicPath: paths.publicUrlOrPath,
      generate: (seed, files, entrypoints) => {
        const manifestFiles = files.reduce((manifest, file) => {
          manifest[file.name] = file.path
          return manifest
        }, seed)
        // 从入口文件开始把所有涉及到的文件全部加到asset-manifest.json里
        // app是入口文件,通常项目里的入口文件是main
        const entrypointFiles = entrypoints.app.filter(fileName => !fileName.endsWith('.map'))

        return {
          files: manifestFiles,
          entrypoints: entrypointFiles,
        }
      },
    }),
  ],
})

只需要在入口文件里注册即可

import * as serviceWorker from './serviceWorker'
serviceWorker.register()

Service Worker 原理:

在客户端和服务端建立一个中间层,做了存储

 Service Worker 注意事项:

  • 延长了首屏时间,但页面总加载时间减少

  • 兼容性

  • 只能在 localhost 或者 https 下使用(为了保证安全性)

五:HTTP2 的性能提升

HTTP1.1 问题

  • 高延迟带来页面加载速度的降低
  • 重复传输的体积巨大的 HTTP 头部
  • 不支持服务器推送消息

5.1.HTTP2 优势

1.二进制传输

HTTP 1.0/1.1 基于文本传输,效率低且不安全

HTTP 2 基于二进制编码传输,安全且能进行很好的压缩,提高了传输效率

2.请求响应多路复用

HTTP 1.1 实现是基于请求-响应模型,同一个连接中 HTTP 完成一个事务才能处理下一个事务,如果响应迟迟不来,后续请求无法发送,造成了 对头阻塞 问题。如果并发多个请求就需要多个 TCP 连接,开启 keep-alive,虽然可以用多次,但是同一时刻只能有一个 HTTP 请求

HTTP 2 所有相同域名的请求都通过一个 TCP 连接并发完成,多个 Stream 复用一条 TCP 连接

3.Server push

HTTP 1.1 不支持服务器主动推送资源给客户端,都是客户端向服务器发起请求后,才能获取到服务器响应的资源

HTTP 2 服务器可以主动推送资源文件,减少消息传递次数。客户端发起请求,必须使用奇数号 Stream,服务器主动推送,使用偶数号 Stream(会先发送 PUSH_PROMISE 帧,告诉客户端接下来在哪个 Stream 发送资源)

4.头部压缩(HTTP 协议报文是有 Header + Body 构成)

HTTP 1.1 可以使用头字段(Content-Encoding)指定 Body 压缩方式(gzip),但是 Header 没有针对它的优化手段

HTTP 2 使用 HPACK 算法进行压缩,对于常见的头通过 静态表和 Huffman 编码 方式,后续请求头,可以建立 动态表

5.2.开启 HTTP2

  • 前提需要开启HTTPS
  • 适合较高的请求量

配置https

server
{ 
  listen 843 ssl http2;
  server_name localhost;
  ssl on;
  ssl_certificate /path/to/server.crt;
  ssl_certificate_key /path/to/server.key;
  ssl_session_cache shared:SSL:1m;
  ssl_session_timeout 5m;
  ssl_ciphers HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers on;
}

生成自签名证书

执行下面的命令后得到 server.crt 和 server.key,在工程目录下新建 ssl 文件夹,将其拷贝进去

openssl genrsa -des3 -passout pass:x -out server.pass.key 2048

openssl rsa -passin pass:x -in server.pass.key -out server.key 

openssl req -new -key server.key -out server.csr 

openssl x509 -req -sha256 -days 3650 -in server.csr -signkey server.key -out server.crt 

 访问 https://localhost:843,会出现如下图。因为我们使用的是自签名证书,可能无法直接点击链接访问,解决方案是在键盘输入thisisunsafe ,页面就可以绕过证书的验证了

所有的网络资源都变成 http2 的协议了,还有 h3(这里 h3 是对 google 外部资源的请求

HTTP 1.1 虽然可以用 keep-alive 复用同个 TCP 链接,但是资源还是有顺序的,会形成阻塞

HTTP 2 真正做到了异步或并发的对资源进行传输,同一个时刻可以发起多个资源请求,可以将不同资源信息同时通过网络传回浏览器

5.3.Server Push(服务器推送)

正常客户端拿到资源都是向服务器发起请求,服务器再把资源推送给客户端,这个来回是有消耗的(TTFB),如果能让服务器提前把这些东西推送到客户端,就能节约一定的网络开销

server
{
  location / {
    index index.html index.htm;
    http2_push /img/me0.jpg;
    http2_push /img/me1.jpg;
    http2_push /img/me2.jpg;
  }
}

重启 nginx,可以发现图片没有了绿色部分(TTFB),少了请求返还回路的过程

可以看到Initiator属性中 图片为 Push,这种资源是通过 server push 提前推送到浏览器的

六:服务端渲染 SSR

SSR 好处:

  • 加速首屏加载
  • 更好的 SEO

 6.1.基于 React Next.js 实现SSR

npm init -y
npm install next react react-dom

添加 scripts 执行脚本:

// package.json
{
  "scripts": {
    "dev": "next"
  }
}

在 index.jsx中添加如下内容,之后 npm run dev 即可

  • 服务端渲染会把页面上显示的所有内容都放在 html 里
  • next.js 已经帮我们把代码进行基于路由的代码拆分,里面提供了 Link 组件
import React from 'react'
import Header from './Header.jsx'

export default () => (
  <div>
    <Header />
    <p>Home</p>
  </div>
)

6.2.是否使用 SSR

  • 架构-大型,动态页面,面向公众用户(是否关心首屏速度)
  • 搜索引擎排名很重要(或者采取前面的页面使用静态页面,后面页面使用 vue react 实现动态加载的方法实现)

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

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

相关文章

【Spring(五)】带你深入了解bean的生命周期

1.5 bean的生命周期 bean的实例化已经说完了&#xff0c;我们最后再来讲讲bean的生命周期。 我们主要来围绕着bean生命周期控制来学习&#xff0c;那么什么是生命周期呢&#xff1f;其实就是一个东西从创建到消亡的完整过程&#xff0c;比如人从出生到死亡的整个过程&#xff…

【MySQL进阶】深入理解redoLog日志

【MySQL进阶】深入理解redoLog日志 文章目录【MySQL进阶】深入理解redoLog日志一&#xff1a;redo日志概述二&#xff1a;redo日志格式三&#xff1a;Mini-Transaction1&#xff1a;以组的形式写入redo日志2&#xff1a;Mini-Transaction的概念四&#xff1a;redo日志的写入过程…

富淼转债,优彩转债上市价格预测

富淼转债基本信息转债名称&#xff1a;富淼转债&#xff0c;评级&#xff1a;A&#xff0c;发行规模&#xff1a;4.5亿元。正股名称&#xff1a;富淼科技&#xff0c;今日收盘价&#xff1a;18.25&#xff0c;转股价格&#xff1a;20.26。当前转股价值 转债面值 / 转股价格 * …

(3分钟速览)SLAM中的三大金刚-H E F Matrix

编辑切换为居中添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09;三个矩阵的自由度&#xff1a;单应矩阵H 自由度8基础矩阵F 自由度7本质矩阵E 自由度5或者8&#xff0c;这个是根据使用旋转矩阵还是旋转向量编辑切换为居中添加图片注释&#xff0c;不超过 14…

每日一题之Vue的异步更新实现原理是怎样的?

最近面试总是会被问到这么一个问题&#xff1a;在使用vue的时候&#xff0c;将for循环中声明的变量i从1增加到100&#xff0c;然后将i展示到页面上&#xff0c;页面上的i是从1跳到100&#xff0c;还是会怎样&#xff1f;答案当然是只会显示100&#xff0c;并不会有跳转的过程。…

计算机基础——计算机应用领域以及未来发展趋势

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.计算机应用领域 1.信息管理 2.过程控制 3.计算机辅助技术 1&#xff09…

一天天过去,每天该如何过?

刚跨了年&#xff0c;又快到春节&#xff0c;日子就这样一天天过去。如何过好这一生是个大命题&#xff0c;不如简化点考虑下如何过好一天&#xff1f;人的时间大体分为两类&#xff1a;主动的&#xff0c;可以自由支配&#xff1b;被动的&#xff0c;等着被安排。过去我在互联…

MCU-51:LCD1602详解

目录一、LCD1602简介1.1 显示原理1.2 引脚及应用电路1.3 技术参数1.4 引脚功能1.5 指令集1.6 连接方式二、时序图2.1 写时序2.2 读时序三、代码演示3.1 LCD1602.c3.2 示例注意&#xff1a;一定要看一、LCD1602简介 LCD1602&#xff08;Liquid Crystal Display&#xff09;液晶…

能量加油站Java上

1、final 在 Java 中有什么作用&#xff1f; 1、final 修饰的类叫最终类&#xff0c;该类不能被继承。2、final 修饰的方法不能被重写3、final 修饰的变量叫常量&#xff0c;常量必须初始化&#xff0c;初始化之后值就不能被修改 2、Math.round() 指向上取整 补充 Double.do…

01背包问题再探

原题&#xff1a; 有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。 第 i 件物品的体积是 vi&#xff0c;价值是 wi。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值。 输入格式 第一行两个整…

盖子的c++小课堂——第五讲:for 循环

前言 hi&#xff0c;大家好&#xff0c;我是盖子的盖&#xff0c;最近大家都放假了吗&#xff0c;反正我还没有&#xff0c;我们期末考才刚开始考呜呜呜&#xff0c;真羡慕那些放假了的童鞋们~~(╥╯^╰╥)~~ 好啦&#xff0c;废话不多说&#xff0c;开始今天的小课堂吧~~ 上…

厚积薄发打卡Day113:Debug设计模式:设计原则(一)<开闭原则、依赖倒置、单一职责>

厚积薄发打卡Day113&#xff1a;Debug设计模式&#xff1a;设计原则&#xff08;一&#xff09;<开闭原则、依赖倒置、单一职责> 开闭原则 定义 一个软件实体如类、模块和函数应该对扩展开放&#xff0c;对修改关闭。其优点&#xff1a;提高软件系统的可复用性及可维护…

JavaEE多线程-创建线程(Thread)

目录一、线程(Thread)1.1 Thread类中的构造方法1.2 启用线程的方法二、创建第一个多线程三、多线程并发执行简单演示四、多线程并发执行的优势五、Thread的常见构造方法和属性5.1 属性5.2 方法六、中断线程七、线程等待一、线程(Thread) 线程是操作系统中的概念. 操作系统内核…

LeetCode二叉树经典题目(六):特殊位置构造二叉树

目录 21. LeetCode404. 左叶子之和 22.LeetCode513. 找树左下角的值 23. LeetCode112. 路径总和 24. LeetCode113. 路径总和 II 25. LeetCode106. 从中序与后序遍历序列构造二叉树 26. LeetCode105. 从前序与中序遍历序列构造二叉树​编辑 27. LeetCode654. 最大二叉树 …

LED、Mini LED、Micro LED、LCD、OLED技术

1、传统led、miniled、microled的异同 2、OLED OLED&#xff08;Organic Light-Emitting Diode&#xff09;&#xff0c;又称为有机电激光显示、有机发光半导体&#xff08;Organic Electroluminescence Display&#xff0c;OLED&#xff09;。OLED属于一种电流型的有机发光器…

S32K144-hello_word点灯

官方提供了很多的参考例程&#xff0c;每个历程分别配置了不同的外设&#xff0c;这里挨个尝试解读一下。 示例效果 RGB红灯绿灯交替闪烁。 导入示例 示例文件所在目录&#xff1a; 该示例使用PCC和PORT模块交替切换两个LED。 硬件连接 配置引脚功能 生成代码 S32DS自带引…

C#上位机基础学习_登录窗体的创建方法和步骤

C#上位机基础学习_登录窗体的创建方法和步骤 本次和大家分享如何制作一个简单的登录窗体。具体的方法和步骤可以参考以下内容: 如下图所示,打开Visual Studio 2019,新建一个Windows 窗体应用(.NET Framework), 如下图所示,在窗体中添加Label标签、Text文本框、Button按…

Java中常用API总结(5)—— Object类中的深克隆和浅克隆

对象克隆一、前言二、浅克隆1.概述2.实例1️⃣思路2️⃣继承cloneable接口底层原理3️⃣重写clone方法底层原理3.代码实现三、深克隆1.概述2.实例3.代码实现四、结语一、前言 本文将详细讲述Object类中的对象克隆方法&#xff0c;其中包含深克隆和浅克隆&#xff0c;两者有一定…

算法竞赛100天第2天——STL IN C++(算法竞赛必备知识总结汇总)

本文已收录于专栏 &#x1f332;《百日算法竞赛》&#x1f332; 目录 前言&#xff1a; 序列容器 序列的要求&#xff1a; 1.vector vector常用方法 vector遍历 2、deque 头文件 方法 3、list 头文件 方法 4、queue 方法&#xff1a; 关联容器 1、map 2、se…

SWPUCTF 2022新生赛部分wp

&#x1f60b;大家好&#xff0c;我是YAy_17&#xff0c;是一枚爱好网安的小白。 本人水平有限&#xff0c;欢迎各位大佬指点&#xff0c;一起学习&#x1f497;&#xff0c;一起进步⭐️。⭐️此后如竟没有炬火&#xff0c;我便是唯一的光。⭐️[SWPUCTF 2022 新生赛]ez_ez_ph…