乐趣区

关于前端:Nginx单页加载优化

上一期咱们讲了单页利用的 Nginx 配置,本期咱们将从一个前端的角度简略介绍一下页面加载的优化工作,当然这只是浅尝辄止,毕竟我不是业余的 Nginx 优化人员。

网页加载

首先咱们要看一下咱们网页加载到底两头是个什么流程,那些货色比拟消耗工夫,比方咱们拜访 github:

  • Queued、Queueing:如果是 HTTP/1.1 的话,会有 队头阻塞,浏览器对每个域名最多开 6 个并发连贯。
  • Stalled:浏览器要事后分配资源,调度连贯。
  • DNS Lookup:DNS 解析域名。
  • Initial connection、SSL:与服务器建设连贯,TCP 握手,当然你是 https 的话还有 TLS 握手。
  • Request sent:服务器发送数据。
  • TTFB:期待返回的数据,网络传输,也就是 首字节响应工夫
  • Content Dowload:接收数据。

从图中能够看出从与服务器建设连贯,到接收数据,这里的工夫破费是十分多的,当然还有 DNS 解析,不过这里有本地缓存,所以根本没有工夫。

gzip- 缩小加载体积

首先咱们能够通过 gzip 对咱们的 js 以及 css 进行压缩:
vue.config.js:

const CompressionWebpackPlugin = require('compression-webpack-plugin')

buildcfg = {productionGzipExtensions: ['js', 'css']
}
configureWebpack: (config) => {
  config.plugins.push(
    new CompressionWebpackPlugin({test: new RegExp('\\.(' + buildcfg.productionGzipExtensions.join('|') + ')$'),
      threshold: 8192,
      minRatio: 0.8
    })
  )
}

在 nginx 里开启 gzip:

server 模块:

# 应用 gzip 实时压缩
gzip on;
gzip_min_length 1024;
gzip_buffers 4 16k;
gzip_comp_level 6;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
# 应用 gzip_static
gzip_static on;

这里简略阐明一下吧,

  • gzip_static是会主动查找对应文件的 .gz 文件,这个的与 gzip 开启与否以及 gzip_types 等并没有关联,你能够了解为优先返会 .gz 文件。
  • gzip的开启是针对于申请文件的实时压缩,这个是会耗费 cpu 的,比如说下面的申请文件的 Content-Length 大于gzip_min_length,就进行压缩返回。

总结一下就是你如果打包后有 .gz 文件,只须要开启 gzip_static 即可,如果没有那么得启用 gzip 实时压缩,不过我倡议应用前者,另外 gzip 的实用于文本类型,图片之类的应用的话会事与愿违,故 gzip_types 请适当设置。

想看 gzip 是否胜利启用能够通过,查看返回的 header 头Content-Encoding: gzip,以及查看文件的 size,这里能够看到咱们原来文件的是 124kb,而返回的 gzip 文件为 44kb,压缩效率还是蛮大的:

缓存管制 - 没有申请就是最好的申请

浏览器于服务器的缓存交互,细说起来可就多了,想理解残缺的请看其他人整顿的文章吧,我只是这里从配置上略说一下:

location /mobile {
  alias   /usr/share/nginx/html/mobile/;
  try_files $uri $uri/ /mobile/index.html;
  if ($request_filename ~ .*\.(htm|html)$){add_header Cache-Control no-cache;}
  if ($request_uri ~* /.*\.(js|css)$) {
      # add_header Cache-Control max-age=2592000;
      expires 30d;
  }
  index  index.html;
}

协商缓存

Last-Modified

咱们的单页入口文件是 index.html,这个文件呢决定了咱们要加载的 js 以及 css,故咱们给 html 文件设置协商缓存Cache-Control no-cache,当咱们首次加载时 http 的状态码为 200,服务器会返回一个Last-Modified 示意这个文件的最初批改工夫,再次刷新时浏览器会把这个批改工夫通过 If-Modified-Since 发送给服务器,如果没有变动(Etag 也会校验),那么服务器会返回 304 状态码,说我的文件没有变,你间接用缓存吧。

Etag

HTTP 协定解释 Etag被申请变量的实体标记 ,你能够了解为一个 id,当文件变动了,这个 id 也会变动,这个和Last-Modified 差不多,服务器会返回一个Etag,浏览器下次申请时会带上If-None-Match,进行比照返回,有些服务器的 Etag 计算不同,故在做分布式的时候可能会出问题,文件没改变不走缓存,当然你能够敞开这个只应用Last-Modified

强缓存

咱们的单页利用打包时 webpack 等工具是会依据文件的变动生成对应的 js 的,也就也是文件不变的话 js 的 hash 值不变,故咱们在加载 js 等文件时能够应用强缓存,让浏览器在缓存工夫类不进行申请,间接从缓存外面取值,比方下面咱们通过设置 expires(Cache-Control 也行,这个优先级更高)为 30 天,那么浏览器下此拜访咱们雷同的缓存过的 js 和 css 时(缓存工夫内),就间接从缓存外面拿(200 from cache),而不会申请咱们的服务器。

留神:此办法是基于上述打包生成 hash 而言的,如果你生成的是 1.js,2.js 之类的,那么你批改了 1.js 外面的类容,打包进去的还是 1.js,那么浏览器还是会从缓存外面拿,不会进行申请的。也就是说应用此形式须要确保你批改了文件打包后批改的 hash 值须要变动。

强制刷新

强缓存用得好的话是飞个别的感觉,然而如果在谬误状况下应用就老是走浏览器缓存,如何清理这个呢,咱们罕用的形式是 Ctrl+F5 或者在浏览器管制台上把 Disable cache 给勾上,实际上这个是在申请文件时会主动加上一个 header 头Cache-Control: no-cache,也就是说我不要缓存,那么浏览器会老老实实的向服务器发出请求。

长连贯 - 缩小握手次数

TCP 握手以及 TLS 握手还是比拟费时的,比方以前的 http1.1 之前的连贯就是每一条都要进过 TCP 三次握手,超级费时,还好 1.1 默认应用了长连贯,能够缩小握手开销,然而如果你做大文件上传时会发现超过肯定工夫会断掉,这是因为 Nginx 默认的长连接时间为 75s,超过了就会断开,当你的网页的确要加载很多很多货色时能够适当把这个工夫缩短一点,以缩小握手次数(keepalive_requests 能够限度 keep alive 最大申请数),至于大文件上传吗你能够抉择分片上传,这里就不做介绍了。

server:

keepalive_timeout 75;
keepalive_requests 100;

HTTP/2- 更平安的 HTTP、更快的 HTTPS

当初很多网站都启用了 HTTP/2HTTP/2 最大的一个长处是齐全放弃了与 HTTP/1 的兼容,HTTP/2 协定自身并不要求肯定开启 SSL,但浏览器要求肯定要启用SSL 能力应用HTTP/2,头部压缩、虚构的“流”传输、多路复用等技术能够充分利用带宽,升高提早,从而大幅度提高上网体验。Nginx 开启相当简略:

server {
  listen       443 ssl http2;
  ssl_certificate         /etc/nginx/conf.d/ssl/xxx.com.pem;
  ssl_certificate_key     /etc/nginx/conf.d/ssl/xxx.com.key;
  ssl_ciphers   ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE+AES128:!MD5:!SHA1; # 弃用不平安的加密套件
  ssl_prefer_server_ciphers   on; # 缓解 BEAST 攻打
}

HSTS- 缩小 302 重定向

当初大多数网站都是 https 的了,然而有个问题就是用户在输出网址时一般来说不会被动输出 https,走的还是 80 端口,咱们个别会在 80 端口进行 rewrite 重写:

server{
  listen    80;
  server_name    test.com;
  rewrite ^(.*)$  https://$host$1 permanent;
}

但这种重定向减少了网络老本,多出了一次申请,我想下次访问时间接拜访 https 怎么解决?咱们能够应用HSTS,80 端口的不变,在 443 端口的 server 新增:

add_header Strict-Transport-Security "max-age=15768000; includeSubDomains;";

这相当于通知浏览器:我这个网站必须严格应用 HTTPS 协定,在在 max-age 工夫内都不容许用 HTTP,下次访问你就间接用HTTPS 吧,那么浏览器只会在第一次拜访时走 80 端口重定向,之后拜访就间接是 HTTPS 的了(includeSubDomains 指定的话那么阐明此规定也实用于该网站的所有子域名)。

Session Ticket-https 会话复用

咱们晓得 https 通信时,SSL 握手会耗费大量工夫,应用非对称加密爱护会话密钥的生成。而真正传输的是通过对称加密进行通信传输。那么咱们每次刷新都进行 SSL 握手太费时间了,既然单方都拿到会话密钥了,那么用这个密钥进行通信不就能够了,这就是会话复用。
服务器把密钥加密后生成 session ticket 发送给客户端,申请敞开后,如果客户端发动后续连贯(超时工夫内),下次客户端再和服务器建设 SSL 连贯的时候,将此 session ticket 发送给服务器,服务器解开 session ticket 后拿出会话密钥进行加密通信。

ssl_protocols               TLSv1.2 TLSv1.3; # 开启 TLS1.2 以上的协定
ssl_session_timeout         5m; # 过期工夫,分钟
ssl_session_tickets         on; # 开启浏览器的 Session Ticket 缓存

本系列更新只有利用周末和下班时间整顿,比拟多的内容的话更新会比较慢,心愿能对你有所帮忙,请多多 star 或点赞珍藏反对一下。

本文地址:https://xuxin123.com/web/nginx-spa-load

退出移动版