为什么要给 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. sql server 分区(上)

    分区发展历程      基于表的分区功能为简化分区表的创建和维护过程提供了灵活性和更好的性能.追溯到逻辑分区表和手动分区表的功能. 二.为什么要进行分区 为了改善大型表以及具有各种访问模式的表的可伸缩 ...

  2. 推荐《用Python进行自然语言处理》中文翻译-NLTK配套书

    NLTK配套书<用Python进行自然语言处理>(Natural Language Processing with Python)已经出版好几年了,但是国内一直没有翻译的中文版,虽然读英文 ...

  3. mysql left join 左连接查询关联n多张表

    left join 左连接即以左表为基准,显示坐标所有的行,右表与左表关联的数据会显示,不关联的则不显示.关键字为left join on. **基本用法如下: select table a left ...

  4. c# xml操作(一)

    c# xml操作(一) 此博文包含图片 (-- ::)转载▼ 标签: 杂谈 分类: c# 同样是增,删,改,查四种操作.现在我们就详细介绍一下增和删两种操作.看下面的一个xml示例: <?xml ...

  5. 如何把word中的图片怎么导出来呢?

    在办公使用word的过程中你可能经常会遇到这个问题:插入到word中的图片找不到导出来的方法,是不是很郁闷呢,别急,今天咱们研究一下把word中的图片导出来的方法(把"我的"变成你 ...

  6. 记录一波由会话堵塞导致tomcat应用故障事件

    一.故障基本信息 发生时间 消除时间 故障历时 故障类别 影响 2018-5-17 18:14:30 2018-05-18 08:58:15 16小时 应用故障 业务瘫痪,用户投诉 二.故障现象 AP ...

  7. BZOJ_4818_[Sdoi2017]序列计数_矩阵乘法

    BZOJ_4818_[Sdoi2017]序列计数_矩阵乘法 Description Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数.Alice还希望 ...

  8. 【爆料】-《布莱顿大学毕业证书》Brighton一模一样原件

    布莱顿大学毕业证[微/Q:2544033233◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归&am ...

  9. XSS过滤JAVA过滤器filter 防止常见SQL注入

    Java项目中XSS过滤器的使用方法. 简单介绍: XSS : 跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩 ...

  10. jdk源码阅读笔记-Integer

    public final class Integer extends Number implements Comparable<Integer> Integer 由final修饰了,所以该 ...