picACG本地缓存目录_前端工程师必备之缓存问题
缓存是个老生长谈的问题,对于前端工程师来讲更是我们的必修课。或许很多人会说我的项目并没有问题,根本不需要聊什么缓存。如果真的是这样,只能证明你前端道路才刚刚开始。
背景
小郭今天分享缓存的原因在于:公司的一个核心APP中嵌入了SPA,而且应用核心都分布在SPA中,功能复杂且重。问题出现了:应用核心页面打开一直处于加载状态,排除掉弱网环境的原因,重点就在于没有缓存,每次进入页面都需要重载DOM和数据,拖慢页面打开速度。
那应该处理缓存问题呢?接下来小郭从三个方向来讲解。
浏览器缓存策略
在了解浏览器缓存前,我们需要先了解一下相关的概念:cache-control,expires,last-Modified,ETag。
浏览器通过请求头实现缓存,关键的请求头有cache-control,expires,last-Modified,ETag等。我们从时间和空间两个角度来看浏览器缓存。
时间
浏览器发送第一次请求:不缓存,服务端根据设定的缓存策略返回相应的header,如:cache-control,expires,last-Modified,ETag。
浏览器发送第二次请求:
- 强缓存策略:不需要和服务端通信就决定是否使用缓存,cache-control优先级大于expires① 有cache-control且不过期,返回本地磁盘缓存,状态值200;② 有expires且不过期,返回本地磁盘缓存,状态值200。
- 协商缓存策略:需要和服务端通信决定是否用缓存,Etag优先级大于last-Modified。① 有Etag,请求头添加If-None-Match,值就是上次返回的Etag值,然后发送给服务端。服务端对比If-None-Match与现有的Etag值是否一样;一样的话只返回header,状态码304,浏览器从本地磁盘获取缓存信息;不一样走正常流程,返回header+body,状态码200;② 有last-Modified,添加请求头If-Modified-Since,值是上次返回的last-Modified,然后发送给服务端。服务端对比If-Modified-Since与现有的是否一样;一样的话返回只返回header,状态码304,浏览器从本地磁盘获取缓存信息;不一样走正常流程,返回header+body,状态码200
- 无缓存
空间
- 浏览器和服务端:服务端需要决定使用哪种缓存策略并在响应头返回;前端不需要设置,是浏览器本身机制。
- html和静态资源:通常html不设置缓存,因为其它资源的入口都是html文件;静态资源(js,css,图片等)会设置缓存
部署时缓存的问题
如果缓存就按理论上设置,那就太简单了。在实际应用有个严重的问题,我们不仅要缓存代码,还需要更新代码。如果静态资源名字不变,怎么让浏览器即能缓存又能在有新代码时更新。最简单的解决方式就是静态资源路径添加一个版本值,版本不变就走缓存策略,版本变了就加载新资源。如下:
然而这种处理方式在部署时有问题。
解决方法:静态资源和页面是分开部署
- 先部署页面再部署静态资源,会出现用户访问到旧的资源
- 先部署静态资源再部署页面,会出现没有缓存用户加载到新资源而报错
这些问题的本质是以上的部署方式是“覆盖式发布”,解决方式是“非覆盖式发布”。即用静态资源的文件摘要信息给文件命名,这样每次更新资源不会覆盖原来的资源,先将资源发布上去。这时候存在两种资源,用户用旧页面访问旧资源,然后再更新页面,用户变成新页面访问新资源,就能做到无缝切换。简单来说就是给静态文件名加hash值。
那如何实现呢?
现在前端代码都用webpack之类的构建工具打包,那么结合webpack该怎么做,怎么才能做到持久化缓存?
webpack持久化缓存
一、webpack给文件名添加hash值是很简单的,但hash/chunkhash/contenthash要用哪个呢?
官方定义
hash: unique hash generated for every build
chunkhash: hashes based on each chunks' content
contenthash: hashes generated for extracted content
根据分析,contenthash才是我们需要的,内容有更新,hash值才会更新。
二、webpack会打包业务代码、第三方库及运行时代码,为保证缓存互不干扰,应该将它们提取出来。
第三方库提取方式是设置optimization的splitChunks的cacheGroups。splitChunks能提取模块,cacheGroups能缓存模块,并且cacheGroups的配置会覆盖splitChunks相同配置,既能提取又能缓存,故只需设置cacheGroups。
运行时代码的提取方式为配置runtimeChunk,默认为false,表示运行时代码嵌入到不同的chunk文件中;现在将运行时代码提取出来,并命名为manifest。
module.exports = { entry: { index: "./src/index.js", bar: "./src/bar.js" }, output: { filename: "[name].[contenthash].js" }, optimization: { splitChunks: { cacheGroups: { vendor: { test:/[/]node_modules[/]/, name: "vendors", chunks: "all" } } }, runtimeChunk: { name: "manifest" } }};
三、 moduleName 和 chunkName 对文件的影响
module:就是js模块
chunk:webpack编译过程中由多个module组成的文件
bundle:bundle是chunk文件的最终状态,是webpack编译后的结果
一个文件被分离为3个文件,文件间怎么相互依赖的,会影响彼此打包,解决方法是将moduleId和chunkId改成按照文件路径生成。
optimization: { moduleIds: 'hashed', namedModules: true, namedChunks: true}
这样子moduleId在编译后的文件是文件目录的hash值,更加安全。这也是namedChunks在production默认为false的原因,不想依赖的文件路径在编译后的文件直接展示,但是为了持久性缓存,这里也只能打开。
四、CSS文件缓存
当css代码提取成单独文件,当我们改变css时,怎么保证不影响引用它的js文件呢?配置如下:
plugins: [ new MiniCssExtractPlugin({ filename: "[contenthash].css" })]
webpack持久化缓存目标是当且仅当该文件内容变动才改变该文件名字的hash值
const MiniCssExtractPlugin = require("mini-css-extract-plugin");module.exports = { output: { filename: [name].[contenthash].js, // 让hash值只在内容变动时更新 chunkFilename: [name].[contenthash].js // 动态引入的模块命名,同上 }, module: { rules: [ { test: /.css$/, use: [ "loader: MiniCssExtractPlugin.loader", // 提取出来css "css-loader" ] } ] }, optimization: { moduleIds: "hashed", // 混淆文件路径名 runtimeChunk: { name: 'manifest' }, // 提取runtime代码命名为manifest namedModules: true, // 让模块id根据路径设置,避免每增加新模块,所有id都改变,造成缓存失效的情况 namedChunks: true, // 避免增加entrypoint,其他文件都缓存失效 cacheGroups: { vendor: { // 提取第三方库文件 test: /[/]node_modules[/]/, name: 'vendors', chunks: 'all', }, }, } plugins: [ new webpack.HashedModuleIdsPlugin(), // 与namedModules: true作用一样 new MiniCssExtractPlugin({ filename: "[contenthash].css", // css文件也是按contenthash命名 chunkFilename: "[contenthash].css", // 动态引入的css命名,同上 }) ], }
总结
浏览器有其缓存机制,想要既能缓存又能在部署时没有问题,需要给静态文件名添加hash值。在webpack中,有些配置能让我们实现持久化缓存。感兴趣的同学可以自行去测试哦!
有任何问题可以在下方留言,想了解更多前端知识欢迎关注公众号“一郭鲜”,文章也将同步于公众号,前端学习不迷路
picACG本地缓存目录_前端工程师必备之缓存问题相关推荐
- 优秀web前端工程师必备_优秀的Web工程师的技能和素质
优秀web前端工程师必备 In this one-on-one episode of the Versioning Show, Tim and David talk about what makes ...
- Vue常用的组件库大全【前端工程师必备】【实时更新】【移动端、PC端(web端)、数据可视化组件库(数据大屏) 、动画组件库、3D组件库】
Vue常用的组件库大全[前端工程师必备] (一)移动端 常用组件库 1)Vant ui 2)Cube UI 3)VUX 4) NuTUI 5)Mint ui 6)Varlet UI 7)OnsenUI ...
- 前端工程师必备九大网站
01 GitHub https://github.com/ 这个网站托管着很多优质的开源项目,像你可能听说过的 Linux,React,Vue,Webpack,JQuery等都在这个网站上开源.你可以 ...
- picACG本地缓存目录_手机上本地存储的哪些文件、文件夹不能删?
手机.电脑随着不断的使用,系统本身.系统工具.第三方应用都会不断产生一些临时文件和垃圾文件.手机产生的垃圾文件更是显得杂乱无章,虽然可以使用系统自带或第三方应用来清理垃圾,但在本地存储还是有大量的文件 ...
- picACG本地缓存目录_如何从缓存白嫖网易云音乐
如何从缓存白嫖网易云音乐 本文仅供学习和交流! 一切的起因都得从一个神秘的夜开始... 那天小猪在剪视频的时候,突然想用几首曲子作为 BGM,于是兴高采烈的想到了钟爱的网易云音乐.不过在小猪的印象中, ...
- nginx 带宽_前端工程师不可不知的Nginx知识
历史背景 互联网的全球化导致了互联网的数据量快速增长,加上在本世纪初摩尔定律在单核 CPU 上的失效,CPU 朝着多核方向发展,而 Apache 显然并没有做好多核架构的准备,它的一个进程同一时间只能 ...
- 前端传中文文件名_前端工程师需要掌握哪些知识,web前端开发规范总结
Web前端作为开发团队中不可或缺的一部分,需要按照相关规定进行合理编写(一部分不良习惯可能给自己和他人造成不必要的麻烦).不同公司不同团队具有不同的规范和文档.下面是根据不同企业和团队的要求进行全面详 ...
- 前端 流星特效_前端工程师流星
前端 流星特效 As part of my daily web browsing routine, I follow a number of front-end blogs. I'm always a ...
- nginx 过滤post报文 防火墙_前端开发必备的Nginx知识(值得收藏)
随着IT行业的发展,前端已经不仅仅只是页面层次,现在是一个大前端的时代,你不仅仅需要懂得如何部署项目,如果使用轻量型服务器,还要懂得如何使得你的页面响应更快,如何解决内外网API交互的问题,Nginx ...
最新文章
- MySQL 自增ID
- Django 【补充】ORM多对多正向查询
- Java是否为整数_Java问题 输入一个数判定其是否为整数
- jvm虚拟机_一文入门jvm虚拟机
- java基础知识一_Java基础知识(一)
- 定时器驱动数码管c语言程序,用c语言编写,实用定时器实现数码管15倒计时
- 解释SpringBoot之Ehcache 2.x缓存
- html清除require报错,javascript - requirejs加载报错问题?
- leetcode-6-Z字形变换
- php--PDO操作数据库
- java web js 创建文件夹_如何在web工程里用java代码用程序动态添加css,images,js等文件夹...
- 从放弃迅雷和IDM到自己开发下载工具 1
- html播放flv直播源,http-flv 直播
- 对计算机网络考研知识点归纳(不断更新中T)
- iTest使用说明_V4.5.1
- 使用Validation框架检查数据格式
- 港科夜闻|「广州粤港澳大湾区研究院」成立,香港科技大学校长史维教授获聘担任研究院顾问...
- K8S 部署 skywalking
- 雅可比矩阵和行列式(Jacobian)
- (Router)路由交换实验