1. 分包策略

分包策略就是将不会经常更新的文件进行单独打包处理,使客户端加载资源更快。

首先说一下浏览器的缓存特性:

  1. 第一次访问网站时,浏览器首先向服务器发起HTTP请求 ,服务器响应该请求,浏览器第一次拿到结果后,会根据响应头的缓存标识,决定是否缓存,是则将请求结果和缓存标识存入浏览器缓存中。

  2. 缓存规则:当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文的HTTP头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是ExpiresCache-Control,其中Cache-Control优先级比Expires高。

    • Expires:Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,即再次发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。
    • Cache-Control:优先级比expires高,那么直接根据Cache-Control的值进行缓存,比如cache-control:max-age=600意思就是说在600秒内再次发起该请求,则会直接使用缓存结果,强制缓存生效。
  3. 下一次访问这个网站时,浏览器会拦截请求,转而先向浏览器缓存发起请求,分为以下强制缓存和协商缓存两种情况:

    • 强制缓存
    1. 如果不存在该缓存结果和缓存标识,则直接向服务器发起请求
    2. 存在该缓存结果和缓存标识,但该结果已失效,进行协商缓存
    3. 存在该缓存结果和缓存标识,且该结果尚未失效,直接返回该结果
    • **协商缓存:**紧接着强制缓存第二步
    1. 携带浏览器缓存发来的缓存标识,向服务器发起请求,若资源无更新,返回304不返回资源,重新读取浏览器缓存,返回该缓存。
    2. 携带浏览器缓存发来的缓存标识,向服务器发起请求,若资源已更新,返回200,返回新资源,将新资源重新缓存进入浏览器缓存。

    那么项目和浏览器缓存有什么关系呢?
    当你经常更新代码后,Vite在检测到了资源变更后,都会主动将打包后的文件重新命名,以消除浏览器缓存。但是,如果你的项目引入了相当多的库,这些代码多是不易变化的,但是,由于库代码将会和你的代码融合起来,仅有一个js文件,这样,每次更新代码都要重新向服务端请求资源。所以将这些库文件单独导出一个文件,以后每次打包时,这些库文件没有变化,打包文件名字也就不会变化,因此,当代码更新,浏览器也仅向服务器请求部分修改js文件,直接读取缓存中的库文件。达到更快的速度。
    那么,Vite怎么开启分包机制呢?
    如下去配置vite.config.js:

    import { defineConfig } from "vite";
    
    export default defineConfig({
      build: {    // 打包配置
        rollupOptions: {       // 配置rollup的一些构建策略
          output: {    // 控制输出
            manualChunks: (id) => {  // https://www.rollupjs.com/configuration-options/#output-manualchunks
              if (id.includes("node_modules")) {
                return 'vendor'   // 所有符合条件的包都会进入vendor自定义文件
              }
            }
          }
        }
      },
    
    })
    

    其中,manualChunks为函数形式时,每个被解析的模块都会经过该函数处理。如果函数返回字符串,那么该模块及其所有依赖将被添加到以返回字符串命名的自定义 chunk中。

2. gzip压缩技术

gzipGNUzip的缩写,最早用于UNIX系统的文件压缩。HTTP协议上的gzip编码是一种用来改进web应用程序性能的技术,web服务器和客户端(浏览器)必须共同支持gzip

HTTP传输协议上的gzip压缩技术工作原理:

1)浏览器请求url,并在request header中设置属性accept-encoding:gzip。表明浏览器支持gzip

2)服务器收到浏览器发送的请求之后,判断浏览器是否支持gzip,如果支持gzip,则向浏览器传送压缩过的内容,不支持则向浏览器发送未经压缩的内容。一般情况下,浏览器和服务器都支持gzipresponse headers返回包含content-encoding:gzip

3)浏览器接收到服务器的响应之后判断内容是否被压缩,如果被压缩则解压缩显示页面内容。

通过这项技术,可以将大文件压缩成小文件传输,降低服务器压力和传输速度,虽然浏览器的解压缩也需要时间,但是对于不压缩****大文件的传输时间还是微不足道的。

vite中可以利用这个插件完成压缩任务:vite-plugin-compression,用法如下:

import { defineConfig } from "vite";
const vitePluginCompression = require('vite-plugin-compression');

export default defineConfig({
  plugins:[vitePluginCompression()]     // 直接放在插件列表即可
})

压缩技术对于大文件来说效果很明显,但对于本来就不大的小文件来说,压缩就不必要了,因为浏览器解压也需要时间的。

参考文件:

  1. https://www.bilibili.com/video/BV1GN4y1M7P5/?p=31&spm_id_from=pageDriver&vd_source=b1c06588c6b8247603b9356c32a1e5b6
  2. https://zhuanlan.zhihu.com/p/24764131
  3. https://github.com/anncwb/vite-plugin-compression/tree/master/#readme

3. 动态导入

优点:使用动态导入可以做到按需编译,降低首页加载速度。

vite的动态导入利用的esModule的规范,可以利用import()函数进行动态导入。import() 函数返回一个 Promise,可以在 Promise 的 then 方法中使用导入的模块。与 import 不同,import() 可以动态地加载模块,即可以在运行时根据需要动态加载模块,而不需要在代码加载阶段就加载所有模块。

**由于 **import() 是异步的,因此在模块加载完成之前,模块中导出的变量或函数是无法使用的。因此,在使用 import() 导入模块时,需要使用 Promiseasync/await 等机制来处理异步操作。

Vite里,import()导入的文件默认是懒加载的,通过动态导入实现,并会在构建时分离为独立的 chunk。

参考文件:

  1. https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/import
  2. https://juejin.cn/post/7205487413350498360
  3. https://cn.vitejs.dev/guide/features.html#glob-import-as

4. CDN加速

在服务器上用到了很多的静态库文件,我们可以把这些库文件从cdn服务器加载,而不是在我们的服务器上,这么服务器的压力就会大大降低地同时,也有利于不同地区的用户有着良好的加载速度。因为CDN服务器遍及多地啊!

推荐一款Vite的CDN加速插件:

它允许指定 modules 在生产环境中使用 CDN 引入。这可以减少构建时间,并且提高生产环境中页面加载速度。

具体配置可以参考文档。