soiz1 commited on
Commit
fb0ef54
·
verified ·
1 Parent(s): 266d361

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +96 -85
index.html CHANGED
@@ -1,111 +1,122 @@
1
  <!DOCTYPE html>
2
  <html lang="ja">
3
  <head>
4
- <meta charset="UTF-8" />
5
- <title>iframe + BlobでService Worker登録</title>
6
  </head>
7
  <body>
8
- <h1>通信ログ(親ページ)</h1>
9
- <div id="log"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  <script>
12
- // iframe内で動くHTML(Service Worker登録用)
13
- const iframeHtml = `
 
 
 
 
 
 
14
  <!DOCTYPE html>
15
  <html lang="ja">
16
- <head><meta charset="UTF-8"></head>
17
  <body>
18
  <script>
19
- // Service Workerのコード(文字列)
20
- const swCode = \`
21
- self.addEventListener('fetch', event => {
22
- const { request } = event;
23
- event.respondWith(
24
- fetch(request).then(response => {
25
- // クライアントにログを送信
26
- self.clients.matchAll().then(clients => {
27
- clients.forEach(client => {
28
- client.postMessage({
29
- type: 'log',
30
- url: request.url,
31
- status: response.status,
32
- method: request.method
33
- });
34
- });
35
- });
36
- return response;
37
- }).catch(error => {
38
- self.clients.matchAll().then(clients => {
39
- clients.forEach(client => {
40
- client.postMessage({
41
- type: 'error',
42
- url: request.url,
43
- message: error.message
44
- });
45
- });
46
- });
47
- throw error;
48
- })
49
- );
50
- });
51
- \`;
52
 
53
- // BlobでSWスクリプト作成
54
  const blob = new Blob([swCode], {type: 'application/javascript'});
55
- const swUrl = URL.createObjectURL(blob);
56
 
57
- if ('serviceWorker' in navigator) {
58
- navigator.serviceWorker.register(swUrl).then(() => {
59
- parent.postMessage({type: 'sw-registered'}, '*');
60
- }).catch(e => {
61
- parent.postMessage({type: 'sw-error', message: e.message}, '*');
62
- });
63
 
64
- // SWからのメッセージを親iframeへ中継
65
- navigator.serviceWorker.addEventListener('message', event => {
66
- parent.postMessage({type: 'sw-message', data: event.data}, '*');
67
- });
68
- }
69
  <\/script>
70
  </body>
71
- </html>
72
- `;
73
 
74
- // iframe用Blob URL作成
75
- const iframeBlob = new Blob([iframeHtml], {type: 'text/html'});
76
- const iframeUrl = URL.createObjectURL(iframeBlob);
77
 
78
- // iframe作成してDOMに追加
79
- const iframe = document.createElement('iframe');
80
- iframe.src = iframeUrl;
81
- iframe.style.width = '100%';
82
- iframe.style.height = '200px';
83
- document.body.appendChild(iframe);
84
 
85
- // ログ表示領域
86
- const logDiv = document.getElementById('log');
 
 
87
 
88
- // iframeからのpostMessage受信
89
- window.addEventListener('message', e => {
90
- if (!e.data) return;
91
-
92
- if (e.data.type === 'sw-registered') {
93
- logDiv.textContent += '✅ Service Worker登録完了\n';
94
- } else if (e.data.type === 'sw-error') {
95
- logDiv.textContent += '❌ Service Worker登録エラー: ' + e.data.message + '\n';
96
- } else if (e.data.type === 'sw-message') {
97
- const d = e.data.data;
98
- if (d.type === 'log') {
99
- logDiv.textContent += `🔵 [${d.method}] ${d.url} ${d.status}\n`;
100
- } else if (d.type === 'error') {
101
- logDiv.textContent += `🔴 エラー: ${d.message} (${d.url})\n`;
 
102
  }
103
- }
104
- });
 
 
 
105
 
106
- // テストfetch(親ページから)
107
- fetch('https://jsonplaceholder.typicode.com/posts/1');
108
- fetch('https://httpstat.us/404');
109
  </script>
110
  </body>
111
  </html>
 
1
  <!DOCTYPE html>
2
  <html lang="ja">
3
  <head>
4
+ <meta charset="UTF-8" />
5
+ <title>1ファイル完結 Service Worker + iframe + Blob</title>
6
  </head>
7
  <body>
8
+ <h1>Service Worker Blob + iframe で1ファイル完結</h1>
9
+ <div id="log">Service Worker 状態ログ</div>
10
+
11
+ <!-- 1. Service Worker スクリプトをscriptタグに埋める -->
12
+ <script type="text/javascript" id="sw-script">
13
+ self.addEventListener('fetch', event => {
14
+ const { request } = event;
15
+ event.respondWith(
16
+ fetch(request).then(response => {
17
+ const resClone = response.clone();
18
+ resClone.text().then(body => {
19
+ self.clients.matchAll().then(clients => {
20
+ clients.forEach(client => {
21
+ client.postMessage({
22
+ type: 'fetch-log',
23
+ url: request.url,
24
+ status: response.status,
25
+ body: body.slice(0, 100)
26
+ });
27
+ });
28
+ });
29
+ });
30
+ return response;
31
+ }).catch(error => {
32
+ self.clients.matchAll().then(clients => {
33
+ clients.forEach(client => {
34
+ client.postMessage({
35
+ type: 'fetch-error',
36
+ url: request.url,
37
+ error: error.toString()
38
+ });
39
+ });
40
+ });
41
+ throw error;
42
+ })
43
+ );
44
+ });
45
+ </script>
46
 
47
  <script>
48
+ (async () => {
49
+ const log = document.getElementById('log');
50
+
51
+ // 2. sw-scriptタグからService Workerコードを取得
52
+ const swScript = document.getElementById('sw-script').textContent.trim();
53
+
54
+ // 3. iframe用のHTMLをBlob化する
55
+ const iframeHtml = `
56
  <!DOCTYPE html>
57
  <html lang="ja">
58
+ <head><meta charset="UTF-8"><title>SW iframe</title></head>
59
  <body>
60
  <script>
61
+ // Service Worker スクリプトをevalで実行して登録
62
+ const swCode = \`${swScript.replace(/`/g, '\\`')}\`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
+ // BlobにしてURLを作成
65
  const blob = new Blob([swCode], {type: 'application/javascript'});
66
+ const swBlobUrl = URL.createObjectURL(blob);
67
 
68
+ navigator.serviceWorker.register(swBlobUrl).then(reg => {
69
+ parent.postMessage({type: 'sw-registered'}, '*');
70
+ }).catch(err => {
71
+ parent.postMessage({type: 'sw-error', error: err.toString()}, '*');
72
+ });
 
73
 
74
+ // Service Worker からのメッセージを親に転送
75
+ navigator.serviceWorker.addEventListener('message', e => {
76
+ parent.postMessage({type: 'sw-message', data: e.data}, '*');
77
+ });
 
78
  <\/script>
79
  </body>
80
+ </html>`;
 
81
 
82
+ const blob = new Blob([iframeHtml], { type: 'text/html' });
83
+ const iframeUrl = URL.createObjectURL(blob);
 
84
 
85
+ // 4. iframeを作成して読み込む
86
+ const iframe = document.createElement('iframe');
87
+ iframe.src = iframeUrl;
88
+ iframe.style.width = '100%';
89
+ iframe.style.height = '200px';
90
+ document.body.appendChild(iframe);
91
 
92
+ // 5. iframeからのメッセージを受け取り、ログ表示
93
+ window.addEventListener('message', (event) => {
94
+ if (!event.data) return;
95
+ const { type, error, data } = event.data;
96
 
97
+ if (type === 'sw-registered') {
98
+ log.textContent = ' Service Worker 登録成功!通信を監視中...';
99
+ } else if (type === 'sw-error') {
100
+ log.textContent = '❌ Service Worker 登録失敗: ' + error;
101
+ } else if (type === 'sw-message') {
102
+ const { url, status, body, error: fetchError } = data;
103
+ const div = document.createElement('div');
104
+ if (data.type === 'fetch-log') {
105
+ div.innerHTML = `✅ ${url} - ${status}<pre>${body}</pre>`;
106
+ div.style.color = 'green';
107
+ } else if (data.type === 'fetch-error') {
108
+ div.innerHTML = `❌ ${url} - エラー: ${fetchError}`;
109
+ div.style.color = 'red';
110
+ }
111
+ document.body.appendChild(div);
112
  }
113
+ });
114
+
115
+ // 6. iframe内で動くfetchテスト(親で発火してもService Workerが拾う)
116
+ fetch('https://jsonplaceholder.typicode.com/posts/1');
117
+ fetch('https://httpstat.us/404'); // エラーの例
118
 
119
+ })();
 
 
120
  </script>
121
  </body>
122
  </html>