PWA系列
PWA系列 - Workbox插件InjectManifest
不论是GenerateSW或是InjectManifest都是对PWA系列 - 我所知道的 Service Worker原生配置的封装,所以首先应该弄懂service workder原始配置
目录
manifest可安装workbox-webpack-plugin提供webpack插件InjectManifestworkbox-window提供给注册sw的window部分封装workbox-core提供控制函数workbox-precaching提供预缓存文件workbox-routing提供自定义路由注册函数workbox-strategies提供5中缓存策略对象workbox-cacheable-response提供响应对象workbox-expiration提供缓存过期对象
装包
npm i workbox-webpack-plugin copy-webpack-plugin@6.3.2 -D
npm i workbox-core workbox-cacheable-response workbox-expiration workbox-precaching workbox-routing workbox-strategies workbox-window
manifest可安装
首先解决最简单的,pwa可以像app一样安装在桌面,增加mainfest.json文件即可
在src下放favicon.ico、logo192.png、logo512.png、manifest.json文件
vue.config.js 配置
const WorkboxWebpackPlugin = require("workbox-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
configureWebpack: () => ({
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: "./src/favicon.ico", to: "" },
{ from: "./src/logo192.png", to: "" },
{ from: "./src/logo512.png", to: "" },
{ from: "./src/manifest.json", to: "" },
],
}),
new WorkboxWebpackPlugin.InjectManifest({
swSrc: "./src/sw.js",
swDest: "sw.js",
}),
],
}),
};
manifest.json 配置
{
"short_name": "PWA",
"name": "PWA Example",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#e50914",
"background_color": "#221f1f"
}
src目录下增加sw.js
可以看到导入了workbox-core和workbox-precaching包,作用在第一篇功能一样代替self.clients.claim()和预请求资源
import { clientsClaim } from "workbox-core";
import { precacheAndRoute } from "workbox-precaching";
// 放在顶部,sw获得控制权,不然是下次打开页面获得
clientsClaim();
// 跳过等待
self.skipWaiting();
// 预请求资源,__WB_MANIFEST变量会注册webpack打包的所有项目资源文件
precacheAndRoute(self.__WB_MANIFEST);
html文件增加head头
<link rel="manifest" href="/manifest.json" />
main.js入口文件注册sw.js
导入了workbox-window就是代替navigator.serviceWorker.register("/sw.js");这个写法
import { Workbox } from "workbox-window";
if ("serviceWorker" in navigator) {
const wb = new Workbox("sw.js");
// wb.addEventListener("installed", (event) => {
// if (event.isUpdate) {
// if (confirm("检查有新版,是否更新最新?")) {
// window.location.reload();
// }
// }
// });
wb.register();
}
效果
点击便可安装到桌面
扩展说明-sw.js增加外部路由规则
缓存逻辑在第一篇中说明了,可查看PWA系列 - 我所知道的 Service Worker,非预请求资源,可以增加自定义路由做缓存
根据域名加规则
将 fonts.googleapis.com 下的请求,采用StaleWhileRevalidate方式缓存到google-fonts-stylesheets这个名下
import { registerRoute } from "workbox-routing";
import { StaleWhileRevalidate, CacheFirst } from "workbox-strategies";
registerRoute(
({ url }) => url.origin === "https://fonts.googleapis.com",
new StaleWhileRevalidate({
cacheName: "google-fonts-stylesheets",
})
);
字体域名和过期时间
将 fonts.gstatic.com 下的请求采用CacheFirst方式缓存到google-fonts-webfonts名下
- 只缓存200状态码的数据
- 存60天,30个
import { ExpirationPlugin } from "workbox-expiration";
import { CacheableResponsePlugin } from "workbox-cacheable-response";
registerRoute(
({ url }) => url.origin === "https://fonts.gstatic.com",
new CacheFirst({
cacheName: "google-fonts-webfonts",
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
}),
new ExpirationPlugin({
maxAgeSeconds: 60 * 60 * 24 * 365,// 60天
maxEntries: 30,
}),
],
})
);
api接口缓存
CacheableResponsePlugin方式,如果接口通,则返回网络数据,如果接口不同,则返回缓存数据
import { StaleWhileRevalidate } from "workbox-strategies";
import { CacheableResponsePlugin } from "workbox-cacheable-response";
import { ExpirationPlugin } from "workbox-expiration";
registerRoute(
({ url }) =>
url.origin === "https://api.themoviedb.org" &&
url.pathname.startsWith("/3/discover/tv"),
new StaleWhileRevalidate({
cacheName: "movie-api-response",
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
}),
new ExpirationPlugin({ maxEntries: 1 }), // Will cache maximum 1 requests.
],
})
);
图片缓存
import { CacheFirst } from "workbox-strategies";
import { CacheableResponsePlugin } from "workbox-cacheable-response";
import { ExpirationPlugin } from "workbox-expiration";
registerRoute(
({ request }) => request.destination === "image",
new CacheFirst({
cacheName: "images",
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
}),
new ExpirationPlugin({
maxEntries: 60,
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
}),
],
})
);
js和css文件缓存
import { registerRoute } from "workbox-routing";
import { StaleWhileRevalidate } from "workbox-strategies";
registerRoute(
({ request }) =>
request.destination === "script" || request.destination === "style",
new StaleWhileRevalidate({
cacheName: "static-resources",
})
);