前端开发必须了解的 Nginx 单页加载优化

更新日期: 2021-08-04阅读: 1.1k标签: 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 uriuri/ /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/2,HTTP/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缓存


链接: https://fly63.com/article/detial/11007

Nginx常用配置--nginx之proxy_pass代理后端https请求完全解析

前提条件:nginx源码或nginx plus源码、一个代理服务器或一个代理服务器组、SSL证书和私钥,你可以从一个可信任证书颁发机构(CA)购买一个服务器证书,或者你可以使用openssl库创建一个内部CA签名

nginx:支持https

查看nginx模块,如果看到with-ssl那就是有的。注册ssl证书并下载,配置nginx就比如说,还没有配置https前你配置了80,那么你http://域名/直接默认访问80端口,那么一样的

nginx做http向https的自动跳转

首先让nginx服务器监听两个端口,分别是80端口和443端口,注意监听443端口的时候需要配置证书的认证以及创建自签名证书!关于证书的认证的以及创建自签名的证书,nginx的配置如下,只给出了两个server的配置,可以直接复制到http块中。

Nginx配置https和wss

常见的服务器有三种:Nginx、IIS、Apache,都可以配置https,但是没必要全部知道,因为Nginx可以起到反向代理的作用,会配置Nginx就足够了。在/etc/nginx/conf.d目录下新建https.conf

nginx加速_开启Gzip/文件做缓存

开启Gzip:给Nginx上 ngx_http_gzip_module 这个模块,用 nginx -V 命令查看 configure arguments 是否有,没有的话需要编译加载这个模块;给文件做缓存:图片文件,字体文件,js和css都是些可以用来缓存的文件

nginx和php-fpm的进程启停重载总结

ginx和php-fpm对于-USR2、-HUP信号的处理方式不一样:TERM, INT(快速退出,当前的请求不执行完成就退出),QUIT (优雅退出,执行完当前的请求后退出)

Nginx解析PHP的原理 | CGI、FastCGI及php-fpm的关系

php-fpm采用master/worker架构设计, master进程负责CGI、PHP公共环境的初始化及事件监听操作。worker进程负责请求的处理功能。在worker进程处理请求时,无需再次初始化PHP运行环境,这也是php-fpm性能优异的原因之一

Nginx 禁止某 IP 访问

总有一些不怀好意的人来访问我的网站,而且频率还很高,所以就用简单的方式禁止访问,就用 Nginx 来实现。想要添加黑名单,只要在 blocksip.conf 中添加 IP ,然后 reload 即可。

Nginx服务器 之反向代理与负载均衡

客户端就可以通过请求代理服务器,获取想要的资源,但客户端并不知道给他资源的是哪个服务器。这种方式就是反向代理。当一台服务器的单位时间内的访问量越大的时候,服务器的压力会越大。我们通常通过负载均衡的方式来分担服务器的压力。

前端如何通过Nginx代理做到跨域访问API接口

Nginx作为反向代理服务器,就是把http请求转发到另一个或者一些服务器上。通过把本地一个url前缀映射到要跨域访问的web服务器上,就可以实现跨域访问。对于浏览器来说,访问的就是同源服务器上的一个url

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!