为什么要给 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/

为 VUE 项目添加 PWA 解决发布后刷新报错问题的更多相关文章

  1. 前端vue项目部署到tomcat,一刷新报错404解决方法

    公司前端写的后台部署到tomcat webapps目录下后,无法进行刷新,一刷新就会报错404,自动跳的404页面.在网上查了下,官方说是HTML5 History 模式引发的问题,但是解决方案中,并 ...

  2. 让 Mongoose 不再重复链接数据库(如何正确连接以解决升级后的报错)

    升级了 Mongoose 后,发现项目打不开了.报错: MongooseError: You can not `mongoose.connect()` multiple times while con ...

  3. Vue项目中执行npm run dev 不报错也不显示点击的地址链接

    问题描述: 输入npm run dev 没有报错也没有显示可以点击的地址链接,如下图: 解决方法: 具体配置: autoOpenBrowser默认为false,改为true.重新 npm run de ...

  4. 微信小程序-解决下拉刷新报错

    关于“enablePullDownRefresh”: “true” 一.使用方式 在 Page 中定义 onPullDownRefresh 处理函数,监听该页面用户下拉刷新事件.需要在 config ...

  5. Vue项目上线后刷新报错404问题(apache,nginx,tomcat)

    转自:https://www.cnblogs.com/sxshaolong/p/10219527.html 很简单,需要 服务器端 加个配置文件,然后 重启服务就好了,记住一定要 重启服务,否则无效!

  6. vue项目安装scss,以及安装scss报错(this.getResolve is not a function)

    1.安装scss: npm install node-sass sass-loader vue-style-loader --save-dev //安装node-sass sass-loader vu ...

  7. 如何为你的 Vue 项目添加配置 Stylelint

    如何为你的 Vue 项目添加配置 Stylelint 现在已经是 9102 年了,网上许多教程和分享帖都已经过期,照着他们的步骤来会踩一些坑,如 stylelint-processor-html 已经 ...

  8. Vue项目添加动态浏览器头部title

    0. 直接上 预览链接 + 效果图 Vue项目添加动态浏览器头部title 1. 实现思路 ( 1 ) 从路由router里面得到组件的title ( 2 ) title存vuex (本项目已经封装h ...

  9. Eclipse中导入项目后js报错解决方法(转未解决问题)

    本文转自:http://blog.csdn.net/chenchunlin526/article/details/54666882 Eclipse中导入项目后js报错的原因与解决方法 在我们将项目导入 ...

随机推荐

  1. jQuery上下滑动内容切换选项卡

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. CAPTCHA---验证码 ---Security code

    BotDetect Java CAPTCHA Generator 3. Add BotDetect Java CAPTCHA Library Dependency Here is how to add ...

  3. pymysql安装

    安装python3之后 链接数据库需要安装pymysql pymysql 下载地址 https://pypi.python.org/pypi/PyMySQL3/0.5 ,下载之后传到linux虚拟机, ...

  4. 7.app和app后端的通讯

    经常有开发者问:app和后端通讯是用http协议还是私有的协议?是用长连接还是短连接?通过阅读本文,帮你解除上面的疑问. (1)是用http协议还是私有的协议? 在间谍电视剧中,经常能看到间谍们的书信 ...

  5. webcron

    一个定时任务管理器,基于Go语言和beego框架开发.用于统一管理项目中的定时任务,提供可视化配置界面.执行日志记录.邮件通知等功能,无需依赖*unix下的crontab服务. 项目背景 开发此项目是 ...

  6. 【HTTP原理】TCP/IP三次握手和四次挥手

    HTTP连接 HTTP协议即超文本传送协议(Hypertext Transfer Protocol),是web联网的基础,也是手机联网常用的协议之一,http协议是建立在TCP协议之上的一种应用. H ...

  7. 【读书笔记】《Maven实战》第6章 仓库

    6.1什么是Maven仓库? Maven仓库:存储所有Maven项目共享的构件的统一位置. Maven仓库的作用:Maven项目仅需声明依赖坐标,即可在需要的时候自动根据坐标找到仓库中的构件. 6.2 ...

  8. Python并发编程之深入理解yield from语法(八)

    大家好,并发编程 进入第八篇. 直到上一篇,我们终于迎来了Python并发编程中,最高级.最重要.当然也是最难的知识点--协程. 当你看到这一篇的时候,请确保你对生成器的知识,有一定的了解.当然不了解 ...

  9. 【SAP HANA】SAP HANA开篇(1)

    有幸当前工作能够接触到SAP S/4,能够接触到史上无敌的HANA内存数据库.HANA的技术我就不多讲了,感兴趣的人可以去百度一下.当然,有人想在本机安装HANA来学习,但前提是你得有128G内存以上 ...

  10. 怎么动态生成js变量

    动态生成全局变量: //简单的用字符串作为变量名 window['hello'] = "hello, world"; alert(hello);   //批量定义 for(var  ...