【PWA】OneSignalを使ってiOSにWebプッシュ通知を送るRTA
はじめに
2023年3月27日に公開されたiOS 16.4で、iOSおよびiPadOSでホーム画面に追加されたWebアプリにWeb Pushがサポートされました。
今回は超カンタンにWebプッシュ通知機能が使えることを証明するため、iOS SafariにWebプッシュ通知を送るまでのRTAに挑戦してみたいと思います。
多分これが一番早いと思います。
レギュレーション
達成条件
Next.jsで新規作成したWebアプリをPWAにしてiPhoneのSafariでWebプッシュ通知を受け取る(Any%)
使用技術
Next.js v14.0.3 (App router)
TypeScript v5.3.2
タイム計測方法
開始点:Terminalでcreate-next-appを実行した瞬間
終了点:Webプッシュ通知を送信してiPhoneで通知を受け取った瞬間
タイマー:外部タイマーを使用し、ビデオ記録にタイマーを表示する
OneSignalとは
プッシュ通知を簡単に送信することができるサービスです。
多様なプラットフォーム(iOS、Android、Web)に対応しており、セグメンテーション、A/Bテストなどの高度な機能も提供しています。無料プランもあります。
実装の流れ
- OneSignalに登録する
- Next.jsにOneSignalを導入する
- manifest.jsonを作成してPWAにする
- デプロイする
- iPhoneのSafariからA2HSする
- OneSignalからプッシュ通知を送る
OneSignalに登録する
OneSignalのSignUpからアカウントを作成します。
Create Appまで進めた後、Settings→Platformsに遷移してApp SettingsからWebを選択します。
1.Choose IntegrationはTypical Siteを選択します。
Webアプリに最低限必要な設定は
| 項目 | 設定値 |
|---|---|
| SITE NAME | Create Next App |
| SITE URL | http://localhost:3000/ |
です。
SITE URLには通常デプロイした環境のURLを設定しますが、ローカルで動作確認する必要があるため、現時点ではhttp://localhost:3000/を設定しています。

その他の設定はデフォルト値のままで問題ありません。Saveを押下して次に進みます。
6.Upload Filesでダウンロードしたファイルは解凍して後ほどpublicディレクトリに格納します。
また7.Add Code to SiteからappIdだけメモしておきます。

Next.jsにOneSignalを導入する
create-next-appしてOneSignalを導入していきます。
今回はApp routerを使用していますがpages routerでも同様です。
手順は以下の3つだけです。
1. OneSignalSDKWorker.jsをpublicに格納する
先ほどダウンロードして解凍したOneSignalSDKWorker.jsをpublicディレクトリに格納します。
2. react-onesignalをインストールする
React用のモジュールですがTypeScriptをサポートしていて便利なので使用します。
npm i react-onesignal
# or
yarn add react-onesignal
# or
pnpm add react-onesignal
# or
bun add react-onesignal
3. OneSignalを初期化する
OneSignalはwindowオブジェクトを拡張して動作するようになっているため、クライアントコンポーネントにする必要があります。
また下記のコード例ではOneSignalを初期化した後すぐにプッシュ通知のプロンプトを表示するように呼び出しています。
'use client'
import { useEffect } from 'react'
import OneSignal from 'react-onesignal'
export const OneSignalInitial = () => {
useEffect(() => {
const oneSignalInit = async () => {
await OneSignal.init({
appId: process.env.NEXT_PUBLIC_ONESIGNAL_APP_ID || '',
}).then(() => {
OneSignal.Slidedown.promptPush()
})
}
oneSignalInit()
}, [])
return null
}
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
+import { OneSignalInitial } from '@/lib/OneSignalInitial'
// 省略
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>
+ <OneSignalInitial />
{children}
</body>
</html>
)
}
ここまで設定して開発環境で確認するとプッシュ通知の購読許可するプロンプトが表示されます。

この時点ですでにiOS Safari以外のブラウザではプッシュ通知を受け取ることができるようになっています。
下記の画像はMac chromeでSubscribeを押下した直後に届いたプッシュ通知です。

manifest.jsonを作成してPWAにする
manifest.json generaterを使用して必要最低限のmanifest.jsonを生成します。
今回は下記のgeneratorを使用しました。
生成されたmanifest.webmanifestをmanifest.jsonに変換してiconの画像ファイルと一緒にpublicに格納します。
{
"theme_color": "#f69435",
"background_color": "#f69435",
"display": "standalone",
"scope": "/",
"start_url": "/",
"name": "next pwa webpush example",
"short_name": "example",
"icons": [
{
"src": "/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icon-256x256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
manifest.jsonをsrc/app/layout.tsxで読み込みます
// 省略
return (
<html lang="en">
+ <head>
+ <link rel="manifest" href="/manifest.json" />
+ <link rel="apple-touch-icon" href="/icon-192x192.png"></link>
+ <meta name="theme-color" content="#f69435" />
+ </head>
<body className={inter.className}>
<OneSignalInitial />
{children}
</body>
</html>
)
これでPWAになりました。
デプロイする
お好きなホスティング先にデプロイしてください。
今回はVercelにデプロイしました。
デプロイ後にはOneSignalのApp SettingsでSITE URLをデプロイした環境のURLに変更する必要があります。

iPhoneのSafariからA2HSする
iPhoneのSafariからA2HS(Add to Home Screen)します。
ホームに追加されたアプリを開くとプッシュ通知の購読許可するプロンプトが表示されます。

OneSignalからプッシュ通知を送る
OneSignalのMessages→Pushに遷移してNew Messageから新しいプッシュ通知を作成します。
Messageの内容は必須です。
それ以外はデフォルトのままでも構いません。

最後にReview and Sendを押下してプッシュ通知を送信します。
無事iOS SafariにWebプッシュ通知を送ることができました。

RTA 結果タイム
この記事を見ながら実装してタイムを計測してみました。
焦ってしまい正確に計測できませんでしたが、10分を切ることができました。


10分程度で出来るので皆さんもぜひ挑戦してみてください。
Discussion