vue项目部署的最佳实践,实现无感知发版

发布时间:2021-09-19 22:46:37

本文中转载自 开课吧前端团队 微信公众号的文章,原文地址->链接地址


作者:沉末_
https://juejin.im/post/5eb2243e51882555d8457833


前 言


使用vue、react、angular等技术开发过程中,我们都会遇到以下问题:


首屏加载慢;


每一次更新都需要清除浏览器缓存才能看到效果(经常被测试吐槽)。


这两个问题可以从很多方面进行优化,今天我就从前端页面部署阶段来优化一下这两个问题。PS:以下内容都基于vue-cli3+。


1.前端页面文件缓存方案

从vue-cli3打包说起


路由使用按需加载后,打包生成的文件,每一个路由页面都对应一个js和css文件,入口main.js及其依赖则打包成了app.js和app.css,公共依赖都放到了chunk-vendors.js。


vue-cli3打包后的dist/js文件夹:

可以看到,打包生成的js/css/img等文件的文件名都带有hash值,当源文件内容改变时,重新打包后对应的文件hash值也会改变。


举个栗子,我们修改了about.vue中js的内容,重新打包时about.js的hash值会改变,以及依赖about.vue的文件app.js的hash值也会改变,而其他没有修改的文件,打包后的hash值都不会改变。


我们知道,文件名带hash是为了消除缓存带来的影响的,但是所有文件都不缓存肯定不是一个很好的解决方案。


vue-cli3打包生成的文件名带hash值的作用


为了缓存的最优体验


我们先来简单回顾下http缓存的知识(参考MDN):


HTTP1.0 是通过Expires(文件过期时间)和Last-Modified(最*修改时间)来告诉浏览器进行缓存的,这两个字段都是 UTC 时间(绝对时间)。


Expires 过期控制不稳定,因为浏览器端可以随意修改本地时间,导致缓存使用不精准。而且 Last-Modified 过期时间只能精确到秒。


HTTP1.1 通过Cache-Contorl和 Etag(版本号)进行缓存控制。


浏览器先检查 Cache-Control,如果有,则以 Cache-Control 为准,忽略 Expires。如果没有 Cache-Control,则以 Expires 为准。


Cache-Control 除了可以设置 max-age(相对过期时间,以秒为单位)以外,还可以设置如下几种常用值:


public,资源允许被中间服务器缓存。浏览器请求服务器时,如果缓存时间没到,中间服务器直接返回给浏览器内容,而不必请求源服务器。


private,资源不允许被中间代理服务器缓存。浏览器请求服务器时,中间服务器都要把浏览器的请求透传给服务器。


no-cache,不管本地副本是否过期,每次访问资源,浏览器都要向服务器询问,如果文件没变化,服务器只告诉浏览器继续使用缓存(304)。


no-store,浏览器和中间代理服务器都不能缓存资源。每次访问资源,浏览器都必须请求服务器,并且,服务器不去检查文件是否变化,而是直接返回完整的资源。


must-revalidate,本地副本过期前,可以使用本地副本;本地副本一旦过期,必须去源服务器进行有效性校验。


proxy-revalidate,要求代理服务器针对缓存资源向源服务器进行确认。


s-maxage:缓存服务器对资源缓存的最大时间。


现在99%的浏览器都是HTTP1.1及以*姹荆颐桥渲没捍婢褪褂肅ache-Contorl和Etag配合就好了。


那么问题来了,检查文件是否最新不是用etag吗,为什么文件名还需要有hash值?


如果文件名不带hash值,文件版本得用etag来标记,浏览器需要先去检查下是否过期,服务器则需要检查文件是否最新。


而文件名带有hash值,可以直接将文件的过期时间设置为1年,浏览器就不用检查是否过期,直接使用。


原因是,如果页面源文件有修改,生成的js/css的hash值就会修改,对应的请求js/css地址也会变化,htpp地址改了,也就不用检查是否过期。没修改的文件的hash则不变,可以使用缓存文件。


所以利用文件名带hash来做缓存,即能保证,页面有修改浏览器能请求到最新的文件,又能节省服务器的请求(检查是否过期的请求)。


实现无感知发版


只有一台服务器的情况下,我们的页面文件需要更新,通常操作是:先删掉旧文件,然后上传新文件,这段时间系统将不可用,对用户有一定的影响。


仅更新前端页面的前提下,文件名带有hash值还可以实现用户无感知发版:


系统更新时,只需要将打包之后的文件除index.html以外的文件(js/css/img),全部上传到服务器网站目录,未修改文件(即重名文件)直接跳过,有修改的文件由于文件的hash值不同会被上传,上传完毕我们再将index.html覆盖掉旧版就行。


这段时间用户已请求旧版本index.html的无影响(不会出现文件404,因为新旧版本js/css同时存在),而新访问用户则请求的是新版index.html,访问旧页面用户刷新也会请求新版文件,并且无缓存影响,即对用户使用0影响。


一段时间之后,我们只需要按文件生成时间对比一下删除旧文件即可。PS:替换前端文件不需要*舴衿鳌


总结:凡是文件名带有hash值的的文件都可以设置为“永久缓存”(一年),其他不带hash的文件使用etag来设置缓存,由Nginx判断是否过期。


优化打包结果


页面部署的时候,有个问题,如何区分文件名是否带有hash值呢?正则匹配显然不是很好的办法。


其实办法很简单,打包生成的文件都带有hash值,而public目录里面的文件不会经过打包处理。


所以只需要将public目录里面的文件除了index.html全部放到一个static目录(注意引入路径)

那么打包后的文件目录就会变成这样:

static目录里面的文件和index.html的文件名是不带hash值的,其他的文件都是带有hash值的。


补充:打包后发现一些页面文件很小,只有几K


如下图所示,虽然是按需加载,但是感觉浪费服务器请求

这时,我们可以配置webpack的特殊注释(需要 Webpack > 2.4),将一些按需加载的路由打包到同一个js文件。

这里需要注意一下,虽然每个文件单独打包都是1k,但是1k+1k不等于2k,也就是说,打包到一起的体积会比原来分开的大,4个1k的文件打包到一起,体积大约是10k,体积达到10k,刚好就会触发gzip压缩,压缩之后体积在4k左右,所以并没有什么影响。


服务器配置缓存


理论知识有了,现在我们来实际操作一下:


文件名带hash的(即css、js、font和img目录下的所有文件)设置一个月缓存,浏览器可以直接使用缓存不需要请求服务器。


其他的文件(index.html和static目录下的文件)设置为no-cache,即每次都来服务器检查是否最新。


为什么缓存时间是一个月,刚才不是说设置一年?


设置为一年,当然没有任何问题。不变的文件可以一直使用,有改动的文件,会重新请求,但是有该动的旧文件已经没有用了,由于过期时间是一年,所以不会被删的,一直占用用户的硬盘,系统更新越频繁,无用旧文件越多,占用的存储也越多,这样是不好的(用户看了想打人)。


所以设置一个合理的时间比较好,一个月就挺好。


废话不说,以Nginx服务器为例,配置如下(配置文件nginx.conf的http模块):

效果如下图:当我们修改index.html内容时,会重新请求,没有修改就会304,文件名带hash的都是直接从本地缓存读取。

有两点需要注意的地方:


项目里面不要用service-worker,这会影响我们的缓存设置,浏览器会优先使用service-worker缓存。


vue-cli4的pwa插件生成的模板自带service-worker


调试的时候记得允许缓存


2.前端文件设置gzip压缩

webpack配置生成gzip压缩的文件


webpack有一个文件压缩的插件,可以将大文件压缩成gzip的格式。使用起来也非常简单,先安装:npm install --save-dev compression-webpack-plugin,


然后修改webpack配置(vue.config.js):

打包完的js/css文件,都会多一份对应的gzip文件,部署的时候需要配置一下,启用gzip,这样支持gzip压缩的浏览器请求的就是压缩文件,不支持的浏览器请求的就是源文件,gzip压缩文件体积会小很多。

字体文件是否需要gzip?


网站中常见的图片的格式有jpg(jpeg)、png、gif、webp,这些格式的图片本身已经优化了,所以不再需要gzip。


实际上对图片进行gzip压缩,不仅没有效果,反而可能使图片体积更大。那么字体文件呢,是不是和图片一样?


从阿里巴巴矢量图库生成的图标字体的css中我们可以看出,一般常见的字体文件有:eot、woff、ttf、svg,另外woff2是以base64的格式存储的。

查阅资料后发现:eot 和 ttf 格式一般情况下本身不压缩,也就是说可以进行gzip压缩。而woff格式具有内建压缩,不需要gzip压缩。


实际测试一下,发现eot和ttf可以进行压缩,效果还不错,而woff格式的,Compressio-nWebpackPlugin插件根本不支持压缩,即使你写了配置了压缩woff文件,它也不会生成gz文件。

并且实验发现,svg虽然是图片,但是也可以进行gzip压缩,压缩效果还不错:

结论:svg、eot 和 ttf 这三种格式的字体文件可以使用:


CompressionWebpackPlugin进行压缩,并且配合Nginx的gzip_types配置,woff和woff2格式的字体文件不需要gzip。


服务器配置gzip压缩


Nginx是前端文件常用的服务器,Nginx服务器的配置文件nginx.conf的http模块:

检查gzip是否生效


浏览器文件请求的请求头包含字段Accept-Encoding: gzip代表浏览器支持gzip压缩文件。

文件响应头包含字段Content-Encoding: gzip代表返回的是压缩文件。

同时NetWork一栏还可以查看到文件的实际大小和实际的请求(gzip)文件大小。

检查Nginx是否使用了我们提供的gz文件


Nginx自带gzip压缩功能,如果我们没提供,它会实时压缩(例如index.html文件),这就很浪费服务器资源了。


现在我们已经提供js和css的gz文件,如何判断Nginx是使用了我们提供的gz文件,而不是自己压缩的呢?


上面有一个配置项:gzip_static on;,开启之后Nginx会优先使用我们的gz文件,但是还是不能确定,Nginx有没有使用gz文件。


查看network请求发现,每一个文件都有etag响应头,如果Nginx使用了已有的gz文件,那么这个请求的etag值不带有W/,反之,如果是文件是Nginx压缩的,etag值则会带有W/。


例如index.html:

拿chunk-vendors.js做一个实验,这个文件本身是带有gz文件的,请求的etag如下(不带有W/):

这时候我们删掉服务器上chunk-vendors.js对应的gz文件,刷新页面,请求如下:
综上,我们就可以验证,只要我们配置了gzip_static on;,Nginx就会优先使用了我们提供的gz文件。


附录 - windows安装Nginx服务器


下载windows下Nginx的安装包:http://nginx.org/en/download.html

在Nginx的目录下使用cmd命令行,启动命令:start nginx,关闭命令:nginx -s stop


备注:修改配置文件需要重载配置:nginx -s reload。启动之后,打开http://localhost:80就能看的效果。


总 结


页面文件合理的设置缓存和gzip压缩是实实在在能提升用户体验的操作,而且比少写几个循环、删除几行代码优化强得多,但是需要前端和运维的密切配合,才能实现最佳方案。


service worker是用来实现离线应用的,文章中没有详细赘述。vue-cli4的pwa插件生成的模板自带service worker,或许这才是vue项目缓存的最佳实践?


最后,Nginx并不是很熟悉,有什么问题和错误,欢迎指出!


本文中转载自 开课吧前端团队 微信公众号的文章,原文地址->链接地址

相关文档

  • 幼儿园大班教育心得范文
  • 末代孔代亲王路易六世?亨利?德?波旁
  • 保育工作心得体会
  • 高中生收看时代新人说对话战疫英雄思政课观后感感想2020年
  • 招标师挂靠一年多少钱
  • 美容师怎么把力度练沉
  • ubuntu16.04 装kvm过程
  • 450家!智能工厂、智慧交通、智慧警务、智慧社区等细分领域龙头全名单!
  • 华硕ZX60VM大家平时用过没实际效果如何
  • 使用阿里云yum源安装docker-ce版本后启动失败
  • 共青团员的自我评价范文
  • 简短唯美古风句子
  • 把钱看的太重怎么办
  • 如何探测引力波留下的“记忆”
  • 高一数学下册教学计划范文
  • php模板和框架,php模板和框架的区别的区别是什么
  • RocketMQ、Kafka、RabbitMQ、ActiveMQ各自特点及对比
  • 街道司法科秘书的个人工作小结
  • 走出职业迷茫,做好未来规划
  • icloud照片最简便批量的下载方法
  • 求1000!结果末尾有多少个0
  • 带动物的四字词语
  • Spark学习笔记6-Spark分布式搭建(5)??ubuntu下Spark分布式搭建
  • 辅导员工作心得体会:在爱与被爱中成长
  • 十二时辰和人体经络时表
  • 作家村上春树名句语录
  • mac版safari开启调试模式
  • DELL RACADM 工具使用介绍
  • 河南卫视雄关观后感
  • 数字取证技术 :Windows内存信息提取
  • 猜你喜欢

  • 最新创业计划书互联网电子商务大数据云计算(含视频片头)优质精选ppt通用模板
  • 高一其他作文:军训作文:军训的感受
  • CA车床电气控制改造PLC控制
  • A4奖状打印模板(三好学生、优秀班干部、优秀员工等等)
  • 福师《货币银行学》在线作业二15秋满分答案
  • 《西餐工艺学》单元12 西餐礼仪
  • 如何去除妊娠纹的好方法
  • 2020学校工会年度工作计划
  • 小学品德与社会北师大版五年级下《5中国人民站起来了》省级名师授课教案优质课教案获奖教案公开课教案A001
  • 长臂白颊猿
  • 宁波去舟山旅游攻略
  • 教育最新K12福建省华安县第一中学2017-2018学年高二英语上学期期末考试题(含解析)
  • 广东省职业技能鉴定高级数控车工知识考题SKC020925
  • 保持完美 10位大牌女星绝密的饮食减肥法
  • 彝良县恒天天麻种植有限公司(企业信用报告)- 天眼查
  • 内蒙古巴彦淖尔市第一中学2017-2018学年高二上学期9月月考物理试题Word版含解析
  • 广东中南信达投资管理有限公司(企业信用报告)- 天眼查
  • 家长写给初中生的一封信
  • 河北大广光电科技有限公司(企业信用报告)- 天眼查
  • cf搞笑顺口溜
  • 北师大版数学七年级下期末考试试题
  • 排气阀空气弹簧系统故障及应对措施
  • 六年级实验报告单—制作铁钉电磁铁
  • 新规下的专业学位型研究生教学模式探索
  • 四川材料科技开发部企业信用报告-天眼查
  • 凌海市志伟农机专业合作社企业信用报告-天眼查
  • 等你回家文章
  • 叙事诗:节妇吟*试上张籍水部ppt课件
  • 药妆品在我国的发展历史及研究现状和应用前景
  • 醋水洗脸可以增加皮肤细胞的水分和营养
  • 最新人教版四年级数学下册常见判断题、选择题
  • 志愿者医院服务管理暂行规定
  • 教科版小学六年级科学上册《4.8、生物多样性的意义》教案(2)【精品】
  • 【述职报告】20XX年区审计局纪检组长述职述廉报告
  • vue3中的toRef 与ref 区别
  • 机械设计(第八版)课后习题答案及解析(最新_参考答案及解析)
  • 2019-2020年二级建造师《公路工程管理与实务》模拟考试(II卷) 含答案
  • 宝宝多大可以吃土豆泥宝宝吃土豆泥有什么好处
  • 泸州艺术摄影作品赏析
  • 怎么知道本机号码是多少
  • 简约创意活动策划发布会动态PPT模板
  • 动物识别系统实验报告 人工智能原理及其应用
  • 电脑版