1. 分包策略
分包策略就是将不会经常更新的文件进行单独打包处理,使客户端加载资源更快。
首先说一下浏览器的缓存特性:
-
第一次访问网站时,浏览器首先向服务器发起
HTTP
请求 ,服务器响应该请求,浏览器第一次拿到结果后,会根据响应头的缓存标识,决定是否缓存,是则将请求结果和缓存标识存入浏览器缓存中。 -
缓存规则:当浏览器向服务器发起请求时,服务器会将缓存规则放入
HTTP
响应报文的HTTP
头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是Expires
和Cache-Control
,其中Cache-Control
优先级比Expires高。Expires
:Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,即再次发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。Cache-Control
:优先级比expires高,那么直接根据Cache-Control
的值进行缓存,比如cache-control:max-age=600
意思就是说在600秒内再次发起该请求,则会直接使用缓存结果,强制缓存生效。
-
下一次访问这个网站时,浏览器会拦截请求,转而先向浏览器缓存发起请求,分为以下强制缓存和协商缓存两种情况:
- 强制缓存:
- 如果不存在该缓存结果和缓存标识,则直接向服务器发起请求
- 存在该缓存结果和缓存标识,但该结果已失效,进行协商缓存
- 存在该缓存结果和缓存标识,且该结果尚未失效,直接返回该结果
- **协商缓存:**紧接着强制缓存第二步
- 携带浏览器缓存发来的缓存标识,向服务器发起请求,若资源无更新,返回304不返回资源,重新读取浏览器缓存,返回该缓存。
- 携带浏览器缓存发来的缓存标识,向服务器发起请求,若资源已更新,返回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压缩技术
gzip
是GNUzip
的缩写,最早用于UNIX
系统的文件压缩。HTTP
协议上的gzip
编码是一种用来改进web
应用程序性能的技术,web
服务器和客户端(浏览器)必须共同支持gzip
。
在HTTP
传输协议上的gzip
压缩技术工作原理:
1)浏览器请求url
,并在request header
中设置属性accept-encoding:gzip
。表明浏览器支持gzip
。
2)服务器收到浏览器发送的请求之后,判断浏览器是否支持gzip
,如果支持gzip
,则向浏览器传送压缩过的内容,不支持则向浏览器发送未经压缩的内容。一般情况下,浏览器和服务器都支持gzip
,response headers
返回包含content-encoding:gzip
。
3)浏览器接收到服务器的响应之后判断内容是否被压缩,如果被压缩则解压缩显示页面内容。
通过这项技术,可以将大文件压缩成小文件传输,降低服务器压力和传输速度,虽然浏览器的解压缩也需要时间,但是对于不压缩****大文件的传输时间还是微不足道的。
vite
中可以利用这个插件完成压缩任务:vite-plugin-compression
,用法如下:
import { defineConfig } from "vite";
const vitePluginCompression = require('vite-plugin-compression');
export default defineConfig({
plugins:[vitePluginCompression()] // 直接放在插件列表即可
})
压缩技术对于大文件来说效果很明显,但对于本来就不大的小文件来说,压缩就不必要了,因为浏览器解压也需要时间的。
参考文件:
- https://www.bilibili.com/video/BV1GN4y1M7P5/?p=31&spm_id_from=pageDriver&vd_source=b1c06588c6b8247603b9356c32a1e5b6
- https://zhuanlan.zhihu.com/p/24764131
- https://github.com/anncwb/vite-plugin-compression/tree/master/#readme
3. 动态导入
优点:使用动态导入可以做到按需编译,降低首页加载速度。
vite
的动态导入利用的esModule的规范,可以利用import()
函数进行动态导入。import()
函数返回一个 Promise,可以在 Promise 的 then
方法中使用导入的模块。与 import
不同,import()
可以动态地加载模块,即可以在运行时根据需要动态加载模块,而不需要在代码加载阶段就加载所有模块。
**由于 **import()
是异步的,因此在模块加载完成之前,模块中导出的变量或函数是无法使用的。因此,在使用 import()
导入模块时,需要使用 Promise
或 async/await
等机制来处理异步操作。
在Vite
里,import()
导入的文件默认是懒加载的,通过动态导入实现,并会在构建时分离为独立的 chunk。
参考文件:
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/import
- https://juejin.cn/post/7205487413350498360
- https://cn.vitejs.dev/guide/features.html#glob-import-as
4. CDN加速
在服务器上用到了很多的静态库文件,我们可以把这些库文件从cdn服务器加载,而不是在我们的服务器上,这么服务器的压力就会大大降低地同时,也有利于不同地区的用户有着良好的加载速度。因为CDN服务器遍及多地啊!
推荐一款Vite的CDN加速插件:
它允许指定 modules 在生产环境中使用 CDN 引入。这可以减少构建时间,并且提高生产环境中页面加载速度。
具体配置可以参考文档。