iPhone アプリ2026年11月5日約12分
Capacitor とは? Next.jsを iPhoneアプリに
Capacitor とは、Web の画面をそのまま iPhone アプリの中で動かすための道具です。この記事では、Next.js で作ったサイトを Capacitor で iPhone アプリにし、Mac のシミュレーターで動かすところまで進めます。私が記録アプリ「ツモル」を App Store に出したときの設定とコマンドを、そのまま載せています。
- この記事でできること
- Next.js の
サイトを iPhone アプリに して、 シミュレーターで 開く - かかる時間
- 1〜2時間ほど
(目安。 Xcode を 入れる 時間は 除く) - 必要なもの
- Mac、
Xcode、 Node.js、 Next.js の プロジェクト。 ストアに 出すなら Apple Developer Program への 登録 - 確認した環境
- 202
6年11月、 macOS 26.5.1、 Xcode 26.3、 Node.js 22.12.0、 Next.js 16.3.8、 Capacitor 8.5.3 (@capacitor/cli・core・ios)。 Capacitor 8 は Node.js 22 以上と Xcode 26.0 以上が 必要です (Capacitor 公式の 環境の 手順)。
Capacitor とは
Capacitor は、Web の画面を表示する部品(iPhone では WKWebView)をアプリの中に置き、そこで自分の Web アプリを動かす仕組みです。公式は「Web アプリのための、複数の OS で動くネイティブの実行環境」と説明しています。
ふつうの Web サイトと違うのは、画面の JavaScript から iPhone の機能を呼べることです。ツモルでは「端末の中で時刻を予約する通知」のために入れました。ホーム画面に追加する Web アプリ(PWA)では、通知はサーバーから送る形しか取れません。
Cordova・Ionic との違い
- Cordova:Capacitor より前からある、同じ考え方の道具です。公式は「考え方はとても近い」と書いています。Capacitor は Cordova のプラグインも使えますが、使えないものもあり、
npx cap syncが飛ばします(公式の Cordova プラグインのページ)。 - Ionic:Capacitor を作っているチームの名前であり、同じチームが出している画面の部品集(Ionic Framework)の名前でもあります。Capacitor は Ionic Framework が無くても使えます。React でも Vue でも、Next.js でもかまいません。
向いているアプリ・向かないアプリ
向いているもの
- すでに Web 版があり、同じコードで iPhone 版も出したいアプリ
- 記録・ToDo・予定のように、画面の操作が中心のアプリ
- 通知や振動など、Web では足りない機能を少しだけ足したいアプリ
ツモルは Web 版と iPhone 版を同じコードから作り、iPhone 版にだけ通知(@capacitor/local-notifications)、振動(@capacitor/haptics)、広告(@capacitor-community/admob)を足しています。
向かないもの
- 3D のゲームなど、描く処理が重いアプリ
- Web サイトを包んだだけで、アプリならではの機能が無いもの
2つ目は審査の問題です。Apple の審査の決まり 4.2 は「包み直した Web サイト以上の機能・内容・画面」を求めています。私は KOMARO(日程調整のアプリ)を出す前にここを心配していましたが、KOMARO もツモルも 4.2 での差し戻しはありませんでした。ツモルは最初から通知を入れ、審査メモに「圏外でも記録できる」ことを書いています。
Next.js のサイトを iPhone アプリにする手順
1. Next.js を静的に書き出す
Capacitor はアプリの中に「HTML と JavaScript のファイル一式」を入れて開きます。Next.js には、サーバー無しで開けるファイルに書き出す機能(静的書き出し)があります。next.config.ts に output: "export" を書くと、next build で out フォルダができます。
ツモルでは、Web の本番(Vercel)はそのままにして、アプリ用のときだけ書き出すように切り替えています。
// next.config.ts
import type { NextConfig } from "next";
const forApp = process.env.TSUMORU_TARGET === "app";
const nextConfig: NextConfig = {
...(forApp ? { output: "export", pageExtensions: ["tsx"] } : {}),
};
export default nextConfig;
pageExtensions: ["tsx"] は、API のファイル(route.ts)を書き出しから外すためです。書き出しでは、リクエストを読む API、Cookie、リダイレクト、Server Actions、next/image の既定の画像最適化などが使えません(Next.js 公式の静的書き出しのページに一覧があります)。API が要る場合、アプリからは本番の住所の API を呼びます。
next.config.tsを上のように書き換える。TSUMORU_TARGET=app npx next buildを流す(TSUMORU_TARGETの名前は自分のアプリに合わせて変えてかまいません)。outフォルダの直下にindex.htmlができたことを確かめる。

index.html には <head> が要ります。無いとプラグインが動きません(Capacitor 公式)。Next.js の書き出しなら入っています。
2. Capacitor を入れる
プロジェクトの一番上のフォルダで、次を流します(Capacitor 公式の手順)。
npm i @capacitor/core
npm i -D @capacitor/cli
npx cap init
npx cap init はアプリの名前と ID を聞いてきます。ID は iPhone の「Bundle ID」になるもので、自分のドメインを逆にした形(例:app.tsumoru)にします。Apple の説明では、ビルドをアップロードしたあとは Bundle ID を変えられません。ここで決めておきます(App Store Connect ヘルプ)。
できた capacitor.config.ts の webDir を、書き出し先の out にします。ツモルの設定はこれだけです。
// capacitor.config.ts
import type { CapacitorConfig } from "@capacitor/cli";
const config: CapacitorConfig = {
appId: "app.tsumoru",
appName: "ツモル",
webDir: "out",
};
export default config;
3. iOS のプロジェクトを作る
npm i @capacitor/ios
npx cap add ios
ios フォルダができ、中に Xcode のプロジェクトが入ります。Capacitor 8 では、iOS の部品の管理に Swift Package Manager を使うのが標準です。前の版で使っていた CocoaPods は --packagemanager CocoaPods を付けたときだけ使います(公式の環境の手順)。CocoaPods を使わないなら Homebrew も要りません。

4. 書き出した画面をアプリへ入れる
npx cap sync ios
out の中身が ios/App/App/public へ写され、プラグインも組み込まれます。画面を直したら、毎回「書き出し → sync」をやり直します。 ツモルでは1つのコマンドにまとめています。
"scripts": {
"build:app": "TSUMORU_TARGET=app next build && cap sync ios"
}
npm run build:app
5. Xcode で開いてシミュレーターで動かす
npx cap open ios
- Xcode が開いたら、上の真ん中にある端末の選択から、シミュレーター(例:iPhone 17)を選ぶ。
- 左上の再生ボタン(▶)を押す。
- シミュレーターが立ち上がり、自分のアプリが開くのを待つ。


Xcode を開かずに npx cap run ios でも動かせます。
実機・ストアに出すときの注意
自分の iPhone で動かす
- iPhone を Mac につなぐ。
- Xcode の左の一覧で「App」を選び、「Signing & Capabilities」を開く。
- 「Team」に自分の Apple アカウントを選ぶ。
- 端末の選択で自分の iPhone を選び、再生ボタンを押す。

Apple Developer Program に入っていない無料のアカウント(Xcode では「Personal Team」と出ます)でも、自分の iPhone で動かせます。ただし、入れたアプリは7日で期限が切れ、登録できる端末は3台までです(Apple の比較表)。期限が切れたら、もう一度ビルドして入れ直します。
Xcode から iPhone に入れるときは、iPhone の「設定」→「プライバシーとセキュリティ」→「デベロッパモード」をオンにします。オンにすると再起動を求められ、再起動のあとに「有効にする」を押してパスコードを入れます。この項目は、Mac とつないだことがある iPhone にだけ出ます(Apple の説明)。
ストアに出す前に確かめること
server.urlで本番のサイトを読む作りにしない。 Capacitor の設定には、アプリの中で外の住所を開くserver.urlがありますが、公式は「開発中の再読み込み用で、本番に使うものではない」と書いています。KOMARO の iPhone 版は今もこの形で出していますが、これから作るなら画面を同梱する形を勧めます。- アプリならではの機能を1つ入れる。 審査の決まり 4.2 への備えです。ツモルの通知、KOMARO の圏外の案内画面がこれにあたります。
- Web を直してもアプリは変わらない。 画面を同梱しているので、アプリに届けるには書き出してストアに出し直します。
- Capacitor を新しい版に上げておく。 2026年10月、@capacitor/ios 8.5.0 に重大な脆弱性の勧告(GHSA-rvm3-566m-v7fv)が出ました。ツモルは 8.5.3 に上げてから審査に出し直しています。
npm auditで確かめられます。 - 広告や分析を入れたら、App Store Connect の「App のプライバシー」を直す。 ツモルは AdMob を入れたとき、「デバイスID」と「広告データ」を足してから出しました。
審査に出す手順はApp Store にアプリを出す手順にまとめています。
圏外でも開けるようにするには
画面をアプリに同梱すれば、起動するときに通信しないので、電波の無い場所でも開けます。ツモルは最初、本番を読みながら Service Worker(一度読んだ画面を端末に取っておく仕組み)で圏外に備えていましたが、広告と両立しませんでした。最後は同梱に切り替えて、圏外と広告の両方を取っています。
同梱にすると、画面の住所が https://... から capacitor://localhost に変わります。そのため、端末に保存した記録の引き継ぎ、API の呼び先、ログインのメールの戻り先を直す必要がありました。この話は圏外でも開けるアプリにする方法に書いています。
よくあるエラーと直し方
| エラーの文 | 原因 | 直し方 |
|---|---|---|
| (エラーは出ず、ボタンを押しても何も起きない) | server.url で外のサイトを読み、Capacitor が2つ動いている | 注入された Capacitor.Plugins だけを使う。または画面を同梱する |
| 日本語が全部「□」になる | -apple-system だけでは日本語の書体に切り替わらない | 日本語用の書体(ヒラギノなど)を名前で指定する |
| 別の画面で読み直すとトップの画面が出る | 拡張子の無い住所を Capacitor が index.html として返す | 同じ名前の .html を返す振り分けを iOS 側に書く |
| ネットワークに接続できません | server.url で本番を読んでいて、通信できない | 画面を同梱する。読む作りのままなら server.errorPath で同梱の案内画面を出す |
Page "/…/[id]" is missing "generateStaticParams()" so it cannot be used with "output: export" config. | 住所に変数を含む画面([id])に、書き出す住所の一覧が無い | generateStaticParams() で書き出す住所を決める |
よくある質問
Capacitor と Cordova、今から使うならどちらですか。
私は Capacitor を使っています。どちらも Web の画面をアプリの中で動かす道具ですが、Capacitor は Cordova のプラグインの多くも使えます。Cordova から Capacitor へ移る手順も公式にあります。
Capacitor を使うには Ionic が必要ですか。
要りません。Capacitor は Ionic のチームが作っていますが、画面は React・Vue・Next.js など何で作ってもかまいません。ツモルは Next.js と Tailwind CSS だけで、Ionic の部品は使っていません。
Next.js の API(Route Handlers)はアプリの中で動きますか。
書き出したアプリの中では動きません。リクエストを読む API はサーバーが要るためです。ツモルでは API を Vercel の本番に置いたまま、アプリからはその住所を呼んでいます。本番の API 側では、アプリの住所(capacitor://localhost)からの呼び出しを通す設定(CORS)を足しました。
Windows でも iPhone アプリを作れますか。
iPhone アプリをビルドするには Mac が要ります(Capacitor 公式の環境の手順)。Capacitor そのものは Windows でも入りますが、Xcode が Mac にしか無いためです。