解决小程序内嵌web-view缓存问题

项目是通过web-view内嵌在小程序里的vue单页应用.然而前几天发现明明发布了代码,在小程序入口进去看到的还是旧页面,尝试以下操作:

  • 手动退出小程序,再次进入
  • 删除小程序,发现-小程序,重新进入
  • 关闭微信,杀掉进程,重新进入
  • 配置Cache-Control:在服务器中,给入口html页面的访问添加响应头,如在nginx中配置 Cache-Control 为 no-store, no-cache,这样浏览器访问页面时,就不会缓存该页面。
    img
  • 安卓手机清除微信浏览器缓存
    1. debugx5.qq.com 手动清除安卓微信浏览器缓存
    2. 使用工具debugtbs, 在微信上打开http://debugtbs.qq.com, 然后将所有清除的按钮点击一遍,下次再进去就可以了
  • iOS手机利用微信自带清除缓存功能
    打开微信,找到:我–设置–通用–存储空间–清理微信缓存,确定即可完成。

    img
  • 入口html文件设置meta标签
    1
    2
    3
    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Expires" content="0">
  • 给页面访问地址增加时间戳参数
    1
    2
    3
    const src = `https://XXX.com?timestamp=${new Date().getTime()}`;

    <web-view src='{{src}}'></web-view>
  • 在webpack打包的时候加上hash配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    module.exports = {
    optimization: {
    chunkIds: 'deterministic',
    },
    output: {
    entry: './src/index.js',
    mode: 'none',
    module: moduleConfig,
    output: {
    filename: '[name].[contenthash].js',
    // chunkFilename: '[name].[contenthash].chunk.js',
    path: path.resolve(__dirname, 'dist/contenthash'),
    clean: true
    },
    plugins: [
    new MiniCssExtractPlugin({
    // css 单独输出成文件
    filename: '[name].[contenthash].css'
    })
    ]
    },
    };
    build后的产物就类似于这种:/dist/main.103a1483.js 浏览器缓存策略识别到这是一个新的文件会去服务端从新请求资源,自然解决了缓存问题
    • 最后终极解决方案就是:在页面做版本管理
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      const getCurrentHash = (html) => {
      const curHashSrc = (html || document).getElementsByTagName('head')[0]
      .getElementsByTagName('script')[2].src.split('/');
      return curHashSrc[curHashSrc.length - 1].split('.')[0]?.split('-')?.[1];
      };
      const fetchNewHash = async () => {
      // 在 js 中请求首页地址不会更新页面
      const timestamp = new Date().getTime();
      const response = await fetch(`${window.location.origin}?time=${timestamp}`);
      if (!response.ok) {
      throw new Error('Network response was not ok ' + response.statusText);
      return;
      }
      // 返回的是字符串,需要转换为 html
      const el = document.createElement('html');
      el.innerHTML = await response.text();
      // 拿到 hash
      const newHash = getCurrentHash(el)
      const currentHash = getCurrentHash();
      console.log('%cnewHash: %c%s %ccurrentHash: %c%s',
      'color: #000;',
      'color: red;',
      newHash,
      'color: #000;',
      'color: green;',
      currentHash
      );
      if (newHash && newHash !== currentHash) {
      // 版本更新,弹出提示
      console.log('%c有新版本更新', 'color: red; font-size: 16px;');
      window.location.reload();
      } else if (newHash && newHash === currentHash) {
      //没有版本更新
      console.log('%c没有新版本更新', 'color: green; font-size: 16px;');
      }
      }
      export default fetchNewHash;