Failed to load the script unexpectedly回避

sw.jsとlib.tsを分離してみた
This commit is contained in:
tamaina 2021-11-30 03:12:32 +09:00
parent 7e5ab7af1b
commit 47d77d14fd
6 changed files with 62 additions and 28 deletions

View File

@ -49,8 +49,14 @@ gulp.task('build:backend:style', () => {
.pipe(gulp.dest('./packages/backend/built/server/web/')); .pipe(gulp.dest('./packages/backend/built/server/web/'));
}); });
gulp.task('build:sw', () => {
return gulp.src(['./packages/sw/src/sw.js'])
.pipe(replace('VERSION', meta.version))
.pipe(gulp.dest('./built/_sw_dist_/'));
});
gulp.task('build', gulp.parallel( gulp.task('build', gulp.parallel(
'copy:client:locales', 'copy:backend:views', 'build:backend:script', 'build:backend:style', 'copy:client:fonts' 'copy:client:locales', 'copy:backend:views', 'build:backend:script', 'build:backend:style', 'copy:client:fonts', 'build:sw'
)); ));
gulp.task('default', gulp.task('build')); gulp.task('default', gulp.task('build'));

View File

@ -100,7 +100,12 @@ router.get('/twemoji/(.*)', async ctx => {
// ServiceWorker // ServiceWorker
router.get('/sw.js', async ctx => { router.get('/sw.js', async ctx => {
await send(ctx as any, `/sw.${config.version}.js`, { await send(ctx as any, `/sw.js`, {
root: swAssets
});
});
router.get(`/sw-lib.${config.version}.js`, async ctx => {
await send(ctx as any, `/sw-lib.js`, {
root: swAssets root: swAssets
}); });
}); });

View File

@ -8,7 +8,7 @@ export async function initializeSw() {
('serviceWorker' in navigator) && ('serviceWorker' in navigator) &&
('PushManager' in window) && ('PushManager' in window) &&
$i && $i.token) { $i && $i.token) {
navigator.serviceWorker.register(`/sw.js`, { scope: '/', type: 'module' }); navigator.serviceWorker.register(`/sw.js`, { scope: '/', type: 'classic' });
navigator.serviceWorker.ready.then(registration => { navigator.serviceWorker.ready.then(registration => {
registration.active?.postMessage({ registration.active?.postMessage({

View File

@ -1,7 +1,17 @@
/** /**
* Service Worker * Service Worker
*/ */
declare var self: ServiceWorkerGlobalScope; declare var self: ServiceWorkerGlobalScope & {
lib: {
oninstall: (ev: ServiceWorkerGlobalScopeEventMap['install']) => void;
onactivate: (ev: ServiceWorkerGlobalScopeEventMap['activate']) => void;
onfetch: (ev: ServiceWorkerGlobalScopeEventMap['fetch']) => void;
onpush: (ev: ServiceWorkerGlobalScopeEventMap['push']) => void;
onnotificationclick: (ev: ServiceWorkerGlobalScopeEventMap['notificationclick']) => void;
onnotificationclose: (ev: ServiceWorkerGlobalScopeEventMap['notificationclose']) => void;
onmessage: (ev: ServiceWorkerGlobalScopeEventMap['message']) => void;
};
};
import { createEmptyNotification, createNotification } from '@/scripts/create-notification'; import { createEmptyNotification, createNotification } from '@/scripts/create-notification';
import { swLang } from '@/scripts/lang'; import { swLang } from '@/scripts/lang';
@ -10,14 +20,15 @@ import { pushNotificationDataMap } from '@/types';
import * as swos from '@/scripts/operations'; import * as swos from '@/scripts/operations';
import { acct as getAcct } from '@/filters/user'; import { acct as getAcct } from '@/filters/user';
self.lib = {} as any;
//#region Lifecycle: Install //#region Lifecycle: Install
self.addEventListener('install', ev => { self.lib.oninstall = (ev: ServiceWorkerGlobalScopeEventMap['install']) => {
ev.waitUntil(self.skipWaiting()); ev.waitUntil(self.skipWaiting());
}); }
//#endregion
//#region Lifecycle: Activate //#region Lifecycle: Activate
self.addEventListener('activate', ev => { self.lib.onactivate = (ev: ServiceWorkerGlobalScopeEventMap['activate']) => {
ev.waitUntil( ev.waitUntil(
caches.keys() caches.keys()
.then(cacheNames => Promise.all( .then(cacheNames => Promise.all(
@ -27,20 +38,20 @@ self.addEventListener('activate', ev => {
)) ))
.then(() => self.clients.claim()) .then(() => self.clients.claim())
); );
}); }
//#endregion //#endregion
//#region When: Fetching //#region When: Fetching
self.addEventListener('fetch', ev => { self.lib.onfetch = (ev: ServiceWorkerGlobalScopeEventMap['fetch']) => {
ev.respondWith( ev.respondWith(
fetch(ev.request) fetch(ev.request)
.catch(() => new Response(`Offline. Service Worker @${_VERSION_}`, { status: 200 })) .catch(() => new Response(`Offline. Service Worker @${_VERSION_}`, { status: 200 }))
); );
}); }
//#endregion //#endregion
//#region When: Caught Notification //#region When: Caught Notification
self.addEventListener('push', ev => { self.lib.onpush = (ev: ServiceWorkerGlobalScopeEventMap['push']) => {
// クライアント取得 // クライアント取得
ev.waitUntil(self.clients.matchAll({ ev.waitUntil(self.clients.matchAll({
includeUncontrolled: true, includeUncontrolled: true,
@ -89,13 +100,12 @@ self.addEventListener('push', ev => {
createEmptyNotification(); createEmptyNotification();
})); }));
}); }
//#endregion //#endregion
//#region Notification //#region Notification
self.addEventListener('notificationclick', <K extends keyof pushNotificationDataMap>(ev: NotificationEvent) => { self.lib.onnotificationclick = <K extends keyof pushNotificationDataMap>(ev: ServiceWorkerGlobalScopeEventMap['notificationclick']) => {
ev.waitUntil((async () => { ev.waitUntil((async () => {
if (_DEV_) { if (_DEV_) {
console.log('notificationclick', ev.action, ev.notification.data); console.log('notificationclick', ev.action, ev.notification.data);
} }
@ -179,19 +189,20 @@ self.addEventListener('notificationclick', <K extends keyof pushNotificationData
notification.close(); notification.close();
})()); })());
}); }
self.addEventListener('notificationclose', <K extends keyof pushNotificationDataMap>(ev: NotificationEvent) => { self.lib.onnotificationclose = <K extends keyof pushNotificationDataMap>(ev: ServiceWorkerGlobalScopeEventMap['notificationclose']) => {
const data: pushNotificationDataMap[K] = ev.notification.data; const data: pushNotificationDataMap[K] = ev.notification.data;
if (data.type === 'notification') { if (data.type === 'notification') {
swNotificationRead.then(that => that.read(data)); swNotificationRead.then(that => that.read(data));
} }
}); }
//#endregion //#endregion
//#region When: Caught a message from the client //#region When: Caught a message from the client
self.addEventListener('message', async ev => { self.lib.onmessage = (ev: ServiceWorkerGlobalScopeEventMap['message']) => {
ev.waitUntil((async () => {
switch (ev.data) { switch (ev.data) {
case 'clear': case 'clear':
// Cache Storage全削除 // Cache Storage全削除
@ -212,5 +223,6 @@ self.addEventListener('message', async ev => {
} }
} }
} }
}); })());
}
//#endregion //#endregion

15
packages/sw/src/sw.js Normal file
View File

@ -0,0 +1,15 @@
self.importScripts('/sw-lib.VERSION.js');
self.addEventListener('install', self.lib.oninstall);
self.addEventListener('activate', self.lib.onactivate);
self.addEventListener('fetch', self.lib.onfetch);
self.addEventListener('push', self.lib.onpush);
self.addEventListener('notificationclick', self.lib.onnotificationclick);
self.addEventListener('notificationclose', self.lib.onnotificationclose);
self.addEventListener('message', self.lib.onmessage);

View File

@ -23,7 +23,7 @@ const meta = require('../../package.json');
module.exports = { module.exports = {
target: 'webworker', target: 'webworker',
entry: { entry: {
sw: './src/sw.ts' ['sw-lib']: './src/lib.ts'
}, },
module: { module: {
rules: [{ rules: [{
@ -35,7 +35,6 @@ module.exports = {
happyPackMode: true, happyPackMode: true,
transpileOnly: true, transpileOnly: true,
configFile: __dirname + '/tsconfig.json', configFile: __dirname + '/tsconfig.json',
appendTsSuffixTo: [/\.vue$/]
} }
}] }]
}] }]
@ -56,7 +55,7 @@ module.exports = {
], ],
output: { output: {
path: __dirname + '/../../built/_sw_dist_', path: __dirname + '/../../built/_sw_dist_',
filename: `[name].${meta.version}.js`, filename: `[name].js`,
publicPath: `/`, publicPath: `/`,
pathinfo: false, pathinfo: false,
}, },
@ -71,9 +70,6 @@ module.exports = {
resolveLoader: { resolveLoader: {
modules: ['node_modules'] modules: ['node_modules']
}, },
experiments: {
topLevelAwait: true
},
devtool: false, //'source-map', devtool: false, //'source-map',
mode: isProduction ? 'production' : 'development' mode: isProduction ? 'production' : 'development'
}; };