ハイライト
macOS Sonoma では任意の Web サイトを Dock に独立 Web App として追加でき、専用ウィンドウ、Cookie、システムレベルの権限管理を持ちます。Web App Manifest でツールバー、リンク遷移範囲、display モードを制御でき、Web Push 通知と Badge は macOS と iOS/iPadOS のホーム画面 Web App の両方で利用できます。
主要内容
macOS 上の Web App
macOS Sonoma で Web App 機能が追加されました。Safari で任意のサイトを閲覧中に File >「Dock に追加…」を選ぶと、Dock に独立アプリとして表示されます。追加時に Safari の Cookie がコピーされるため、通常はログイン状態が維持されます。
Web App には簡素化されたツールバーがあり、サイトのテーマカラーがツールバー背景に溶け込みます。Stage Manager、Mission Control、Command+Tab 切り替えなどネイティブ macOS アプリと同様に動作し、Dock、Launchpad、Spotlight から起動できます。
権限管理もネイティブアプリと同様です。カメラ、マイク、位置情報はシステム権限ダイアログで要求され、システム設定 > プライバシーとセキュリティで管理します。
(00:51)
Web App Manifest によるカスタマイズ
Web App Manifest で挙動を制御します。HTML の head に追加:
<link rel="manifest" href="/manifest.json">
主要フィールド:
name:Web App 名(ページタイトルを置換)display:表示モード、standaloneはツールバーなしstart_url:初回起動時に読み込む URLscope:Web App 内で開くリンクの範囲id:同一ドメイン内の Web App を区別する一意 ID
(05:01)
display: standalone の効果はプラットフォームで異なります:
- macOS:ツールバー非表示
- iOS/iPadOS:ホーム画面 Web App として独立 Cookie とストレージ、ブラウザと分離
iOS で Web Push と Badge を使うには standalone モードが必須です。
リンク遷移と Scope
Web App には関連 scope があります。scope 内リンクは Web App 内、外はデフォルトブラウザで開きます。デフォルト scope は Web App 作成時のページの host です。
manifest の scope でさらに限定可能。例: example.com/browserpets にすると example.com/webkittens はデフォルトブラウザで開きます。
iOS のホーム画面 Web App では scope 外リンクは Safari View Controller で開きます。
(05:53)
認証と Cookie
Web App 作成時に Safari の Cookie がコピーされるため、通常はログイン状態が維持されます。local storage はコピーされません。認証状態が Cookie と local storage に分散している場合、再ログインが必要です。
認証状態は Cookie に保存することを推奨します。OAuth フローは通常 Web App 内で開きます(ヒューリスティック)。問題があれば Apple に報告してください。window.open で開くリンクは常に Web App 内で、scope 制限を受けません。
メールの自動ログインリンクはデフォルトブラウザで開き、既存 Web App には自動ログインしません。メールにワンタイムコードを提供する代替も検討できます。Passkey 認証がより推奨されます。
(07:37)
Web Push 通知と Badge
macOS の Web App は標準 Web Push をサポートします。Web 標準に沿って Web Push を実装済みなら、macOS Web App で追加作業なしに利用できます。
通知には Safari ではなく Web App のアイコンが表示され、正しいコンテキストをユーザーに示します。
サウンドはプラットフォーム慣例に従い、iOS/iPadOS ではデフォルト ON、macOS ではデフォルト OFF。Notification API の silent で上書き:
new Notification("New message", { silent: false });
Badge は macOS Web App と iOS ホーム画面 Web App の両方でサポート。通知許可時に Badge 権限も付与されます。Web App 起動中およびバックグラウンド push 処理中に更新可能です。
(10:00)
フォーカスモード統合
Web App 通知はフォーカスモードと統合されます。ユーザーはフォーカスモードごとに異なる通知設定ができ、デバイス間で同期されます。
manifest の id で同一ドメイン内の異なる Web App を区別。shop と forums なら id: "shop" と id: "forums" で通知設定を分けられます。
フォーカス設定は name + id で同期。同一サイトの複数インスタンス(「Forums」と「Forums - Work」など)を作成し、通知とフォーカス設定を個別にできます。
(12:54)
新しい Web API
Safari 17 で追加された API:
- User Activation API:ユーザーが一時的または持続的なアクティベーションを行ったかをサイトに通知(通知権限要求前など)
- Fullscreen API:Safari 16.4 で macOS/iPadOS のプレフィックスを削除、標準 Fullscreen API をサポート
- Screen Orientation API:
type、angleプロパティとonchangeイベントの初期サポート
(14:29)
詳細
Web App Manifest 完全例
{
"name": "Browser Pets",
"short_name": "Pets",
"description": "A virtual pet community",
"start_url": "/browserpets",
"scope": "/browserpets",
"display": "standalone",
"theme_color": "#FF6B6B",
"background_color": "#FFFFFF",
"icons": [
{ "src": "/icon-192.png", "sizes": "192x192" },
{ "src": "/icon-512.png", "sizes": "512x512" }
],
"id": "browserpets"
}
キーポイント:
nameは Dock/ホーム画面表示、short_nameはスペース不足時start_urlは初回起動ページscopeは Web App 内リンク範囲、manifest URL のサブディレクトリである必要ありdisplay: standaloneは macOS でツールバー非表示、iOS で独立ホーム画面 Web Apptheme_colorは macOS ツールバー背景に影響idはフォーカスモード同期用に同一ドメイン内 Web App を区別
HTML で Manifest を参照
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#FF6B6B">
<title>Browser Pets - Your Virtual Pet Community</title>
<link rel="manifest" href="/manifest.json">
<link rel="apple-touch-icon" href="/icon-192.png">
</head>
<body>
<!-- ページ内容 -->
</body>
</html>
キーポイント:
theme-colormeta と manifest のtheme_colorを一致させるapple-touch-iconは iOS ホーム画面アイコンmanifestlink はhead内に配置
Web Push と Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(registration => console.log('SW registered'))
.catch(err => console.error('SW registration failed', err));
}
async function subscribeToPush() {
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(
'BEl62i...'
)
});
await fetch('/api/push-subscription', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(subscription)
});
}
キーポイント:
- Web Push には Service Worker が必要
pushManager.subscribeはユーザーアクティベーション(クリック等)が必要applicationServerKeyはサーバーの VAPID 公開鍵userVisibleOnly: trueは各 push で通知を表示
Service Worker で push 処理:
// sw.js
self.addEventListener('push', event => {
const data = event.data?.json() ?? {};
event.waitUntil(
self.registration.showNotification(data.title, {
body: data.body,
icon: '/icon-192.png',
badge: '/badge-72.png',
silent: false,
data: { url: data.url }
})
);
});
self.addEventListener('notificationclick', event => {
event.notification.close();
event.waitUntil(
clients.openWindow(event.notification.data.url)
);
});
キーポイント:
showNotificationで Service Worker からシステム通知を表示silent: falseで macOS デフォルト静音を上書きbadgeは通知エリアと Dock バッジ用の小アイコンnotificationclickで通知タップ時の挙動を処理
Badge API の利用
navigator.setAppBadge(42);
navigator.clearAppBadge();
self.addEventListener('push', event => {
event.waitUntil(
getUnreadCount().then(count => {
return self.navigator.setAppBadge(count);
})
);
});
キーポイント:
navigator.setAppBadge()で Dock(macOS)またはホーム画面アイコン(iOS)のバッジを設定- 通知許可時に Badge 権限も自動付与
- Service Worker では
self.navigator.setAppBadge()で更新 - フォアグラウンド・バックグラウンド両方で更新可能
認証状態管理
// 推奨: 認証状態を Cookie に保存
// Set-Cookie: session=abc123; Path=/; HttpOnly; Secure; SameSite=Lax
// 避ける: localStorage に認証状態を分散
// Web App 作成時に localStorage はコピーされない
async function checkAuthState() {
const sessionCookie = document.cookie.match(/session=([^;]+)/);
const localToken = localStorage.getItem('auth_token');
if (sessionCookie && !localToken) {
const response = await fetch('/api/refresh-token', {
credentials: 'include'
});
const data = await response.json();
localStorage.setItem('auth_token', data.token);
}
}
キーポイント:
- Web App 作成時は Cookie のみコピー、localStorage は非コピー
- Cookie のみ認証のサイトは通常ログイン維持
- 混合認証は初回読み込みで検出し再認証を案内
- Passkey はメールリンクより安全で便利
重要ポイント
1. Web App Manifest をサイトに追加
- やること:既存サイトに manifest.json を追加し、
name、display: standalone、theme_color、iconsを設定 - 価値:macOS ユーザーが Dock に独立アプリとして追加、iOS ユーザーがホーム画面 Web App 体験を得られる
- 始め方:manifest.json を作成、HTML head に link を追加、Safari の「Dock に追加」「ホーム画面に追加」をテスト
2. Web Push 通知を実装
- やること:Web App にプッシュ通知(新着メッセージ、Badge 更新)を追加
- 価値:Web App 未起動でも再エンゲージ、Badge で未読数を表示
- 始め方:Service Worker 登録、Push API 購読、サーバー側 Web Push 統合、プラットフォーム別
silent処理
3. 従来認証を Passkey に置き換え
- やること:パスワードやメールリンクから Passkey ログインへ移行
- 価値:Web App とブラウザ両方で動作、Cookie コピー制限の影響を受けにくく、メールコードより安全
- 始め方:Web Authentication API を統合。WWDC22「Meet passkeys」を参照
4. 同一サイトの複数機能を独立 Web App 化
- やること:店舗とフォーラムなど独立機能ごとに
idで区別した Web App を作成 - 価値:機能ごとに通知とフォーカス設定を分け、ネイティブアプリに近い体験
- 始め方:機能ごとに独立 manifest、
idとscopeを設定、リンクが正しい Web App で開くことを確認
5. Scope 外リンクを適切に処理
- やること:scope 境界を明確にし、外部リンク(サードパーティログイン等)が正しく遷移するよう設計
- 価値:scope 外はデフォルトブラウザで開くため、OAuth 誤判定でログイン不能になる可能性
- 始め方:外部リンクと OAuth フローをテスト。Web App 内で開く必要がある場合は
window.open()を使用例。誤判定 OAuth ドメインは Apple に報告
関連セッション
- Meet Web Push for Safari — Safari における Web Push 標準の実装
- Rediscover Safari developer features — Safari 開発者機能の総合アップデート
- What’s new in Web Inspector — Safari Web Inspector の新しいデバッグ機能
- What’s new in Safari extensions — Safari 拡張の新 API と機能
- Meet passkeys — Passkey 認証の紹介
コメント
GitHub Issues · utterances