refactor(pwa): migrate sw.js to TS (#7467)

* refactor(pwa): migrate sw.js to TS

* add gitattributes
This commit is contained in:
Joshua Chen 2022-05-23 14:22:56 +08:00 committed by GitHub
parent 2d94d575a1
commit 0c8e57de67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 42 deletions

4
.gitattributes vendored
View file

@ -32,9 +32,13 @@
# See https://github.com/github/linguist/blob/master/docs/overrides.md # See https://github.com/github/linguist/blob/master/docs/overrides.md
# generated files' diff will be minimized # generated files' diff will be minimized
**/__fixtures__/** linguist-generated **/__fixtures__/** linguist-generated
**/__mocks__/** linguist-generated
examples/** linguist-generated examples/** linguist-generated
.husky/** linguist-vendored .husky/** linguist-vendored
jest/** linguist-vendored jest/** linguist-vendored
admin/** linguist-documentation admin/** linguist-documentation
website/** linguist-documentation website/** linguist-documentation
packages/create-docusaurus/templates/** linguist-vendored packages/create-docusaurus/templates/** linguist-vendored
.eslintrc.* linguist-vendored
jest.config.* linguist-vendored
.stylelintrc.* linguist-vendored

View file

@ -6,11 +6,11 @@
*/ */
/* eslint-disable no-restricted-globals */ /* eslint-disable no-restricted-globals */
import {PrecacheController} from 'workbox-precaching'; import {PrecacheController, type PrecacheEntry} from 'workbox-precaching';
function parseSwParams() { function parseSwParams() {
const params = JSON.parse( const params = JSON.parse(
new URLSearchParams(self.location.search).get('params'), new URLSearchParams(self.location.search).get('params')!,
); );
if (params.debug) { if (params.debug) {
console.log('[Docusaurus-PWA][SW]: Service Worker params:', params); console.log('[Docusaurus-PWA][SW]: Service Worker params:', params);
@ -22,7 +22,7 @@ function parseSwParams() {
// https://developers.google.com/web/tools/workbox/guides/using-bundlers#code_splitting_and_dynamic_imports // https://developers.google.com/web/tools/workbox/guides/using-bundlers#code_splitting_and_dynamic_imports
// https://twitter.com/sebastienlorber/status/1280155204575518720 // https://twitter.com/sebastienlorber/status/1280155204575518720
// but looks it's working fine as it's inlined by webpack, need to double check // but looks it's working fine as it's inlined by webpack, need to double check
async function runSWCustomCode(params) { async function runSWCustomCode(params: {offlineMode: boolean; debug: boolean}) {
if (process.env.PWA_SW_CUSTOM) { if (process.env.PWA_SW_CUSTOM) {
const customSW = await import(process.env.PWA_SW_CUSTOM); const customSW = await import(process.env.PWA_SW_CUSTOM);
if (typeof customSW.default === 'function') { if (typeof customSW.default === 'function') {
@ -38,40 +38,34 @@ async function runSWCustomCode(params) {
/** /**
* Gets different possible variations for a request URL. Similar to * Gets different possible variations for a request URL. Similar to
* https://git.io/JvixK * https://git.io/JvixK
*
* @param {string} url
*/ */
function getPossibleURLs(url) { function getPossibleURLs(url: string) {
const possibleURLs = [];
const urlObject = new URL(url, self.location.href); const urlObject = new URL(url, self.location.href);
if (urlObject.origin !== self.location.origin) { if (urlObject.origin !== self.location.origin) {
return possibleURLs; return [];
} }
// Ignore search params and hash // Ignore search params and hash
urlObject.search = ''; urlObject.search = '';
urlObject.hash = ''; urlObject.hash = '';
// /blog.html return [
possibleURLs.push(urlObject.href); // /blog.html
urlObject.href,
// /blog/ => /blog/index.html // /blog/ => /blog/index.html
if (urlObject.pathname.endsWith('/')) {
possibleURLs.push(`${urlObject.href}index.html`);
} else {
// /blog => /blog/index.html // /blog => /blog/index.html
possibleURLs.push(`${urlObject.href}/index.html`); `${urlObject.href}${urlObject.pathname.endsWith('/') ? '' : '/'}index.html`,
} ];
return possibleURLs;
} }
(async () => { (async () => {
const params = parseSwParams(); const params = parseSwParams();
// eslint-disable-next-line no-underscore-dangle // eslint-disable-next-line no-underscore-dangle
const precacheManifest = self.__WB_MANIFEST; const precacheManifest = (
self as typeof globalThis & {__WB_MANIFEST: (string | PrecacheEntry)[]}
).__WB_MANIFEST;
const controller = new PrecacheController({ const controller = new PrecacheController({
// Safer to turn this true? // Safer to turn this true?
fallbackToNetwork: true, fallbackToNetwork: true,
@ -80,9 +74,7 @@ function getPossibleURLs(url) {
if (params.offlineMode) { if (params.offlineMode) {
controller.addToCacheList(precacheManifest); controller.addToCacheList(precacheManifest);
if (params.debug) { if (params.debug) {
console.log('[Docusaurus-PWA][SW]: addToCacheList', { console.log('[Docusaurus-PWA][SW]: addToCacheList', {precacheManifest});
precacheManifest,
});
} }
} }
@ -90,31 +82,30 @@ function getPossibleURLs(url) {
self.addEventListener('install', (event) => { self.addEventListener('install', (event) => {
if (params.debug) { if (params.debug) {
console.log('[Docusaurus-PWA][SW]: install event', { console.log('[Docusaurus-PWA][SW]: install event', {event});
event,
});
} }
event.waitUntil(controller.install(event)); (event as ExtendableEvent).waitUntil(
controller.install(event as ExtendableEvent),
);
}); });
self.addEventListener('activate', (event) => { self.addEventListener('activate', (event) => {
if (params.debug) { if (params.debug) {
console.log('[Docusaurus-PWA][SW]: activate event', { console.log('[Docusaurus-PWA][SW]: activate event', {event});
event,
});
} }
event.waitUntil(controller.activate(event)); (event as ExtendableEvent).waitUntil(
controller.activate(event as ExtendableEvent),
);
}); });
self.addEventListener('fetch', async (event) => { self.addEventListener('fetch', async (event) => {
if (params.offlineMode) { if (params.offlineMode) {
const requestURL = event.request.url; const requestURL = (event as FetchEvent).request.url;
const possibleURLs = getPossibleURLs(requestURL); const possibleURLs = getPossibleURLs(requestURL);
for (let i = 0; i < possibleURLs.length; i += 1) { for (const possibleURL of possibleURLs) {
const possibleURL = possibleURLs[i];
const cacheKey = controller.getCacheKeyForURL(possibleURL); const cacheKey = controller.getCacheKeyForURL(possibleURL);
if (cacheKey) { if (cacheKey) {
const cachedResponse = caches.match(cacheKey); const cachedResponse = caches.match(cacheKey) as Promise<Response>;
if (params.debug) { if (params.debug) {
console.log('[Docusaurus-PWA][SW]: serving cached asset', { console.log('[Docusaurus-PWA][SW]: serving cached asset', {
requestURL, requestURL,
@ -124,7 +115,7 @@ function getPossibleURLs(url) {
cachedResponse, cachedResponse,
}); });
} }
event.respondWith(cachedResponse); (event as FetchEvent).respondWith(cachedResponse);
break; break;
} }
} }
@ -133,15 +124,14 @@ function getPossibleURLs(url) {
self.addEventListener('message', async (event) => { self.addEventListener('message', async (event) => {
if (params.debug) { if (params.debug) {
console.log('[Docusaurus-PWA][SW]: message event', { console.log('[Docusaurus-PWA][SW]: message event', {event});
event,
});
} }
const type = event.data?.type; const type = (event as MessageEvent).data?.type;
if (type === 'SKIP_WAITING') { if (type === 'SKIP_WAITING') {
self.skipWaiting(); // lib def bug, see https://github.com/microsoft/TypeScript/issues/14877
(self as typeof globalThis & ServiceWorkerGlobalScope).skipWaiting();
} }
}); });
})(); })();

View file

@ -1,6 +1,9 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"references": [{"path": "./tsconfig.client.json"}], "references": [
{"path": "./tsconfig.client.json"},
{"path": "./tsconfig.worker.json"}
],
"compilerOptions": { "compilerOptions": {
"noEmit": false, "noEmit": false,
"incremental": true, "incremental": true,
@ -13,6 +16,7 @@
"exclude": [ "exclude": [
"src/theme/", "src/theme/",
"src/registerSw.ts", "src/registerSw.ts",
"src/sw.ts",
"src/renderReloadPopup.tsx", "src/renderReloadPopup.tsx",
"**/__tests__/**" "**/__tests__/**"
] ]

View file

@ -0,0 +1,17 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"noEmit": false,
"composite": true,
"incremental": true,
"lib": ["webworker", "esnext"],
"tsBuildInfoFile": "./lib/.tsbuildinfo-worker",
"rootDir": "src",
"outDir": "lib",
"module": "esnext",
"target": "esnext",
"types": ["node"]
},
"include": ["src/sw.ts"],
"exclude": ["**/__tests__/**"]
}