Next.jsのプロジェクトでWebプッシュ通知を行う方法を記載します!
Webプッシュ通知にはOneSignalというプッシュ通知を行う際に良く利用されるサービスを用います。
始める前は正直難しそうだな、、と思っていたのですが、
分かりやすいサービスで非常に導入がしやすかったです!
検証した環境
1 | nextjs | 14.1.3 |
2 | react-onesignal | 3.0.1 |
OneSignalへの登録
Push Notification Software to Improve Customer Engagement - OneSignal

OneSignal は
- 無料で始められる
- モバイルへのプッシュ通知、webのプッシュ通知が行える
- A/Bテスト、ユーザープロパティに応じた通知最適化
といった特徴があります
Web Pushの設定
アカウントの登録を進めていくのと同時にアプリを作成されていて
計7ステップあることが表示されます

Push Notification > Web を選択

Typical Site
を選択- サイト名入力
- ローカルのURLを入力(
http://localhost:3000
のような値) - LOCAL TESTINGをONに(ローカルのURLを入力すると表示されます)

Permission Prompt Setup
からCustom Linkを追加
Prompt Editorが表示されて、内容はデフォルトのままでOKです!

デフォルトで登録されている「Push Slide Prompt」を削除します。

サイトアクセス時に自動で通知許可のダイアログを表示する場合はPush Slide Promptを残します
その他の設定はそのままでSaveボタンを押下
すると以下のような設定をアプリケーションに行ってね、というメッセージが表示されます

ここで重要なのは
- Download OneSignal SDK files からサービスワーカーファイルをDL
- appId以降のOneSignalのappIdを取得
の2点がポイントです
Next.jsへの設定
OneSignalが機能することの確認
まず Next.js で OneSignal が接続出来ていることを確認出来るようにします
手順としては大きく3つ
- サービスワーカーファイルをアプリケーションに設置
- OneSignalの設定を追記
- 通知用ボタンを表示
1. サービスワーカーファイルをアプリケーションに設置

Download OneSignal SDK filesからダウンロードしたサービスワーカーのファイルをpublicフォルダに設置します

意図としてはOneSignalが以下のURLにサービスワーカーのファイルがあることを想定しているためです
https://{yoursite.com}/OneSignalSDKWorker.js
参考: React JS Setup
そのため、ローカルで確認する際は
http://localhost:3000/OneSignalSDKWorker.js
にアクセスした際にファイルの中身が表示されればOKです!

2. OneSignalの設定をNext.jsに追加
React向けのOneSignalのパッケージを追加します
npm install react-onesignal
OneSignalを初期化するためのファイルを作成します。
いくつかのドキュメント読んだ限りApp Routerの場合client側で呼び出した方が良さそうなので、
'use client'
を使いつつ
styled-componentsなどを使用する方法を真似た形のregistryファイルを作って対応してみます
NEXT_PUBLIC_ONESIGNAL_APP_ID={{ OneSignalで取得したappId }}
'use client'
import { ReactNode, useEffect } from 'react'
import OneSignal from 'react-onesignal'
export function OneSignalRegistry(): ReactNode {
useEffect(() => {
const initializeOneSignal = async () => {
await OneSignal.init({
appId: process.env.NEXT_PUBLIC_ONESIGNAL_APP_ID || '',
notifyButton: {
enable: true,
},
})
}
initializeOneSignal()
}, [])
return undefined
}
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
import { OneSignalRegistry } from '@/lib/OneSignalRegistry'
const inter = Inter({ subsets: ['latin'] })
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="en">
<body className={inter.className}>
<OneSignalRegistry />
{children}
</body>
</html>
)
}
3. 通知用ボタンを表示
通知を許可するためのボタンを表示します
Next.jsを初期化した時に作成されたルートの page.tsx に記載してみます
import Image from 'next/image'
export default function Home() {
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<div className="onesignal-customlink-container" />
・・・
これで開発環境を立ち上げてみると
通知を許可出来るようになりました! 🙌
この時ブラウザのコンソールを確認すると「OneSignalを2回Initializeしようとしているよ」というエラーメッセージが表示されています

これは、開発環境だとReactのStrictModeで必ず2回呼び出しているのが原因で、
本番環境では表示されず特に問題にならないことが公式に書かれています
参考: React JS Setup
OneSignalからWebプッシュ通知を送る
いよいよWebプッシュ通知を送れるようにしていきます!
Vercelにデプロイ
Vercelにデプロイしサイトの表示を出来るようにします。
次の項目の設定をしていないため、
この時はまだOneSignalの通知ボタンが表示されません
環境変数 NEXT_PUBLIC_ONESIGNAL_APP_ID
の指定も忘れずに 📝
OneSignalの対象URLを変更
OneSignalの設定が http://localhost:3000
になっているはずなので、
デプロイしたVercelのURLにを変更します

これで改めてVercelを表示するとWebプッシュ通知のボタンが表示出来ました!

ここで「Subscribe to push notifications」ボタンよりプッシュ通知を許可しておきます
Webプッシュ通知を送る
OneSignalの Messages > Push よりメッセージを作成し

「Review and Send」を押下します
すると、Webプッシュ通知が無事届きました!!🎉
