|
<!DOCTYPE html> |
|
<html lang="ja"> |
|
<head> |
|
<meta charset="UTF-8" /> |
|
<title>iframe + BlobでService Worker登録</title> |
|
</head> |
|
<body> |
|
<h1>通信ログ(親ページ)</h1> |
|
<div id="log"></div> |
|
|
|
<script> |
|
// iframe内で動くHTML(Service Worker登録用) |
|
const iframeHtml = ` |
|
<!DOCTYPE html> |
|
<html lang="ja"> |
|
<head><meta charset="UTF-8"></head> |
|
<body> |
|
<script> |
|
|
|
const swCode = \` |
|
self.addEventListener('fetch', event => { |
|
const { request } = event; |
|
event.respondWith( |
|
fetch(request).then(response => { |
|
// クライアントにログを送信 |
|
self.clients.matchAll().then(clients => { |
|
clients.forEach(client => { |
|
client.postMessage({ |
|
type: 'log', |
|
url: request.url, |
|
status: response.status, |
|
method: request.method |
|
}); |
|
}); |
|
}); |
|
return response; |
|
}).catch(error => { |
|
self.clients.matchAll().then(clients => { |
|
clients.forEach(client => { |
|
client.postMessage({ |
|
type: 'error', |
|
url: request.url, |
|
message: error.message |
|
}); |
|
}); |
|
}); |
|
throw error; |
|
}) |
|
); |
|
}); |
|
\`; |
|
|
|
// BlobでSWスクリプト作成 |
|
const blob = new Blob([swCode], {type: 'application/javascript'}); |
|
const swUrl = URL.createObjectURL(blob); |
|
|
|
if ('serviceWorker' in navigator) { |
|
navigator.serviceWorker.register(swUrl).then(() => { |
|
parent.postMessage({type: 'sw-registered'}, '*'); |
|
}).catch(e => { |
|
parent.postMessage({type: 'sw-error', message: e.message}, '*'); |
|
}); |
|
|
|
// SWからのメッセージを親iframeへ中継 |
|
navigator.serviceWorker.addEventListener('message', event => { |
|
parent.postMessage({type: 'sw-message', data: event.data}, '*'); |
|
}); |
|
} |
|
<\/script> |
|
</body> |
|
</html> |
|
`; |
|
|
|
|
|
const iframeBlob = new Blob([iframeHtml], {type: 'text/html'}); |
|
const iframeUrl = URL.createObjectURL(iframeBlob); |
|
|
|
|
|
const iframe = document.createElement('iframe'); |
|
iframe.src = iframeUrl; |
|
iframe.style.width = '100%'; |
|
iframe.style.height = '200px'; |
|
document.body.appendChild(iframe); |
|
|
|
|
|
const logDiv = document.getElementById('log'); |
|
|
|
|
|
window.addEventListener('message', e => { |
|
if (!e.data) return; |
|
|
|
if (e.data.type === 'sw-registered') { |
|
logDiv.textContent += '✅ Service Worker登録完了\n'; |
|
} else if (e.data.type === 'sw-error') { |
|
logDiv.textContent += '❌ Service Worker登録エラー: ' + e.data.message + '\n'; |
|
} else if (e.data.type === 'sw-message') { |
|
const d = e.data.data; |
|
if (d.type === 'log') { |
|
logDiv.textContent += `🔵 [${d.method}] ${d.url} → ${d.status}\n`; |
|
} else if (d.type === 'error') { |
|
logDiv.textContent += `🔴 エラー: ${d.message} (${d.url})\n`; |
|
} |
|
} |
|
}); |
|
|
|
|
|
fetch('https://jsonplaceholder.typicode.com/posts/1'); |
|
fetch('https://httpstat.us/404'); |
|
</script> |
|
</body> |
|
</html> |
|
|