Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 650|回复: 0

为 VUE 项目添加 PWA 解决发布后刷新报错问题

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-4-14 13:52:40 | 显示全部楼层 |阅读模式

    为什么要给 VUE 项目添加 PWA

    为什么要添加?因为不管是部署在 IIS,还是 nginx,每次应用部署后,再次访问因为旧的 js 已经不存在,所以页面访问的时候会整个报错,报错的结果就是一个白屏。
    为了解决这个问题,我的解决方案是使用 PWA ,这样就可以将 js 缓存到本地,再次发布后,service-worker.js 会使旧的 js 失效,重新请求并缓存 js。

    如果对于问题这个有更好的解决方案,务必请大佬指定一二

    安装 PWA 的相关依赖包

    yarn 安装

    yarn add sw-precache-webpack-plugin --dev
    yarn add uglify-es --dev
    

    npm 安装

    npm install sw-precache-webpack-plugin --dev-dev
    npm install uglify-es --dev-dev
    

    添加修改相关配置

    下面这些文件忘记出处是哪,Github也能搜到一些,之前写的 PWA 的 Demo 里面拿过来的~

    添加 build/service-worker-dev.js

    self.addEventListener('install', () => self.skipWaiting())
    
    self.addEventListener('activate', () => {
      self.clients.matchAll({ type: 'window' }).then(windowClients => {
        for (let windowClient of windowClients) {
          // Force open pages to refresh, so that they have a chance to load the
          // fresh navigation response from the local dev server.
          windowClient.navigate(windowClient.url)
        }
      })
    })
    

    添加 build/service-worker-prod.js

    ;(function() {
      'use strict'
    
      // Check to make sure service workers are supported in the current browser,
      // and that the current page is accessed from a secure origin. Using a
      // service worker from an insecure origin will trigger JS console errors.
      var isLocalhost = Boolean(
        window.location.hostname === 'localhost' ||
          // [::1] is the IPv6 localhost address.
          window.location.hostname === '[::1]' ||
          // 127.0.0.1/8 is considered localhost for IPv4.
          window.location.hostname.match(
            /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
          )
      )
    
      window.addEventListener('load', function() {
        if (
          'serviceWorker' in navigator &&
          (window.location.protocol === 'https:' || isLocalhost)
        ) {
          navigator.serviceWorker
            .register('service-worker.js')
            .then(function(registration) {
              // updatefound is fired if service-worker.js changes.
              registration.onupdatefound = function() {
                // updatefound is also fired the very first time the SW is installed,
                // and there's no need to prompt for a reload at that point.
                // So check here to see if the page is already controlled,
                // i.e. whether there's an existing service worker.
                if (navigator.serviceWorker.controller) {
                  // The updatefound event implies that registration.installing is set
                  var installingWorker = registration.installing
    
                  installingWorker.onstatechange = function() {
                    switch (installingWorker.state) {
                      case 'installed':
                        // At this point, the old content will have been purged and the
                        // fresh content will have been added to the cache.
                        // It's the perfect time to display a "New content is
                        // available; please refresh." message in the page's interface.
                        break
    
                      case 'redundant':
                        throw new Error(
                          'The installing ' + 'service worker became redundant.'
                        )
    
                      default:
                      // Ignore
                    }
                  }
                }
              }
            })
            .catch(function(e) {
              console.error('Error during service worker registration:', e)
            })
        }
      })
    })()
    

    添加 build/load-minified.js

    'use strict'
    
    const fs = require('fs')
    const UglifyJS = require('uglify-es')
    
    module.exports = function(filePath) {
      const code = fs.readFileSync(filePath, 'utf-8')
      const result = UglifyJS.minify(code)
      if (result.error) return ''
      return result.code
    }
    

    修改 build/webpack.prod.conf.js

    首先引用sw-precache-webpack-pluginbuild/load-minified

    const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin')
    const loadMinified = require('./load-minified')
    

    为 webpack 插件 HtmlWebpackPlugin 添加参数 serviceWorkerLoader: `<script>${loadMinified( path.join(__dirname, './service-worker-prod.js'))}</script>

      plugins: [
          ....
      new HtmlWebpackPlugin({
          filename:
            process.env.NODE_ENV === 'testing' ? 'index.html' : config.build.index,
          template: 'index.html',
          inject: true,
          minify: {
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true
            // more options:
            // https://github.com/kangax/html-minifier#options-quick-reference
          },
          // necessary to consistently work with multiple chunks via CommonsChunkPlugin
          chunksSortMode: 'dependency',
          serviceWorkerLoader: `<script>${loadMinified( path.join(__dirname, './service-worker-prod.js'))}</script>`
        }),
    

    并在最后添加 SWPrecacheWebpackPlugin 插件

    // service worker caching
    new SWPrecacheWebpackPlugin({
      cacheId: 'web_pwa',
      filename: 'service-worker.js',
      staticFileGlobs: ['dist/**/*.{js,html,css}'],
      minify: true,
      stripPrefix: 'dist/'
    })
    

    在 /index.html 中注入 service-worker.js

    <%= htmlWebpackPlugin.options.serviceWorkerLoader %>
    

    如下所示

    
    <body>
      <div id="app"></div>
      <%= htmlWebpackPlugin.options.serviceWorkerLoader %>
      <!-- built files will be auto injected -->
    </body>   
    

    至此,添加完毕,build 之后查看缓存中是否包含 js 检验结果

    注意:PWA 应用需要在本地上运行或者 https 协议下, 要保证你的页面是安全页面。

    结语

    几分钟就搞定了,然后把之前的一个基于VUE的后台模板项目也升级了,如果有相同需求的可以参考下。

    仓库地址:https://github.com/yimogit/me-admin-template
    线上预览:https://vue-admin.yimo.link/

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

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

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-1-24 17:32 , Processed in 0.064519 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

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