history,hash缓存那些事

打印 上一主题 下一主题

主题 532|帖子 532|积分 1596

vue-router 中的 createWebHistory,createWebHashHistory两种模式

createWebHistory

是基于 window.history 对象是HTML5提供的用于维护当前标签页浏览历史的对象,重要功能是前进后退和在不刷新页面的情况下,修改地址栏里的URL地址。history 模式就是利用了 HTML5 historyAPI,所以也叫 HTML5 模式,Vue Router 中是用 createWebHistory() 创建。地址发生变化 都会出现404 而404 会在服务器上映射到index.html中,重新哀求资源!
createWebHashHistory

是用 createWebHashHistory() 创建,hash指的是地址中 # 号以及后面的字符,这个 # 就是hash符号,中文名叫哈希符或锚点,哈希符后面的值,我们称之为哈希值!我们虽然在访问的过程,在 URL 会出现#,但是此方式不会抱憾在HTTP的哀求中,所以对服务器没有任何影响,因为此方式不颠末服务器,所以url的hash的改变不会重新加载页面,所以如果第一次加载完html 之后在后面操纵都会出现,不会是最新的资源的情况!但是这中对SEO也有影响!
缓存

为了后面更好的归类,这里我把缓存分为两类,一类是静态资源,不管是图片 js css 等等 只要是打包生成出来的同一叫静态资源,第二种就是动态的 也就是我们在哀求服务器的接口动态处理惩罚dom 填补动态数据!
动态资源缓存题目

不难看出,就是哀求的url被缓存啦,其实也好好处理惩罚,前端项目基本都是同一的哀求器,直接在哀求器上同一拦截,url上加上时间戳后缀!如许保证每次url 不是类似的,这个在以前的项目中 ,客户用的ie浏览器,get哀求 都被缓存,这个貌似是IE的特殊性的坑!当时就通过时间戳的形式处理惩罚!如果没有同一的哀求器的,要么一个一个改,要么写个xhr去处理惩罚!
静态资源缓存题目

无论createWebHistory,createWebHashHistory的哪一种打包生成的一些静态资源做一次文件签名即可,vite.config.js设置处理惩罚,如许处理惩罚每次打包都会变更js的文件名,默认的只会改动变更的文件,
  1.   build: {
  2.     hash: true,
  3.     manifest: true,
  4.     rollupOptions: {
  5.       output: {
  6.         // 入口文件名
  7.         entryFileNames: `assets/[name].${timeStamp}.js`,
  8.         // 块文件名
  9.         chunkFileNames: `assets/[name]-[hash].${timeStamp}.js`,
  10.         // 资源文件名 css 图片等等
  11.         assetFileNames: `assets/[name]-[hash].${timeStamp}.[ext]`,
  12.       },
  13.     },
  14.   }
复制代码
  nginx 上禁止缓存html
  1.         location = /index.html {
  2.             root /Volumes/wanglaibin/work/vite-project/dist;
  3.             expires 0;
  4.             add_header Cache-Control "no-cache, no-store, must-revalidate";
  5.         }
复制代码
  index.html 上禁止html
  1. <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
  2. <meta http-equiv="Pragma" content="no-cache">
  3. <meta http-equiv="Expires" content="0">
复制代码
上面的设置,无关createWebHistory,createWebHashHistory,因为只要重新加载html都会哀求最新的资源,只是createWebHistory相对友好,因为每次地址变更都会哀求都会颠末服务器,而createWebHashHistory只有在第一次加载大概F5刷新才会哀求资源。
针对createWebHashHistory的缓存方式

   该方式怎样处理惩罚,我们都知道,每次url地址变更没有颠末服务器,所以才造成一个后面全部操纵都会以第一次的加载html资源做处理惩罚,后面发布变,前端在方式过程中,只要不发生重载html的操纵,都会出现哀求旧的资源,如果没有访问过资源,大概出现找不到资源的情况!
    我们知道这个造成的缘故原由,所以我们通过某种方式,来告知相应的版本更新,做一次资源的重新加载!所以我们只能从路由的钩子上做处理惩罚,当我们路由变更时,哀求前端的某个资源文件,记录当前的hash值,每次变更跟客户端做相应的比力,如果不一致,直接通知用户,当前系统版本升级,需要重新加载!之后重载整个html的入口!现在两种方式可以处理惩罚:
    第一种在 vite中的异常变乱中处理惩罚,在vite加载动态导入失败时,会触发 vite:preloadError 变乱,所以我们监听这个错误变乱,不过这种如果以前缓存过文件,改方式也不会出发最新的操纵
  1. window.addEventListener('vite:preloadError', (event) => {
  2.   console.log('检测到有新版本,5秒后即将刷新...');
  3.   // 更好的用户体验 可以做个tips
  4.   setTimeout(() => {
  5.     window.location.reload(true) // 例如,刷新页面
  6.     console.log('页面已更新为最新版本...');
  7.   }, 5000)
  8. })
复制代码
  第二种在 打包的过程中,我们生成相应的json文件信息,在路由的哀求的钩子上处理惩罚,每次路由变更哀求对比版本变化来决定是否做一个重载url;
在vite.config.js中编写插件生成相应的json文件
  1. import { fileURLToPath, URL } from 'node:url'import upgradePlugin from './version-upgrade-plugin'...const timeStamp = new Date().getTime();// https://vitejs.dev/config/export default defineConfig({  define: {    __APP_VERSION__: timeStamp,  },  plugins: [    ...    upgradePlugin({      version: timeStamp    })  ],  ...  build: {
  2.     hash: true,
  3.     manifest: true,
  4.     rollupOptions: {
  5.       output: {
  6.         // 入口文件名
  7.         entryFileNames: `assets/[name].${timeStamp}.js`,
  8.         // 块文件名
  9.         chunkFileNames: `assets/[name]-[hash].${timeStamp}.js`,
  10.         // 资源文件名 css 图片等等
  11.         assetFileNames: `assets/[name]-[hash].${timeStamp}.[ext]`,
  12.       },
  13.     },
  14.   }
  15. })
复制代码
  version-upgrade-plugin.js
  1. export default (options) => {
  2.   let config
  3.   return {
  4.     name: 'version-upgrade',
  5.     configResolved(resolvedConfig) {
  6.       // 存储最终解析的配置
  7.       config = resolvedConfig
  8.     },
  9.     async buildStart() {
  10.       console.log('')
  11.       console.log('生成项目文件信息')
  12.       const fs = await import('fs').then((module) => module.default);
  13.       const path = await import('path').then((module) => module.default)
  14.       // 生成版本信息文件路径
  15.       const file = config.publicDir + path.sep + 'version.json'
  16.       // 这里使用编译时间作为版本信息
  17.       const content = JSON.stringify({ version: options.version })
  18.       if (fs.existsSync(config.publicDir)) {
  19.         writeVersion(file, content)
  20.       } else {
  21.         fs.mkdir(config.publicDir, (err) => {
  22.           if (err) throw err
  23.           writeVersion(file, content)
  24.         })
  25.       }
  26.       console.log(config, file)
  27.     }
  28.   }
  29. }
  30. const writeVersion = async (versionFile, content) => {
  31.   const fs = await import('fs').then((module) => module.default);
  32.   // 写入文件
  33.   fs.writeFile(versionFile, content, 'utf8', (err) => {
  34.     if (err) throw err
  35.   })
  36. }
复制代码
  路由上处理惩罚
  1. router.afterEach(async () => {
  2.   await isHeavyLoadPage();
  3. });
  4. function isHeavyLoadPage() {
  5.   if (process.env.NODE_ENV === 'development') return
  6.   fetch(`version.json?t=${Date.now()}`)
  7.     .then(res => res.json())
  8.     .then(data => {
  9.       console.log(data)
  10.       if (__APP_VERSION__ !== data.version) {
  11.         alert(__APP_VERSION__, data.version)
  12.         setTimeout(() => {
  13.           window.location.reload(true) // 例如,刷新页面
  14.           console.log('页面已更新为最新版本...');
  15.         }, 5000)
  16.       }
  17.     })
  18.     .catch(function (e) {
  19.       console.log(e)
  20.     })
  21. }
复制代码
其实我们做项目找到题目的本质,从本质上找相应的办理方案举行处理惩罚,才不会无任何头绪!也不至于没有任何方向!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

干翻全岛蛙蛙

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表