dev-tools / index.html
soiz1's picture
Update index.html
fb0ef54 verified
raw
history blame
4.01 kB
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>1ファイル完結 Service Worker + iframe + Blob</title>
</head>
<body>
<h1>Service Worker Blob + iframe で1ファイル完結</h1>
<div id="log">Service Worker 状態ログ</div>
<!-- 1. Service Worker スクリプトをscriptタグに埋める -->
<script type="text/javascript" id="sw-script">
self.addEventListener('fetch', event => {
const { request } = event;
event.respondWith(
fetch(request).then(response => {
const resClone = response.clone();
resClone.text().then(body => {
self.clients.matchAll().then(clients => {
clients.forEach(client => {
client.postMessage({
type: 'fetch-log',
url: request.url,
status: response.status,
body: body.slice(0, 100)
});
});
});
});
return response;
}).catch(error => {
self.clients.matchAll().then(clients => {
clients.forEach(client => {
client.postMessage({
type: 'fetch-error',
url: request.url,
error: error.toString()
});
});
});
throw error;
})
);
});
</script>
<script>
(async () => {
const log = document.getElementById('log');
// 2. sw-scriptタグからService Workerコードを取得
const swScript = document.getElementById('sw-script').textContent.trim();
// 3. iframe用のHTMLをBlob化する
const iframeHtml = `
<!DOCTYPE html>
<html lang="ja">
<head><meta charset="UTF-8"><title>SW iframe</title></head>
<body>
<script>
// Service Worker スクリプトをevalで実行して登録
const swCode = \`${swScript.replace(/`/g, '\\`')}\`;
// BlobにしてURLを作成
const blob = new Blob([swCode], {type: 'application/javascript'});
const swBlobUrl = URL.createObjectURL(blob);
navigator.serviceWorker.register(swBlobUrl).then(reg => {
parent.postMessage({type: 'sw-registered'}, '*');
}).catch(err => {
parent.postMessage({type: 'sw-error', error: err.toString()}, '*');
});
// Service Worker からのメッセージを親に転送
navigator.serviceWorker.addEventListener('message', e => {
parent.postMessage({type: 'sw-message', data: e.data}, '*');
});
<\/script>
</body>
</html>`;
const blob = new Blob([iframeHtml], { type: 'text/html' });
const iframeUrl = URL.createObjectURL(blob);
// 4. iframeを作成して読み込む
const iframe = document.createElement('iframe');
iframe.src = iframeUrl;
iframe.style.width = '100%';
iframe.style.height = '200px';
document.body.appendChild(iframe);
// 5. iframeからのメッセージを受け取り、ログ表示
window.addEventListener('message', (event) => {
if (!event.data) return;
const { type, error, data } = event.data;
if (type === 'sw-registered') {
log.textContent = '✅ Service Worker 登録成功!通信を監視中...';
} else if (type === 'sw-error') {
log.textContent = '❌ Service Worker 登録失敗: ' + error;
} else if (type === 'sw-message') {
const { url, status, body, error: fetchError } = data;
const div = document.createElement('div');
if (data.type === 'fetch-log') {
div.innerHTML = `✅ ${url} - ${status}<pre>${body}</pre>`;
div.style.color = 'green';
} else if (data.type === 'fetch-error') {
div.innerHTML = `❌ ${url} - エラー: ${fetchError}`;
div.style.color = 'red';
}
document.body.appendChild(div);
}
});
// 6. iframe内で動くfetchテスト(親で発火してもService Workerが拾う)
fetch('https://jsonplaceholder.typicode.com/posts/1');
fetch('https://httpstat.us/404'); // エラーの例
})();
</script>
</body>
</html>