前言
最近这一年,作为一名前端狗,一直在优化性能的道路一去不回头。vue、nginx、webpack、redis,能做优化的地方,都不曾放过,只为那最后一秒的舒爽!(猥琐的一笑)。
之前一直对PWA所有关注,希望通过PWA对目前的项目做一次性能上的提升,趁着最近还算有点时间,对现在公司使用的前端结构做一次改造!
本次改造主要分两部分:
- 改造基于vue cli3创建的项目
- 改造基于webpack3.0打包的项目
关于PWA和Service Work的相关知识,在这里就不过多介绍了,大家可以自行百度
改造基于vue cli3创建的项目
新项目直接在vue create的时候,选择PWA模板,就可以启用PWA,这里主要介绍如果在已有项目中启用PWA
1. 安装PWA插件
vue add pwa
需要注意的是vue cli3 是基于workbox来实现PWA
2.目录结构
安装完插件后,目录结构如下:
- registerServiceWorker.js:负责注册service work
- service-worker.js:自定义的service work配置文件
3.修改registerServiceWorker.js,做兼容处理
目前部分浏览器还不支持service work,我们需要保证它们依旧能正常工作。 通过'serviceWorker' in window.navigator
来判断浏览器是否支持sw,具体代码如下:
/* eslint-disable no-console */
import {register} from 'register-service-worker';
if ('serviceWorker' in window.navigator && process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
ready() {
console.log(
'App is being served from cache by a service worker.\n' +
'For more details, visit https://goo.gl/AFskqB'
);
},
registered() {
console.log('Service worker has been registered.');
},
cached() {
console.log('Content has been cached for offline use.');
},
updatefound() {
console.log('New content is downloading.');
},
updated() {
console.log('New content is available; please refresh.');
},
offline() {
console.log('No internet connection found. App is running in offline mode.');
},
error(error) {
console.error('Error during service worker registration:', error);
}
});
}
4.编写service-work.js
完整的service-work,可以参考我们的前端模板工程中service-work.js,下面我们来逐步介绍:
- 设置缓存的前缀和后缀,我们一般用项目名作为前缀,版本号作为后缀
workbox.core.setCacheNameDetails({
prefix: 'easy-front-vue-cli3',
suffix: 'v1.0.0'
});
- 配置service work的更新激活策略
workbox.core.skipWaiting(); // 强制等待中的 Service Worker 被激活
workbox.core.clientsClaim(); // Service Worker 被激活后使其立即获得页面控制权
- 设置预加载
workbox.precaching.precacheAndRoute(self.__precacheManifest || []);
- 设置资源缓存策略 workbox主要提供了以下几种缓存策略:
Stale-While-Revalidate:使用缓存的内容(如果可用)尽快响应请求,如果未缓存,则使用网络请求。 然后,网络请求得到数据用于更新缓存。
Cache First:如果请求命中缓存,则将使用缓存的响应来完成请求,不会使用网络。 如果没有命中缓存,将通过网络请求来获取数据,并且将数据缓存,以便下次直接从缓存获取数据。该模式可以为前端提供快速响应的同时,减轻服务器压力。但是数据的时效性就需要开发者通过设置缓存过期时间或更改service-work.js里面的修订标识来完成缓存文件的更新
Network First:优先从网络获取最新数据。 如果成功,它会将数据放入缓存。如果网络无法返回响应,则将使用缓存数据。
Network Only:只使用网络请求数据
Cache Only:只使用缓存数据
具体使用什么策略,还是需要根据实际的业务场景和需求来设定,我采用的基本策略如下:
// 缓存web的css资源
workbox.routing.registerRoute(
// Cache CSS files
/.*\.css/,
// 使用缓存,但尽快在后台更新
workbox.strategies.staleWhileRevalidate({
// 使用自定义缓存名称
cacheName: 'css-cache'
})
);
// 缓存web的js资源
workbox.routing.registerRoute(
// 缓存JS文件
/.*\.js/,
// 使用缓存,但尽快在后台更新
workbox.strategies.staleWhileRevalidate({
// 使用自定义缓存名称
cacheName: 'js-cache'
})
);
// 缓存web的图片资源
workbox.routing.registerRoute(
/\.(?:png|gif|jpg|jpeg|svg)$/,
workbox.strategies.staleWhileRevalidate({
cacheName: 'images',
plugins: [
new workbox.expiration.Plugin({
maxEntries: 60,
maxAgeSeconds: 30 * 24 * 60 * 60 // 设置缓存有效期为30天
})
]
})
);
// 我们很多资源在其他域名上,比如cdn、oss等,这里做单独处理,需要支持跨域
workbox.routing.registerRoute(
/^https:\/\/cdn\.my\.com\/.*\.(jpe?g|png|gif|svg)/,
workbox.strategies.staleWhileRevalidate({
cacheName: 'cdn-images',
plugins: [
new workbox.expiration.Plugin({
maxEntries: 60,
maxAgeSeconds: 5 * 24 * 60 * 60 // 设置缓存有效期为5天
})
],
fetchOptions: {
credentials: 'include' // 支持跨域
}
})
);
// 缓存get api请求的数据
workbox.routing.registerRoute(
new RegExp('https://m.my.com/api'),
workbox.strategies.networkFirst({
cacheName: 'api'
})
);
// 缓存post api请求的数据
// const bgSyncPlugin = new workbox.backgroundSync.Plugin('apiQueue', {
// maxRetentionTime: 1 * 60
// });
// workbox.routing.registerRoute(
// /.*\/api\/.*/,
// new workbox.strategies.NetworkOnly({
// plugins: [bgSyncPlugin]
// }),
// 'POST'
// );
5.修改main.js
加入以下代码
import './registerServiceWorker';
6.修改vue.config.js
参考我们的前端模板工程中vue.config.js.js,下面列举了跟PWA相关的部分:
pwa: {
name: 'easy-front-vue-cli3',
themeColor: '#4DBA87',
msTileColor: '#000000',
appleMobileWebAppCapable: 'yes',
appleMobileWebAppStatusBarStyle: 'black',
// configure the workbox plugin (GenerateSW or InjectManifest)
workboxPluginMode: 'InjectManifest',
workboxOptions: {
// swSrc is required in InjectManifest mode.
swSrc: 'src/service-worker.js',
importWorkboxFrom: 'disabled',
importScripts: 'https://cdn.your.info/workbox-v4.3.1/workbox-sw.js'
// ...other Workbox options...
}
}
- workboxPluginMode:workbox的模式,GenerateSW使用默认模式,InjectManifest使用自定义模式,我推荐使用InjectManifest,自由度更大
- workboxOptions.swSrc: 指定service-worker.js所在位置
- workboxOptions.importWorkboxFrom: 引入workbox依赖库的方式,默认的依赖库在Google的cdn上,国内情况大家都懂,因此建议将依赖库放到大家自己的cdn上,所以我这里设置了
disabled
- workboxOptions.importScripts: 指定你自己的依赖库的cdn的url
7.配置manifest.json
PWA支持创建快捷方式,manifest.json包含了快捷方式的名称、图标、入口路径等配置。 如果不需要快捷方式,也可以不创建
{
"name": "easy-front-vue-cli3",
"short_name": "easy-front-vue-cli3",
"icons": [
{
"src": "/img/icons/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/img/icons/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "/",
"display": "standalone",
"background_color": "#000000",
"theme_color": "#4DBA87"
}
改造基于webpack3.0打包的项目
我们这里只介绍跟vue cli3不同的部分,registerServiceWorker.js、service-work.js和manifest.json这些相同部分就不重复介绍了。
1.安装依赖包
npm install workbox-webpack-plugin -D
npm install register-service-worker -S
2.修改webpack.prod.conf.js
// 在webpack中加入workbox插件,并进行配置
const {InjectManifest} = require('workbox-webpack-plugin');
webpackConfig.plugins.push(new InjectManifest({
swSrc: 'src/service-worker.js',
importWorkboxFrom: 'disabled',
importScripts: 'https://cdn.your.info/workbox-v4.3.1/workbox-sw.js'
}));
3.修改main.js
加入以下代码
import './registerServiceWorker';
参考
我的模板工程:easy-front-vue-cli3
workbox仓库地址:workbox
PWA学习资料:PWA应用实战
今天的文章Vue+PWA实践过程分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/18927.html