From 47d77d14fd918df5d838416e6473b0a087d47825 Mon Sep 17 00:00:00 2001
From: tamaina <tamaina@hotmail.co.jp>
Date: Tue, 30 Nov 2021 03:12:32 +0900
Subject: [PATCH] =?UTF-8?q?Failed=20to=20load=20the=20script=20unexpectedl?=
 =?UTF-8?q?y=E5=9B=9E=E9=81=BF=20sw.js=E3=81=A8lib.ts=E3=82=92=E5=88=86?=
 =?UTF-8?q?=E9=9B=A2=E3=81=97=E3=81=A6=E3=81=BF=E3=81=9F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 gulpfile.js                                  |  8 +++-
 packages/backend/src/server/web/index.ts     |  7 ++-
 packages/client/src/scripts/initialize-sw.ts |  2 +-
 packages/sw/src/{sw.ts => lib.ts}            | 50 ++++++++++++--------
 packages/sw/src/sw.js                        | 15 ++++++
 packages/sw/webpack.config.js                |  8 +---
 6 files changed, 62 insertions(+), 28 deletions(-)
 rename packages/sw/src/{sw.ts => lib.ts} (80%)
 create mode 100644 packages/sw/src/sw.js

diff --git a/gulpfile.js b/gulpfile.js
index 3bc0b23bee..f12e2ca255 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -49,8 +49,14 @@ gulp.task('build:backend:style', () => {
 		.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(
-	'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'));
diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts
index 43b3d29452..c9d0bac630 100644
--- a/packages/backend/src/server/web/index.ts
+++ b/packages/backend/src/server/web/index.ts
@@ -100,7 +100,12 @@ router.get('/twemoji/(.*)', async ctx => {
 
 // ServiceWorker
 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
 	});
 });
diff --git a/packages/client/src/scripts/initialize-sw.ts b/packages/client/src/scripts/initialize-sw.ts
index 13c0c4565b..b7057f84b3 100644
--- a/packages/client/src/scripts/initialize-sw.ts
+++ b/packages/client/src/scripts/initialize-sw.ts
@@ -8,7 +8,7 @@ export async function initializeSw() {
 		('serviceWorker' in navigator) &&
 		('PushManager' in window) &&
 		$i && $i.token) {
-		navigator.serviceWorker.register(`/sw.js`, { scope: '/', type: 'module' });
+		navigator.serviceWorker.register(`/sw.js`, { scope: '/', type: 'classic' });
 
 		navigator.serviceWorker.ready.then(registration => {
 			registration.active?.postMessage({
diff --git a/packages/sw/src/sw.ts b/packages/sw/src/lib.ts
similarity index 80%
rename from packages/sw/src/sw.ts
rename to packages/sw/src/lib.ts
index 60d916d04f..e2534613de 100644
--- a/packages/sw/src/sw.ts
+++ b/packages/sw/src/lib.ts
@@ -1,7 +1,17 @@
 /**
  * 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 { swLang } from '@/scripts/lang';
@@ -10,14 +20,15 @@ import { pushNotificationDataMap } from '@/types';
 import * as swos from '@/scripts/operations';
 import { acct as getAcct } from '@/filters/user';
 
+self.lib = {} as any;
+
 //#region Lifecycle: Install
-self.addEventListener('install', ev => {
+self.lib.oninstall = (ev: ServiceWorkerGlobalScopeEventMap['install']) => {
 	ev.waitUntil(self.skipWaiting());
-});
-//#endregion
+}
 
 //#region Lifecycle: Activate
-self.addEventListener('activate', ev => {
+self.lib.onactivate = (ev: ServiceWorkerGlobalScopeEventMap['activate']) => {
 	ev.waitUntil(
 		caches.keys()
 			.then(cacheNames => Promise.all(
@@ -27,20 +38,20 @@ self.addEventListener('activate', ev => {
 			))
 			.then(() => self.clients.claim())
 	);
-});
+}
 //#endregion
 
 //#region When: Fetching
-self.addEventListener('fetch', ev => {
+self.lib.onfetch = (ev: ServiceWorkerGlobalScopeEventMap['fetch']) => {
 	ev.respondWith(
 		fetch(ev.request)
 		.catch(() => new Response(`Offline. Service Worker @${_VERSION_}`, { status: 200 }))
 	);
-});
+}
 //#endregion
 
 //#region When: Caught Notification
-self.addEventListener('push', ev => {
+self.lib.onpush = (ev: ServiceWorkerGlobalScopeEventMap['push']) => {
 	// クライアント取得
 	ev.waitUntil(self.clients.matchAll({
 		includeUncontrolled: true,
@@ -89,13 +100,12 @@ self.addEventListener('push', ev => {
 
 		createEmptyNotification();
 	}));
-});
+}
 //#endregion
 
 //#region Notification
-self.addEventListener('notificationclick', <K extends keyof pushNotificationDataMap>(ev: NotificationEvent) => {
-	ev.waitUntil((async () => {
-
+self.lib.onnotificationclick = <K extends keyof pushNotificationDataMap>(ev: ServiceWorkerGlobalScopeEventMap['notificationclick']) => {
+ev.waitUntil((async () => {
 	if (_DEV_) {
 		console.log('notificationclick', ev.action, ev.notification.data);
 	}
@@ -178,20 +188,21 @@ self.addEventListener('notificationclick', <K extends keyof pushNotificationData
 
 	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;
 
 	if (data.type === 'notification') {
 		swNotificationRead.then(that => that.read(data));
 	}
-});
+}
 //#endregion
 
 //#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) {
 		case 'clear':
 			// Cache Storage全削除
@@ -212,5 +223,6 @@ self.addEventListener('message', async ev => {
 			}
 		}
 	}
-});
+})());
+}
 //#endregion
diff --git a/packages/sw/src/sw.js b/packages/sw/src/sw.js
new file mode 100644
index 0000000000..ac9866337a
--- /dev/null
+++ b/packages/sw/src/sw.js
@@ -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);
diff --git a/packages/sw/webpack.config.js b/packages/sw/webpack.config.js
index 99f3bc6f89..7f9f0ebb20 100644
--- a/packages/sw/webpack.config.js
+++ b/packages/sw/webpack.config.js
@@ -23,7 +23,7 @@ const meta = require('../../package.json');
 module.exports = {
 	target: 'webworker',
 	entry: {
-		sw: './src/sw.ts'
+		['sw-lib']: './src/lib.ts'
 	},
 	module: {
 		rules: [{
@@ -35,7 +35,6 @@ module.exports = {
 					happyPackMode: true,
 					transpileOnly: true,
 					configFile: __dirname + '/tsconfig.json',
-					appendTsSuffixTo: [/\.vue$/]
 				}
 			}]
 		}]
@@ -56,7 +55,7 @@ module.exports = {
 	],
 	output: {
 		path: __dirname + '/../../built/_sw_dist_',
-		filename: `[name].${meta.version}.js`,
+		filename: `[name].js`,
 		publicPath: `/`,
 		pathinfo: false,
 	},
@@ -71,9 +70,6 @@ module.exports = {
 	resolveLoader: {
 		modules: ['node_modules']
 	},
-	experiments: {
-		topLevelAwait: true
-	},
 	devtool: false, //'source-map',
 	mode: isProduction ? 'production' : 'development'
 };