Web API
第1部:Web APIの基礎
1. Web APIとは
概要と重要性
Web APIは、Webアプリケーションやサイトを開発する際に利用できるインターフェースとオブジェクトの集合です。これらのAPIは、ブラウザに組み込まれた機能へのアクセスを提供し、開発者がリッチなWebアプリケーションを構築することを可能にします。
- Web APIの重要性は以下の点にあります:
- クロスプラットフォーム開発の実現
- 標準化されたインターフェースの提供
- モダンなWebアプリケーション開発の基盤
- デバイス機能へのアクセス
ブラウザとWeb APIの関係
ブラウザはWeb APIの実行環境として機能します。各ブラウザベンダーは、W3CやWHATWGなどの標準化団体が定めた仕様に基づいてAPIを実装します。
- 主要なブラウザとWeb APIの関係:
- Chrome:Blinkエンジンを使用
- Firefox:Geckoエンジンを使用
- Safari:WebKitエンジンを使用
- Edge:Chromiumベース(Blinkエンジン)
JavaScriptとの連携
Web APIは主にJavaScriptを通じて利用されます。以下は基本的な使用パターンです:
// DOMの操作例 document.querySelector('.myClass').addEventListener('click', () => { console.log('クリックされました'); }); // Fetch APIの使用例 fetch('https://api.example.com/data') .then(response => response.json()) .then(data => console.log(data)); // Web Storage APIの使用例 localStorage.setItem('user', 'John Doe'); const user = localStorage.getItem('user');
2. Web APIの基本概念
イベント処理
イベント駆動プログラミングは、Web APIの重要な概念です。
- イベントの主な特徴:
- イベントの伝播(キャプチャリングとバブリング)
- イベントリスナーの登録と削除
- イベントオブジェクトの属性と方法
- 例:
element.addEventListener('click', (event) => { event.preventDefault(); // イベント処理 }, false);
非同期処理
多くのWeb APIは非同期処理を採用しています。
- 非同期処理の主なパターン:
- Promise
- async/await
- コールバック(レガシーなパターン)
- 例:
async function fetchData() { try { const response = await fetch('https://api.example.com/data'); const data = await response.json(); return data; } catch (error) { console.error('エラーが発生しました:', error); } }
セキュリティモデル
Web APIのセキュリティは、同一オリジンポリシー(Same-Origin Policy)を基本としています。
- 主なセキュリティ考慮事項:
- オリジン間リソース共有(CORS)
- コンテンツセキュリティポリシー(CSP)
- 安全なコンテキスト(HTTPS)要件
クロスオリジンの制約
クロスオリジンリソース共有(CORS)は、異なるオリジン間でのリソースアクセスを制御します。
- 主な考慮事項:
- プリフライトリクエスト
- 認証情報の取り扱い
- ヘッダーの設定
- 例:
// CORSを考慮したフェッチリクエスト fetch('https://api.example.com/data', { credentials: 'include', headers: { 'Content-Type': 'application/json' } });
第2部:主要なWeb API
3. DOM操作の基本
Document Object Model
DOMは、HTMLやXMLドキュメントをプログラムから操作するためのインターフェースを提供します。
- 主要な概念:
- ノードとエレメント
- DOMツリーの構造
- セレクタとクエリ
- 基本的なDOM操作:
// 要素の取得 const element = document.querySelector('.myClass'); const elements = document.querySelectorAll('.myClass'); // 要素の作成と追加 const newDiv = document.createElement('div'); newDiv.textContent = 'New Element'; document.body.appendChild(newDiv); // 要素の変更 element.classList.add('newClass'); element.style.backgroundColor = 'blue';
イベントハンドリング
DOM要素のイベント処理は、インタラクティブなWebアプリケーションの基礎となります。
- 一般的なイベントタイプ:
- マウスイベント(click, mouseover, mouseout)
- キーボードイベント(keydown, keyup, keypress)
- フォームイベント(submit, change, input)
- ドキュメントイベント(DOMContentLoaded, load)
- イベント処理の例:
// イベントリスナーの追加 element.addEventListener('click', handleClick); // イベントデリゲーション document.body.addEventListener('click', (event) => { if (event.target.matches('.button')) { handleButtonClick(event); } }); // カスタムイベント const customEvent = new CustomEvent('myEvent', { detail: { message: 'Hello!' } }); element.dispatchEvent(customEvent);
4. ネットワーク通信
Fetch API
Fetch APIは、ネットワークリソースの取得のための現代的なインターフェースを提供します。
- 主な特徴:
- Promiseベース
- JSONの自動解析
- ストリーミングレスポンス
- リクエストとレスポンスのカスタマイズ
- 基本的な使用例:
// GETリクエスト fetch('https://api.example.com/data') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); // POSTリクエスト fetch('https://api.example.com/create', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: '新規投稿', content: '投稿内容' }) }); // ファイルのアップロード const formData = new FormData(); formData.append('file', fileInput.files[0]); fetch('https://api.example.com/upload', { method: 'POST', body: formData });
WebSocket API
WebSocketは、クライアントとサーバー間の双方向通信を実現します。
- 主な用途:
- リアルタイムデータ更新
- チャットアプリケーション
- ライブ通知
- 実装例:
const ws = new WebSocket('wss://websocket.example.com'); ws.onopen = () => { console.log('接続が確立されました'); ws.send('Hello Server!'); }; ws.onmessage = (event) => { console.log('メッセージを受信:', event.data); }; ws.onclose = () => { console.log('接続が閉じられました'); }; ws.onerror = (error) => { console.error('WebSocketエラー:', error); };
5. ストレージとデータ
Web Storage API
Web Storageは、ブラウザにデータを保存するためのシンプルな機能を提供します。
- localStorage と sessionStorage の違い:
- localStorage: データは永続的に保存
- sessionStorage: ブラウザセッション中のみ保存
- 使用例:
// データの保存 localStorage.setItem('user', JSON.stringify({ id: 1, name: 'John Doe', preferences: { theme: 'dark', language: 'ja' } })); // データの取得 const user = JSON.parse(localStorage.getItem('user')); // データの削除 localStorage.removeItem('user'); // 全データの削除 localStorage.clear(); // ストレージの変更イベント window.addEventListener('storage', (event) => { console.log('変更されたキー:', event.key); console.log('古い値:', event.oldValue); console.log('新しい値:', event.newValue); });
IndexedDB
IndexedDBは、大量の構造化データを保存するための低レベルAPIを提供します。
- 主な特徴:
- インデックス付きデータベース
- トランザクションベース
- 非同期API
- 基本的な使用例:
// データベースを開く const request = indexedDB.open('MyDatabase', 1); request.onerror = (event) => { console.error('データベースエラー:', event.target.error); }; request.onupgradeneeded = (event) => { const db = event.target.result; const store = db.createObjectStore('users', { keyPath: 'id' }); store.createIndex('name', 'name', { unique: false }); }; request.onsuccess = (event) => { const db = event.target.result; // データの追加 const transaction = db.transaction(['users'], 'readwrite'); const store = transaction.objectStore('users'); store.add({ id: 1, name: 'John Doe', email: 'john@example.com' }); // データの取得 const getRequest = store.get(1); getRequest.onsuccess = () => { console.log('取得したデータ:', getRequest.result); }; };
6. マルチメディア
Web Audio API
Web Audio APIは、高度な音声処理と合成機能を提供します。
- 主な機能:
- 音声の再生と制御
- 音声効果の適用
- 音声の分析と視覚化
- 実装例:
// オーディオコンテキストの作成 const audioContext = new AudioContext(); // オシレーターの作成と再生 function playTone(frequency = 440, duration = 1) { const oscillator = audioContext.createOscillator(); const gainNode = audioContext.createGain(); oscillator.connect(gainNode); gainNode.connect(audioContext.destination); oscillator.frequency.value = frequency; oscillator.type = 'sine'; oscillator.start(); // フェードアウト gainNode.gain.exponentialRampToValueAtTime( 0.01, audioContext.currentTime + duration ); // 停止 oscillator.stop(audioContext.currentTime + duration); } // 音声ファイルの再生 async function playAudioFile(url) { const response = await fetch(url); const arrayBuffer = await response.arrayBuffer(); const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); const source = audioContext.createBufferSource(); source.buffer = audioBuffer; source.connect(audioContext.destination); source.start(); }
Media Capture and Streams
メディアキャプチャAPIは、カメラやマイクからのメディアストリームを扱います。
- 主な用途:
- ビデオ通話
- 画面録画
- メディア録音/録画
- 基本的な実装:
// カメラとマイクへのアクセス async function startCapture() { try { const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 1280, height: 720 }, audio: true }); // ビデオ要素にストリームを設定 const videoElement = document.querySelector('video'); videoElement.srcObject = stream; // 録画の開始 const mediaRecorder = new MediaRecorder(stream); const chunks = []; mediaRecorder.ondataavailable = (event) => { chunks.push(event.data); }; mediaRecorder.onstop = () => { const blob = new Blob(chunks, { type: 'video/webm' }); const url = URL.createObjectURL(blob); // ダウンロードリンクの作成 const a = document.createElement('a'); a.href = url; a.download = 'recording.webm'; a.click(); }; mediaRecorder.start(); } catch (error) { console.error('メディアの取得に失敗:', error); } }
承知いたしました。追加を推奨するAPIについて、提示されたハンドブックと同じスタイルで執筆します。
7. その他の主要なWeb API
Geolocation API
Geolocation APIは、ユーザーの位置情報へのアクセスを提供します。
- 主な機能:
- 現在地の取得
- 位置情報の監視
- 基本的な使用例:
// 現在地の取得 navigator.geolocation.getCurrentPosition( (position) => { console.log('緯度:', position.coords.latitude); console.log('経度:', position.coords.longitude); }, (error) => { console.error('位置情報の取得に失敗:', error); } ); // 位置情報の監視 const watchId = navigator.geolocation.watchPosition( (position) => { console.log('位置情報が更新されました:', position.coords); }, (error) => { console.error('位置情報の監視中にエラーが発生:', error); } ); // 位置情報の監視を停止 navigator.geolocation.clearWatch(watchId);
Canvas API
Canvas APIは、JavaScriptを使用して動的なグラフィックスやアニメーションを描画します。
- 主な機能:
- 図形、テキスト、画像の描画
- アニメーションの実装
- ピクセル操作
- 基本的な使用例:
const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); // 四角形の描画 ctx.fillStyle = 'red'; ctx.fillRect(10, 10, 100, 50); // テキストの描画 ctx.font = '20px Arial'; ctx.fillText('Hello Canvas!', 20, 80); // 画像の描画 const img = new Image(); img.onload = () => { ctx.drawImage(img, 120, 10); }; img.src = 'image.jpg';
Web Workers API
Web Workers APIは、バックグラウンドでJavaScriptを実行し、メインスレッドの負荷を軽減します。
- 主な機能:
- バックグラウンド処理
- 並列処理
- 基本的な使用例:
// Workerの作成 const worker = new Worker('worker.js'); // Workerへのメッセージ送信 worker.postMessage({ action: 'calculate', data: [1, 2, 3] }); // Workerからのメッセージ受信 worker.onmessage = (event) => { console.log('Workerからのメッセージ:', event.data); }; // Workerのエラー処理 worker.onerror = (error) => { console.error('Workerエラー:', error); }; // worker.js (Worker内で実行されるコード) self.onmessage = (event) => { const data = event.data; if (data.action === 'calculate') { const result = data.data.reduce((sum, num) => sum + num, 0); self.postMessage(result); } };
Intersection Observer API
Intersection Observer APIは、要素の表示状態を監視し、遅延読み込みや無限スクロールなどの実装を容易にします。
- 主な機能:
- 要素の表示状態の監視
- 遅延読み込み
- 無限スクロール
- 基本的な使用例:
const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { console.log('要素が表示されました:', entry.target); // 遅延読み込みやアニメーションなどの処理 observer.unobserve(entry.target); // 監視を停止 } }); }); // 監視対象の要素を設定 const target = document.querySelector('.observe-target'); observer.observe(target);
第3部:デバイスとハードウェア連携
7. デバイスセンサー
Geolocation API
Geolocation APIは、デバイスの位置情報へのアクセスを提供します。
- 主な機能:
- 現在位置の取得
- 位置の継続的な監視
- 位置情報の精度制御
- 実装例:
// 現在位置の1回取得 function getCurrentPosition() { if ('geolocation' in navigator) { navigator.geolocation.getCurrentPosition( position => { const { latitude, longitude, accuracy } = position.coords; console.log(`位置: ${latitude}, ${longitude}`); console.log(`精度: ${accuracy}メートル`); }, error => { console.error('位置情報の取得に失敗:', error.message); }, { enableHighAccuracy: true, timeout: 5000, maximumAge: 0 } ); } } // 位置の継続的な監視 let watchId; function startWatchingPosition() { watchId = navigator.geolocation.watchPosition( position => { updateMap(position.coords); }, error => { console.error('監視エラー:', error.message); }, { enableHighAccuracy: true, timeout: 5000 } ); } function stopWatchingPosition() { navigator.geolocation.clearWatch(watchId); }
Device Orientation
デバイスの向きや動きを検出するためのAPIです。
- 主な用途:
- モバイルゲーム
- 拡張現実(AR)アプリケーション
- デバイスの傾きに応じたUI調整
- 実装例:
// デバイスの向きの検出 window.addEventListener('deviceorientation', (event) => { // アルファ: z軸周りの回転(0-360) const rotation = event.alpha; // ベータ: x軸周りの回転(-180-180) const frontToBack = event.beta; // ガンマ: y軸周りの回転(-90-90) const leftToRight = event.gamma; // UIの更新 updateInterface(rotation, frontToBack, leftToRight); }); // デバイスの動きの検出 window.addEventListener('devicemotion', (event) => { // 加速度(重力を含む) const x = event.accelerationIncludingGravity.x; const y = event.accelerationIncludingGravity.y; const z = event.accelerationIncludingGravity.z; // 回転速度 const rotationRate = event.rotationRate; // モーションの処理 handleMotion(x, y, z, rotationRate); });
8. 入出力
File API
File APIは、ファイルの読み込みと操作のためのインターフェースを提供します。
- 主な機能:
- ファイルの選択と読み込み
- ドラッグ&ドロップ
- ファイルの情報取得
- 実装例:
// ファイル選択と読み込み const fileInput = document.querySelector('input[type="file"]'); fileInput.addEventListener('change', (event) => { const files = Array.from(event.target.files); files.forEach(file => { // ファイル情報の表示 console.log(` 名前: ${file.name} サイズ: ${file.size} bytes タイプ: ${file.type} 最終更新: ${file.lastModified} `); // ファイルの読み込み const reader = new FileReader(); reader.onload = (e) => { const content = e.target.result; // ファイル内容の処理 processFileContent(content); }; reader.onerror = (error) => { console.error('ファイル読み込みエラー:', error); }; if (file.type.startsWith('image/')) { reader.readAsDataURL(file); // 画像の場合 } else { reader.readAsText(file); // テキストの場合 } }); }); // ドラッグ&ドロップの処理 const dropZone = document.querySelector('.drop-zone'); dropZone.addEventListener('dragover', (event) => { event.preventDefault(); dropZone.classList.add('drag-over'); }); dropZone.addEventListener('dragleave', () => { dropZone.classList.remove('drag-over'); }); dropZone.addEventListener('drop', (event) => { event.preventDefault(); dropZone.classList.remove('drag-over'); const files = Array.from(event.dataTransfer.files); handleDroppedFiles(files); });
Web Bluetooth API
Web Bluetooth APIは、WebアプリケーションからのBluetooth Low Energy(BLE)デバイスへの接続を可能にします。
- 主な機能:
- デバイスの検出と接続
- サービスとキャラクタリスティクスの操作
- 通知の受信
- 実装例:
async function connectToBluetoothDevice() { try { // デバイスを選択 const device = await navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] }); // デバイスに接続 const server = await device.gatt.connect(); // サービスの取得 const service = await server.getPrimaryService('heart_rate'); // 心拍数の特性を取得 const characteristic = await service.getCharacteristic('heart_rate_measurement'); // 通知を開始 await characteristic.startNotifications(); characteristic.addEventListener('characteristicvaluechanged', (event) => { const value = event.target.value; const heartRate = value.getUint8(1); console.log('心拍数:', heartRate); }); } catch (error) { console.error('Bluetooth接続エラー:', error); } }
第4部:グラフィックスとアニメーション
9. 描画とアニメーション
Canvas API
Canvas APIは、2D描画とピクセルレベルの操作を提供します。
- 主な機能:
- 基本図形の描画
- 画像操作
- アニメーション
- パスとグラデーション
- 実装例:
const canvas = document.querySelector('canvas'); const ctx = canvas.getContext('2d'); // 基本的な描画 function drawShapes() { // 四角形 ctx.fillStyle = 'blue'; ctx.fillRect(10, 10, 100, 100); // 円 ctx.beginPath(); ctx.arc(200, 60, 50, 0, Math.PI * 2); ctx.fillStyle = 'red'; ctx.fill(); // パス ctx.beginPath(); ctx.moveTo(300, 10); ctx.lineTo(350, 110); ctx.lineTo(250, 110); ctx.closePath(); ctx.strokeStyle = 'green'; ctx.stroke(); } // アニメーション let x = 0; function animate() { // キャンバスのクリア ctx.clearRect(0, 0, canvas.width, canvas.height); // 図形の描画 ctx.fillStyle = 'purple'; ctx.fillRect(x, 50, 50, 50); // 位置の更新 x = (x + 2) % canvas.width; requestAnimationFrame(animate); } // グラデーション function createGradient() { const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0); gradient.addColorStop(0, 'red'); gradient.addColorStop(0.5, 'green'); gradient.addColorStop(1, 'blue'); ctx.fillStyle = gradient; ctx.fillRect(0, 0, canvas.width, canvas.height); }
Web Animations API
Web Animations APIは、JavaScriptによるアニメーションの制御を提供します。
- 主な特徴:
- キーフレームベースのアニメーション
- タイミング制御
- アニメーションの一時停止と再開
- 実装例:
const element = document.querySelector('.animated-element'); // 基本的なアニメーション const keyframes = [ { transform: 'translateX(0px)' }, { transform: 'translateX(300px)' } ]; const options = { duration: 1000, easing: 'ease-in-out', iterations: Infinity, direction: 'alternate' }; const animation = element.animate(keyframes, options); // アニメーションの制御 document.getElementById('pause').onclick = () => animation.pause(); document.getElementById('play').onclick = () => animation.play(); document.getElementById('reverse').onclick = () => animation.reverse(); document.getElementById('cancel').onclick = () => animation.cancel(); // アニメーションイベントの処理 animation.onfinish = () => console.log('アニメーション完了'); animation.oncancel = () => console.log('アニメーション中断'); // 複雑なアニメーション const complexKeyframes = [ { transform: 'scale(1) rotate(0deg)', opacity: 1, offset: 0 }, { transform: 'scale(1.5) rotate(45deg)', opacity: 0.5, offset: 0.5 }, { transform: 'scale(1) rotate(90deg)', opacity: 0, offset: 1 } ]; const complexAnimation = element.animate(complexKeyframes, { duration: 2000, fill: 'forwards', easing: 'cubic-bezier(0.4, 0, 0.2, 1)' });
10. 3Dグラフィックス
WebGL
WebGLは、ウェブブラウザで3Dグラフィックスを実現するためのAPIです。
- 主な機能:
- 3D描画とレンダリング
- シェーダープログラミング
- テクスチャマッピング
- 行列演算
- 実装例:
const canvas = document.querySelector('canvas'); const gl = canvas.getContext('webgl'); // シェーダーの設定 const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, ` attribute vec4 position; void main() { gl_Position = position; } `); gl.compileShader(vertexShader); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, ` void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } `); gl.compileShader(fragmentShader); // プログラムの作成 const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); gl.useProgram(program); // 頂点データの設定 const positions = new Float32Array([ 0.0, 0.5, 0.0, -0.5, -0.5, 0.0, 0.5, -0.5, 0.0 ]); const positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); // 描画 const positionLocation = gl.getAttribLocation(program, 'position'); gl.enableVertexAttribArray(positionLocation); gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0); gl.drawArrays(gl.TRIANGLES, 0, 3);
WebGPU
WebGPUは、最新の3Dグラフィックス技術を活用するための次世代APIです。
- 主な特徴:
- 低レベルGPUアクセス
- 高性能コンピューティング
- モダンなGPUアーキテクチャの活用
- 実装例:
async function initWebGPU() { if (!navigator.gpu) { throw new Error('WebGPU not supported'); } const adapter = await navigator.gpu.requestAdapter(); const device = await adapter.requestDevice(); const canvas = document.querySelector('canvas'); const context = canvas.getContext('webgpu'); const format = navigator.gpu.getPreferredCanvasFormat(); context.configure({ device: device, format: format, alphaMode: 'premultiplied', }); // シェーダーモジュールの作成 const shaderModule = device.createShaderModule({ code: ` @vertex fn vertexMain(@location(0) position: vec4f) -> @builtin(position) vec4f { return position; } @fragment fn fragmentMain() -> @location(0) vec4f { return vec4f(1.0, 0.0, 0.0, 1.0); } ` }); // レンダーパイプラインの設定 const pipeline = device.createRenderPipeline({ layout: 'auto', vertex: { module: shaderModule, entryPoint: 'vertexMain' }, fragment: { module: shaderModule, entryPoint: 'fragmentMain', targets: [{ format: format }] } }); // 描画コマンドの実行 const commandEncoder = device.createCommandEncoder(); const textureView = context.getCurrentTexture().createView(); const renderPass = commandEncoder.beginRenderPass({ colorAttachments: [{ view: textureView, clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }, loadOp: 'clear', storeOp: 'store' }] }); renderPass.setPipeline(pipeline); renderPass.draw(3, 1, 0, 0); renderPass.end(); device.queue.submit([commandEncoder.finish()]); }
第5部:パフォーマンスと最適化
11. パフォーマンス最適化
Performance API
Performance APIは、ウェブアプリケーションのパフォーマンス測定と分析を提供します。
- 主な機能:
- タイミング測定
- リソース読み込み分析
- ナビゲーション計測
- メモリ使用状況
- 実装例:
// パフォーマンスマーク performance.mark('処理開始'); // 重い処理 for(let i = 0; i < 1000000; i++) { // 処理 } performance.mark('処理終了'); performance.measure('処理時間', '処理開始', '処理終了'); // リソースタイミング const resources = performance.getEntriesByType('resource'); resources.forEach(resource => { console.log(`${resource.name}: ${resource.duration}ms`); }); // ナビゲーションタイミング const navigation = performance.getEntriesByType('navigation')[0]; console.log(`DOMContentLoaded: ${navigation.domContentLoadedEventEnd}ms`); console.log(`Load: ${navigation.loadEventEnd}ms`); // メモリ使用状況 const memory = performance.memory; console.log(`ヒープサイズ上限: ${memory.jsHeapSizeLimit}`); console.log(`使用中のヒープサイズ: ${memory.usedJSHeapSize}`); // パフォーマンスオブザーバー const observer = new PerformanceObserver((list) => { list.getEntries().forEach((entry) => { console.log(`${entry.name}: ${entry.duration}ms`); }); }); observer.observe({ entryTypes: ['measure', 'resource'] });
Web Workers
Web Workersは、バックグラウンドスレッドでJavaScriptを実行する機能を提供します。
- 主な特徴:
- マルチスレッド処理
- メインスレッドのブロック防止
- メッセージベースの通信
- 実装例:
// メインスレッド (main.js) const worker = new Worker('worker.js'); worker.postMessage({ type: '計算開始', data: [1, 2, 3, 4, 5] }); worker.onmessage = (e) => { console.log('計算結果:', e.data); }; worker.onerror = (error) => { console.error('Worker エラー:', error); }; // ワーカースレッド (worker.js) self.onmessage = (e) => { if (e.data.type === '計算開始') { const result = e.data.data.map(num => num * 2); self.postMessage(result); } }; // SharedWorkerの例 const sharedWorker = new SharedWorker('shared-worker.js'); sharedWorker.port.start(); sharedWorker.port.onmessage = (e) => { console.log('共有ワーカーからのメッセージ:', e.data); }; // WorkerモジュールのESM対応 const moduleWorker = new Worker('module-worker.js', { type: 'module' });
Service Workers
Service Workersは、オフライン機能とバックグラウンド同期を実現するAPIです。
- 主な機能:
- オフラインキャッシュ
- プッシュ通知
- バックグラウンド同期
- 実装例:
// Service Workerの登録 if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(registration => { console.log('SW登録成功:', registration.scope); }) .catch(error => { console.error('SW登録失敗:', error); }); } // Service Worker実装 (sw.js) const CACHE_NAME = 'my-site-cache-v1'; const urlsToCache = [ '/', '/styles/main.css', '/scripts/main.js' ]; self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME) .then(cache => cache.addAll(urlsToCache)) ); }); self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(response => { if (response) { return response; } return fetch(event.request); }) ); }); self.addEventListener('push', event => { const options = { body: event.data.text(), icon: '/images/icon.png', badge: '/images/badge.png' }; event.waitUntil( self.registration.showNotification('プッシュ通知', options) ); }); self.addEventListener('sync', event => { if (event.tag === 'mySync') { event.waitUntil( // バックグラウンド同期処理 fetch('/api/sync') ); } });
12. オフライン機能
Cache Storage
Cache Storage APIは、HTTPリクエストとレスポンスのキャッシュを管理するためのAPIです。
- 主な機能:
- リクエスト/レスポンスの保存
- キャッシュの更新と削除
- 複数キャッシュの管理
- 実装例:
// キャッシュの作成と追加 caches.open('my-cache').then(cache => { cache.add('/api/data'); cache.addAll([ '/images/logo.png', '/styles/main.css', '/scripts/app.js' ]); }); // キャッシュの取得と更新 caches.match('/api/data').then(response => { if (response) { return response; } return fetch('/api/data').then(response => { return caches.open('my-cache').then(cache => { cache.put('/api/data', response.clone()); return response; }); }); }); // キャッシュの削除 caches.delete('old-cache'); // 全キャッシュの管理 caches.keys().then(cacheNames => { return Promise.all( cacheNames.map(cacheName => { if (cacheName !== 'my-cache-v2') { return caches.delete(cacheName); } }) ); });
Background Sync
Background Sync APIは、ネットワーク接続が復帰したときにデータを同期する機能を提供します。
- 主な特徴:
- オフライン操作の保証
- 自動再試行
- バックグラウンド処理
- 実装例:
// 同期の登録 navigator.serviceWorker.ready.then(registration => { registration.sync.register('sync-messages').then(() => { console.log('同期タスク登録成功'); }).catch(err => { console.error('同期タスク登録失敗:', err); }); }); // Service Worker内での同期処理 self.addEventListener('sync', event => { if (event.tag === 'sync-messages') { event.waitUntil( // オフライン時のデータを取得 getOfflineData().then(data => { // サーバーへ送信 return fetch('/api/messages', { method: 'POST', body: JSON.stringify(data), headers: { 'Content-Type': 'application/json' } }); }).then(() => { // 成功時の処理 return clearOfflineData(); }) ); } }); // 定期的な同期 registration.periodicSync.register('periodic-sync', { minInterval: 24 * 60 * 60 * 1000 // 24時間 }).then(() => { console.log('定期同期登録成功'); });
Push API
Push APIは、サーバーからクライアントへのプッシュ通知を実現するAPIです。
- 主な機能:
- プッシュ通知の送受信
- サブスクリプション管理
- 暗号化通信
- 実装例:
// プッシュ通知の購読 navigator.serviceWorker.ready.then(registration => { return registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(publicVapidKey) }); }).then(subscription => { // サブスクリプション情報をサーバーに送信 return fetch('/api/subscribe', { method: 'POST', body: JSON.stringify(subscription), headers: { 'Content-Type': 'application/json' } }); }).catch(err => { console.error('プッシュ通知登録エラー:', err); }); // Service Worker内でのプッシュ通知処理 self.addEventListener('push', event => { const data = event.data.json(); const options = { body: data.body, icon: '/images/icon.png', badge: '/images/badge.png', data: { url: data.url }, actions: [ { action: 'open', title: '開く' }, { action: 'close', title: '閉じる' } ] }; event.waitUntil( self.registration.showNotification(data.title, options) ); }); // 通知クリック時の処理 self.addEventListener('notificationclick', event => { event.notification.close(); if (event.action === 'open') { event.waitUntil( clients.openWindow(event.notification.data.url) ); } });
第6部:セキュリティと認証
13. セキュリティ
Content Security Policy
Content Security Policy (CSP)は、XSSやその他のコンテンツインジェクション攻撃を防ぐセキュリティ機能です。
- 主な機能:
- リソースの読み込み制御
- インラインスクリプトの制限
- レポーティング機能
- 実装例:
// HTTPヘッダーの設定例 const securityHeaders = { 'Content-Security-Policy': "default-src 'self';" + "script-src 'self' 'nonce-randomNonce' https://trusted.com;" + "style-src 'self' https://styles.com;" + "img-src 'self' data: https:;" + "connect-src 'self' https://api.example.com;" + "report-uri /csp-report" }; // CSPレポートの処理 app.post('/csp-report', (req, res) => { const report = req.body; console.log('CSP違反:', report); // 違反をログに記録 logCSPViolation(report); res.status(204).end(); }); // メタタグでのCSP設定 document.head.innerHTML += ` <meta http-equiv="Content-Security-Policy" content="default-src 'self'"> `; // nonceの動的生成 function generateNonce() { return crypto.randomBytes(16).toString('base64'); }
Cross-Origin Resource Sharing
CORSは、異なるオリジン間でのリソース共有を制御するメカニズムです。
- 主な特徴:
- クロスオリジンリクエストの制御
- プリフライトリクエスト
- 認証情報の扱い
- 実装例:
// サーバー側のCORS設定 app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', 'https://trusted-site.com'); res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization'); res.header('Access-Control-Allow-Credentials', 'true'); if (req.method === 'OPTIONS') { return res.sendStatus(200); } next(); }); // クライアント側のCORS設定 fetch('https://api.example.com/data', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ data: 'example' }) }).then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }).catch(error => { console.error('CORS error:', error); }); // XMLHttpRequestでのCORS const xhr = new XMLHttpRequest(); xhr.open('GET', 'https://api.example.com/data', true); xhr.withCredentials = true; xhr.onload = function() { if (xhr.status === 200) { console.log(xhr.responseText); } }; xhr.send(null);
Web Crypto API
Web Crypto APIは、暗号化機能を提供する低レベルインターフェースです。
- 主な機能:
- 暗号化と復号
- ハッシュ生成
- 鍵生成と管理
- 実装例:
// ハッシュの生成 async function generateHash(message) { const msgBuffer = new TextEncoder().encode(message); const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer); const hashArray = Array.from(new Uint8Array(hashBuffer)); return hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); } // 鍵ペアの生成 async function generateKeyPair() { const keyPair = await crypto.subtle.generateKey( { name: 'RSA-OAEP', modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: 'SHA-256' }, true, ['encrypt', 'decrypt'] ); return keyPair; } // データの暗号化 async function encryptData(data, publicKey) { const encoded = new TextEncoder().encode(data); const encrypted = await crypto.subtle.encrypt( { name: 'RSA-OAEP' }, publicKey, encoded ); return encrypted; } // データの復号 async function decryptData(encrypted, privateKey) { const decrypted = await crypto.subtle.decrypt( { name: 'RSA-OAEP' }, privateKey, encrypted ); return new TextDecoder().decode(decrypted); } // AES暗号化の例 async function generateAESKey() { return await crypto.subtle.generateKey( { name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt'] ); }
14. 認証と認可
Credential Management API
Credential Management APIは、ユーザー認証情報の保存と管理を提供します。
- 主な機能:
- パスワード認証情報の管理
- フェデレーション認証
- 自動サインイン
- 実装例:
// パスワード認証情報の保存 async function storeCredential(username, password) { if (!window.PasswordCredential) { return; } const cred = new PasswordCredential({ id: username, password: password, name: 'ユーザー名', iconURL: '/images/avatar.png' }); await navigator.credentials.store(cred); } // 認証情報の取得 async function getCredential() { const cred = await navigator.credentials.get({ password: true, mediation: 'silent' }); if (cred) { await signIn(cred); } } // フェデレーション認証 const federatedCredential = new FederatedCredential({ id: user.email, provider: 'https://accounts.google.com', name: user.name, iconURL: user.profilePic }); // 認証情報の防止 navigator.credentials.preventSilentAccess(); // 自動サインインの実装 window.addEventListener('load', async () => { try { const cred = await navigator.credentials.get({ password: true, federated: { providers: ['https://accounts.google.com'] }, mediation: 'silent' }); if (cred) { await signIn(cred); } } catch (error) { console.error('Auto sign-in failed:', error); } });
Web Authentication API
Web Authentication APIは、パスワードレス認証を実現するための標準APIです。
- 主な特徴:
- 生体認証
- ハードウェアキー
- 公開鍵暗号方式
- 実装例:
// 認証情報の作成 async function registerUser() { const publicKeyCredentialCreationOptions = { challenge: new Uint8Array([/* チャレンジ */]), rp: { name: "Example Corp", id: "example.com", }, user: { id: Uint8Array.from( "UZSL85T9AFC", c => c.charCodeAt(0)), name: "test@example.com", displayName: "Test User" }, pubKeyCredParams: [{ type: "public-key", alg: -7 // "ES256" }], authenticatorSelection: { authenticatorAttachment: "platform", userVerification: "required" }, timeout: 60000 }; const credential = await navigator.credentials.create({ publicKey: publicKeyCredentialCreationOptions }); // 認証情報をサーバーに送信 await sendToServer(credential); } // 認証の実行 async function authenticateUser() { const publicKeyCredentialRequestOptions = { challenge: new Uint8Array([/* チャレンジ */]), allowCredentials: [{ type: 'public-key', id: new Uint8Array([/* 認証情報ID */]), transports: ['internal'] }], timeout: 60000, userVerification: "required" }; const assertion = await navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }); // アサーションをサーバーで検証 await verifyWithServer(assertion); } // 生体認証の可用性チェック async function checkBiometricCapability() { const available = await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(); return available; } // 条件付き認証 async function conditionalAuthentication() { try { const credential = await navigator.credentials.get({ publicKey: { challenge: new Uint8Array([/* チャレンジ */]), userVerification: "preferred", rpId: "example.com" }, mediation: "conditional" }); // 認証成功の処理 return credential; } catch (error) { console.error('認証エラー:', error); } }
第7部:実践とベストプラクティス
15. デバッグとトラブルシューティング
Developer Tools の活用
Developer Toolsは、ウェブアプリケーションのデバッグと分析を行うための統合開発環境です。
- 主な機能:
- コンソールデバッグ
- ネットワーク監視
- パフォーマンス分析
- DOM検査
- 実装例:
// コンソールデバッグ console.group('デバッグセッション'); console.log('通常のログ'); console.info('情報メッセージ'); console.warn('警告メッセージ'); console.error('エラーメッセージ'); console.groupEnd(); // パフォーマンスマーク performance.mark('処理開始'); // 処理内容 performance.mark('処理終了'); performance.measure('処理時間', '処理開始', '処理終了'); // カスタムイベントのデバッグ const debugEvents = new EventTarget(); debugEvents.addEventListener('customEvent', (e) => { console.debug('カスタムイベント発生:', e.detail); }); // 条件付きブレークポイント function processData(data) { if (data.debug) { debugger; // 条件付きブレークポイント } // データ処理 } // メモリリーク検出 let leakyArray = []; function potentialLeak() { console.memory; // メモリ使用状況の確認 leakyArray.push(new Array(10000)); }
一般的な問題と解決方法
一般的な問題と解決方法では、ウェブ開発で遭遇する代表的な問題とその対処法を説明します。
- 主な問題:
- メモリリーク
- パフォーマンスボトルネック
- クロスブラウザ互換性
- 実装例:
// メモリリークの防止 class ResourceManager { constructor() { this.resources = new WeakMap(); this.observers = new Set(); } addResource(key, value) { this.resources.set(key, value); } cleanup() { this.observers.clear(); } } // エラーハンドリング class ErrorBoundary { static catch(error) { console.error('エラー発生:', error); // エラーログの送信 this.sendErrorLog(error); } static async sendErrorLog(error) { try { await fetch('/api/error-log', { method: 'POST', body: JSON.stringify({ message: error.message, stack: error.stack, timestamp: new Date() }) }); } catch (e) { console.error('エラーログ送信失敗:', e); } } } // クロスブラウザ対応 const getBrowserInfo = () => { const ua = navigator.userAgent; const browserInfo = { isChrome: /Chrome/.test(ua), isFirefox: /Firefox/.test(ua), isSafari: /Safari/.test(ua), isIE: /MSIE|Trident/.test(ua) }; return browserInfo; };
パフォーマンス監視
パフォーマンス監視は、アプリケーションのパフォーマンスを継続的に測定し改善する機能を提供します。
- 主な機能:
- メトリクス収集
- パフォーマンス分析
- ボトルネック特定
- 実装例:
// パフォーマンスモニタリング class PerformanceMonitor { constructor() { this.metrics = {}; this.initObservers(); } initObservers() { // ページロード時間の測定 this.metrics.load = { startTime: performance.now() }; // リソースタイミング const resourceObserver = new PerformanceObserver(list => { list.getEntries().forEach(entry => { this.logResourceTiming(entry); }); }); resourceObserver.observe({ entryTypes: ['resource'] }); // レイアウトシフト監視 const layoutObserver = new PerformanceObserver(list => { list.getEntries().forEach(entry => { this.logLayoutShift(entry); }); }); layoutObserver.observe({ entryTypes: ['layout-shift'] }); } logResourceTiming(entry) { console.log(`リソース: ${entry.name}, 読み込み時間: ${entry.duration}ms`); } logLayoutShift(entry) { console.log(`レイアウトシフト: スコア ${entry.value}`); } measureUserTiming(label) { performance.mark(`${label}-start`); return { end: () => { performance.mark(`${label}-end`); performance.measure(label, `${label}-start`, `${label}-end`); } }; } getMetrics() { return { loadTime: performance.now() - this.metrics.load.startTime, resources: performance.getEntriesByType('resource'), measures: performance.getEntriesByType('measure') }; } } // 使用例 const monitor = new PerformanceMonitor(); const timing = monitor.measureUserTiming('critical-operation'); // 処理実行 timing.end();
16. プロジェクト実践
リアルワールドの実装例
リアルワールドの実装例では、実際のプロジェクトで使用される一般的なパターンと実装方法を説明します。
- 主な例:
- SPA実装
- PWA実装
- マイクロフロントエンド
- 実装例:
// SPAのルーティング実装 class Router { constructor(routes) { this.routes = routes; this.init(); } init() { window.addEventListener('popstate', this.handleRoute.bind(this)); document.addEventListener('click', e => { if (e.target.matches('a[data-route]')) { e.preventDefault(); const route = e.target.getAttribute('data-route'); this.navigate(route); } }); } handleRoute() { const path = window.location.pathname; const route = this.routes[path] || this.routes['404']; const main = document.querySelector('main'); main.innerHTML = route.template; if (route.init) route.init(); } navigate(path) { window.history.pushState({}, '', path); this.handleRoute(); } } // PWAのサービスワーカー実装 const CACHE_NAME = 'my-pwa-cache-v1'; self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME).then(cache => { return cache.addAll([ '/', '/styles/main.css', '/scripts/app.js', '/images/icon.png' ]); }) ); }); // マイクロフロントエンド統合 class MicroFrontend { constructor(name, host) { this.name = name; this.host = host; } async mount(container) { const html = await fetch(`${this.host}/index.html`).then(r => r.text()); container.innerHTML = html; this.executeScripts(container); } executeScripts(container) { const scripts = container.getElementsByTagName('script'); Array.from(scripts).forEach(script => { const newScript = document.createElement('script'); Array.from(script.attributes).forEach(attr => { newScript.setAttribute(attr.name, attr.value); }); newScript.textContent = script.textContent; script.parentNode.replaceChild(newScript, script); }); } }
ベストプラクティス
ベストプラクティスでは、効率的で保守性の高いコードを書くためのガイドラインを提供します。
- 主な内容:
- コード構造化
- エラー処理
- セキュリティ対策
- 実装例:
// モジュールパターン const UserModule = (function() { // プライベート変数 let currentUser = null; // プライベート関数 function validateUser(user) { return user.name && user.email; } return { // パブリックメソッド setUser(user) { if (!validateUser(user)) { throw new Error('Invalid user data'); } currentUser = user; }, getUser() { return {...currentUser}; } }; })(); // エラー処理 class AppError extends Error { constructor(message, code) { super(message); this.name = 'AppError'; this.code = code; } } function handleError(error) { if (error instanceof AppError) { // アプリケーション固有のエラー処理 console.error(`[${error.code}] ${error.message}`); } else { // 一般的なエラー処理 console.error('Unexpected error:', error); } } // セキュリティ対策 const SecurityUtils = { sanitizeInput(input) { return input.replace(/[<>&'"]/g, char => { const entities = { '<': '<', '>': '>', '&': '&', "'": ''', '"': '"' }; return entities[char]; }); }, validateToken(token) { // トークンの検証ロジック return /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/.test(token); } };
ブラウザ互換性への対応
ブラウザ互換性への対応では、異なるブラウザでの一貫した動作を実現するための手法を説明します。
- 主な機能:
- フィーチャーディテクション
- ポリフィル
- ベンダープレフィックス
- 実装例:
// フィーチャーディテクション const BrowserFeatures = { hasIntersectionObserver: 'IntersectionObserver' in window, hasWebP: () => { return new Promise(resolve => { const img = new Image(); img.onload = () => resolve(true); img.onerror = () => resolve(false); img.src = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA='; }); }, checkApiSupport() { return { webgl: (() => { try { return !!document.createElement('canvas').getContext('webgl'); } catch(e) { return false; } })(), webWorkers: !!window.Worker, localStorage: (() => { try { localStorage.setItem('test', 'test'); localStorage.removeItem('test'); return true; } catch(e) { return false; } })() }; } }; // ポリフィルの実装 if (!Array.prototype.includes) { Array.prototype.includes = function(searchElement, fromIndex) { if (this == null) { throw new TypeError('"this" is null or undefined'); } const o = Object(this); const len = o.length >>> 0; if (len === 0) { return false; } const n = fromIndex | 0; let k = Math.max(n >= 0 ? n : len + n, 0); while (k < len) { if (o[k] === searchElement) { return true; } k++; } return false; }; } // ベンダープレフィックスの処理 const vendorPrefix = { getPrefix() { const styles = window.getComputedStyle(document.documentElement, ''); const prefix = (Array.prototype.slice .call(styles) .join('') .match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o']) )[1]; return { dom: prefix === 'ms' ? 'MS' : prefix, css: `-${prefix}-` }; }, applyPrefixedStyle(element, property, value) { const prefix = this.getPrefix().css; element.style[property] = value; element.style[prefix + property] = value; } };
ブラウザ対応状況
主要ブラウザの各API対応状況を示します。
- Chrome: バージョン100以降で全APIに対応
- Firefox: バージョン95以降で全APIに対応
- Safari: バージョン15以降で主要APIに対応
- Edge: バージョン95以降で全APIに対応
APIリファレンス
各APIの詳細な仕様とメソッド一覧です。
- DOM API
- Web Storage API
- Fetch API
- Web Components API
- Service Workers API
- WebGL API
用語集
ウェブ開発で使用される主要な用語の説明です。
- DOM (Document Object Model)
- API (Application Programming Interface)
- AJAX (Asynchronous JavaScript and XML)
- SPA (Single Page Application)
- PWA (Progressive Web Application)
関連リソース
さらなる学習のための参考資料です。