本篇主要介绍pwa的相关内容,nextjs相关的请参考nextjs项目以及vercel发布
vercel发布tips
当项目发布到vercel以后
- 将修改的内容push到分支后,会自动触发development环境的deploy。
- 将修改的内容merge到master并push后,会自动触发production环境的deploy。
pwa知识点
三个必备条件
- https站点 必须
service worker只能在https上使用,localhost除外 - 一个或多个service worker 必须
控制应用的网络请求,以及是否使用缓存响应网络请求 - manifest.json文件 非必须
描述应用的名字,启动url,icons等其他信息,需要安装应用的时候才需要此文件
service worker生命周期
上一个经典的图
对应上图
- installing阶段
注册sw,在此阶段可以设置cache缓存- install事件
- event.waitUntil()
延长installing阶段,用来自定义操作,比如设置缓存 - self.skipWaiting()
结束延长,进入下一阶段
- event.waitUntil()
- install事件
- installed阶段
sw设置完成 - activating
主要用来清理旧缓存或其他sw的资源- activate事件
- event.waitUntil()
延长activating阶段,清理旧缓存 - self.clients.claim()
结束延长,进入下一阶段
- event.waitUntil()
- activate事件
- activated
sw可以处理functional events - redundant
sw被另一个sw替代
service worker可使用的event
四步让next.js具备pwa
/public目录中新增manifest.json/public目录中新增service-worker.jsservice-worker.js必须在访问域名的根域名下,所以必须放在public目录下/pages/_document.js文件中的Head中插入<link rel="manifest" href="/manifest.json" />/pages/_app.js文件中注册service-worker.js
// _app.js
import React, {useEffect} from 'react';
import '../styles/globals.css'
import '../styles/antd.less';
import sw from '../utils/sw.js';
function MyApp({ Component, pageProps }) {
useEffect(()=>{
if ('serviceWorker' in navigator) {
// register service worker
navigator.serviceWorker.register('../service-worker.js');
}
}, [])
return <Component {...pageProps} />
}
export default MyApp
// manifest.json
{
"name" : "会员",
"short_name" : "会员",
"description" : "会员",
"start_url" : "/",
"display" : "standalone",
"orientation" : "any",
"background_color" : "#ACE",
"theme_color" : "#ACE",
"icons": [
{
"src" : "/logo.jpeg",
"sizes" : "72x72",
"type" : "image/png"
},
{
"src" : "/logo.jpeg",
"sizes" : "152x152",
"type" : "image/png"
},
{
"src" : "/logo.jpeg",
"sizes" : "192x192",
"type" : "image/png"
},
{
"src" : "/logo.jpeg",
"sizes" : "256x256",
"type" : "image/png"
},
{
"src" : "/logo.jpeg",
"sizes" : "512x512",
"type" : "image/png"
}
]
}
// service-worker.js
const
version = '1.0.2',
CACHE = version + '::ZiyiMember',
installFilesEssential = [
'/',
'/manifest.json',
'/favicon.ico',
'/logo.jpeg',
];
// install static assets
function installStaticFiles() {
return caches.open(CACHE)
.then(cache => {
return cache.addAll(installFilesEssential);
});
}
function clearOldCaches() {
return caches.keys()
.then(keylist => {
return Promise.all(
keylist
.filter(key => key !== CACHE)
.map(key => caches.delete(key))
);
});
}
self.addEventListener('install', event => {
event.waitUntil(
installStaticFiles()
.then(() => self.skipWaiting())
);
});
self.addEventListener('activate', event => {
event.waitUntil(
clearOldCaches()
.then(() => self.clients.claim())
);
});
self.addEventListener('fetch', event => {
if (event.request.method !== 'GET') return;
let url = event.request.url;
event.respondWith(
caches.open(CACHE)
.then(cache => {
return cache.match(event.request)
.then(response => {
if (response) {
return response;
}
return fetch(event.request)
.then(newreq => {
console.log('network fetch: ' + url);
if (newreq.ok) cache.put(event.request, newreq.clone());
return newreq;
})
.catch(()=>null);
});
})
);
});