はじめに
既存の Nuxt ウェブアプリをお持ちですか?このガイドでは、以下のツールを使用してネイティブな iOS および Android モバイルアプリに変換する方法を解説します。 Capacitor 8 — パフォーマンスが向上し、新機能が追加された最新バージョンです。
Capacitor は、既存の Vue コードベースを維持したまま、Web アプリをネイティブコンテナでラップします。これにより、カメラ、ファイルシステム、プッシュ通知などのデバイス API へのアクセスが可能になります。Flutter や React Native とは異なり、コードを書き直す必要はありません。Nuxt の code がそのまま動作します。
学習内容:
- 既存の Nuxt アプリを静的生成(SSG)用に設定する
- 必須のネイティブプラグインを含む Capacitor 8 を追加する
- iOS および Android シミュレーターでのビルドとテスト
- 開発を高速化するライブリロードの有効化
- iOS でよくあるレイアウトの問題(viewport、セーフエリア、横方向のオーバーフロー)の修正
- Capgo Native Navigation と Transitions でネイティブに近い UI を実現する
ゼロから新しいプロジェクトを始めたい方は、こちらのガイドをご覧ください: Nuxt モバイルアプリをゼロから構築する.
Nuxt と Capacitor を使用するメリット
- Code による再利用性: VueコンポーネントとロジックをWebとモバイルアプリ間で共有できます。
- パフォーマンス: Nuxtの静的生成により、モバイルに最適な最適化済みbundleを作成できます。
- Native機能の活用: Capacitorプラグインを通じて、カメラ、位置情報、ファイルシステムなどのデバイス機能にアクセスできます。
- 開発の簡素化: Native開発を学ぶことなく、使い慣れたVue/Nuxtのパターンを利用できます。
前提条件
開始前に、以下が用意されていることを確認してください:
- Node.js 18+ インストール
- 既存の Nuxt 4 アプリケーション
- iOSプロファイリング (iOS開発用、macOSのみ)
- デバッグ (Android開発用)
Nuxtアプリのモバイル向け設定
最初のステップは、Nuxtアプリを静的生成用に設定することです。Capacitor はネイティブアプリにバンドルするため、静的なHTML/JS/CSSファイルが必要です。
次の設定( package.json に以下のgenerateスクリプトがあります:
{
"scripts": {
"dev": "nuxt dev",
"build": "nuxt build",
"generate": "nuxt generate",
"preview": "nuxt preview",
"mobile": "bun run generate && bunx cap sync",
"mobile:ios": "bun run mobile && bunx cap open ios",
"mobile:android": "bun run mobile && bunx cap open android"
}
}
重要: サーバーサイドの機能(API ルートやサーバーミドルウェアなど)を使用している場合は、クライアントサイドの代替手段や外部APIを使用するようにリファクタリングする必要があります。
以下のコマンドを実行して、静的生成をテストしてください:
bun run generate
以下の .output/public 静的ファイルが格納されたフォルダです。Capacitor は、この内容をネイティブアプリに bundle します。
プロジェクトに Capacitor 8 を追加する
Nuxt アプリをネイティブモバイルコンテナにパッケージングするには、以下の手順に従ってください:
- Capacitor core と CLI をインストールします:
bun add @capacitor/core
bun add -D @capacitor/cli
- 必要になりそうな一般的な Capacitor プラグインをインストールします:
bun add @capacitor/app @capacitor/keyboard @capacitor/splash-screen @capacitor/status-bar @capacitor/preferences
これらのプラグインは、以下の必須機能を提供します:
- @capacitor/app:アプリのライフサイクルイベント(フォアグラウンド/バックグラウンド、ディープリンク)を処理します
- @capacitor/keyboard:モバイルでのキーボードの動作を制御します
- @capacitor/splash-screen: ネイティブのスプラッシュ画面を管理
- @capacitor/status-bar: デバイスのステータスバーのスタイルを設定
- @capacitor/preferences: キーバリューストレージ(localStorageのようだがネイティブ)
- プロジェクトの詳細で Capacitor を初期化します:
bunx cap init my-app com.example.myapp --web-dir .output/public
置換する my-app アプリ名と com.example.myapp アプリID(逆ドメイン形式)を使用して。
- 以下を作成または更新:
capacitor.config.ts適切な設定を含むファイル:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: '.output/public',
plugins: {
SplashScreen: {
launchShowDuration: 2000,
launchAutoHide: true,
androidScaleType: 'CENTER_CROP',
splashFullScreen: true,
splashImmersive: true,
},
Keyboard: {
resize: 'body',
resizeOnFullScreen: true,
},
StatusBar: {
style: 'dark',
},
},
};
export default config;
- ネイティブプラットフォームのインストール:
bun add @capacitor/ios @capacitor/android
- ネイティブプラットフォームのフォルダを追加:
bunx cap add ios
bunx cap add android
Capacitor により、 ios と android プロジェクトのルートにネイティブプロジェクトを含むフォルダが作成されます。
Androidプロジェクトをビルドするには、以下が必要です: デバッグiOSの場合は、Macと以下が必要です: iOSプロファイリング.
- プロジェクトのビルドと同期:
bun run mobile
これにより、カスタムスクリプトが実行され、静的なNuxtビルドの生成とネイティブプラットフォームへのファイルの同期が行われます。
ネイティブアプリのビルドとデプロイ
ネイティブモバイルアプリをビルドしてデプロイするには、以下の手順に従ってください:
iOSアプリを開発するには、 iOSプロファイリング のインストールが必要です。また、Androidアプリの場合は、 デバッグ のインストールが必要です。さらに、アプリをApp Storeで配布する場合は、iOS用にApple Developer Programへ、Android用にGoogle Play Consoleへの登録が必要になります。
- ネイティブプロジェクトを開く:
iOSの場合:
bun run mobile:ios
Androidの場合:
bun run mobile:android
または Capacitor CLI で直接実行:
bunx cap open ios
bunx cap open android
- アプリのビルドと実行:

- Android Studioでプロジェクトの準備が整うのを待ち、「Run」ボタンをクリックして、接続されたデバイスまたはエミュレータにアプリをデプロイします。

- Xcodeで、実機にアプリをデプロイするためのSigningアカウントを設定します。初めての場合は、Xcodeのガイドに従って設定を進めてください(Apple Developer Programへの登録が必要です)。設定完了後、「Play」ボタンをクリックすると、接続されたデバイスでアプリが実行されます。
おめでとうございます!Nuxtウェブアプリのモバイルデバイスへのデプロイに成功しました。
でもちょっと待ってください。開発中にもっと速い方法があります…
Capacitor Live Reload
開発中は、Live Reloadを活用することで、変更内容をモバイルデバイスに即座に反映できます。この機能を有効にするには、以下の手順に従ってください。
- ローカルIPアドレスを確認してください:
-
macOSでは、ターミナルで次のコマンドを実行します:
ipconfig getifaddr en0 -
Windowsの場合は、以下を実行してください:
ipconfig出力結果からIPv4アドレスを確認します。
- 以下のファイルを更新して、
capacitor.config.ts開発サーバーを指すように:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'my-app',
webDir: '.output/public',
server: {
url: 'http://YOUR_IP_ADDRESS:3000',
cleartext: true,
},
plugins: {
// ... your plugin config
},
};
export default config;
置換する YOUR_IP_ADDRESS ローカルIPアドレスに置き換えます(例: 192.168.1.100).
- 変更をネイティブプロジェクトに適用します:
bunx cap copy
この copy このコマンドは、プロジェクト全体を更新することなく、webフォルダと設定の変更内容のみをネイティブプロジェクトにコピーします。
- Nuxtのdev serverを起動し、XcodeまたはAndroid Studioでリビルドします:
bun run dev
これで、Nuxtアプリに変更を加えるたびに、モバイルアプリが自動的にリロードされ、変更が反映されるようになります。
注意: 新しいプラグインをインストールしたり、ネイティブファイルを変更したりした場合は、ネイティブプロジェクトの再ビルドが必要です。ライブリロードはWebの code 変更にのみ適用されるためです。
Capacitor プラグインの使用
Capacitor プラグインを使用すると、Nuxt アプリからデバイスのネイティブ機能にアクセスできます。以下の手順を プラグインを共有 例として見ていきましょう:
- Share プラグインをインストールします:
bun add @capacitor/share
- Share プラグインを使用するページを作成または更新します。Nuxt 4 では、ページは
app/pages/:
<template>
<div class="p-6">
<h1 class="text-2xl font-bold mb-4">Welcome to Nuxt + Capacitor!</h1>
<button
@click="shareContent"
class="px-6 py-3 bg-blue-600 text-white rounded-lg font-semibold"
>
Share now!
</button>
</div>
</template>
<script setup lang="ts">
import { Share } from '@capacitor/share';
async function shareContent() {
await Share.share({
title: 'Check this out!',
text: 'Built with Nuxt and Capacitor',
url: 'https://capacitorjs.com',
dialogTitle: 'Share with friends',
});
}
</script>
- 変更をネイティブプロジェクトに同期します:
bun run mobile
または、再ビルドせずに同期のみを行います:
bunx cap sync
- アプリを再ビルドしてデバイスで実行します。
これで、「Share now!」ボタンをクリックすると、ネイティブの共有ダイアログが表示されます。
次に、Capgo のナビゲーションとトランジションで、iOS と Android でアプリをよりネイティブに感じさせ、横方向のオーバーフローやセーフエリアの欠けを引き起こす iOS でよくあるレイアウト問題も修正できます。
Capgo Native Navigation and Transitions によるネイティブ感のあるUI
私は長年、 Ionic はクロスプラットフォームアプリの開発に適していますが、Nuxtとの統合は無理があり、すでに Tailwind CSS.
Nuxt + Capacitor アプリでネイティブアプリのような操作感を実現するには、Konsta UI のような Web 専用の UI キットではなく、Capgo プラグインを使用しましょう:
- @capgo/capacitor-native-navigation — ネイティブの navbar、iOS の Liquid Glass タブバー、Android のブラー効果付きタブバーなどが利用できます。Nuxt router がルートの状態を管理し、プラグインがネイティブの UI 要素(chrome)を制御します。
- @capgo/capacitor-transitions — Ionic UIを採用せずに、WebViewレイヤーでIonicスタイルのページ遷移とiOSのエッジスワイプによる戻る操作を実現します。
両方をインストールしてください:
bun add @capgo/capacitor-native-navigation @capgo/capacitor-transitions
bunx cap sync
CSS insetモードでネイティブナビゲーションを設定し、Webコンテンツがネイティブバーと重ならないようにします:
import { NativeNavigation } from '@capgo/capacitor-native-navigation';
await NativeNavigation.configure({
contentInsetMode: 'css',
animationDuration: 360,
glass: {
effect: 'liquidGlass',
},
});
Liquid Glassタブバーをレンダリングします(iOSはシステム側のレンダリングを使用し、Androidはぼかし付きWebViewバックドロップを使用します):
await NativeNavigation.setTabbar({
selectedId: 'home',
labelVisibilityMode: 'labeled',
icons: true,
colors: { dynamic: true },
tabs: [
{ id: 'home', title: 'Home', icon: { svg: '...' } },
{ id: 'settings', title: 'Settings', icon: { svg: '...' } },
],
});
await NativeNavigation.addListener('tabSelect', ({ id }) => {
router.push(`/${id}`);
});
アプリシェルにネイティブページ遷移を追加します:
<script setup>
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import '@capgo/capacitor-transitions';
import { initTransitions, setDirection, setupRouterOutlet } from '@capgo/capacitor-transitions/vue';
initTransitions({ platform: 'auto' });
const router = useRouter();
const outletRef = ref(null);
onMounted(() => {
if (outletRef.value) {
setupRouterOutlet(outletRef.value, { platform: 'auto', swipeGesture: 'auto' });
}
});
const openSettings = () => {
setDirection('forward');
router.push('/settings');
};
</script>
<template>
<cap-router-outlet ref="outletRef">
<router-view />
</cap-router-outlet>
</template>
ルーティングされたページを以下でラップします: cap-router-outlet, cap-pageや cap-content、そして呼び出します setDirection('forward') または setDirection('back') 遷移前に実行してください。ネイティブナビゲーションがその領域を管理している場合、Webのヘッダーやフッターを重複させないでください。
ガイドの全文はこちら: @capgo/capacitor-native-navigation の活用 と @capgo/capacitor-transitions の活用.
Tailwind によるセーフエリア対応
Tailwind CSS でデバイスのセーフエリアを扱うには、以下を使用します: @capgo/tailwind-capacitor ( tailwind-capacitor として npm で公開)。これは、 safe-areas ユーティリティや Capacitor と相性の良いその他の Tailwind プラグインを提供します:
bun add -D tailwind-capacitor
では app/assets/css/main.css:
@import 'tailwindcss';
@plugin "@capgo/tailwind-capacitor/platform";
@plugin "@capgo/tailwind-capacitor/safe-areas";
Tailwind CSS 4 を使用した Nuxt 4 の場合、以下のインポートを CSS ファイルに手動で記述してください。 nuxt.config.ts.
次のようなユーティリティを使用します: pt-safe, pb-safeや px-safe 手作業でばらまくのではなく env(safe-area-inset-*) 本プロジェクトは活発に開発されています。Nuxt のセットアップに必要な要素が不足している場合は、 GitHub でPRを作成してください.
iOSのレイアウト問題を修正(ビューポート、セーフエリア、横方向のオーバーフロー)
iOSでコンテンツが切れて見えたり、ずれて見えたり、横スクロールが発生したりする場合は、さらに追加するだけでも、 overflow-x: hidden viewportタグを調整するだけでも通常は解決しません。以下のチェックを順番に確認してください。
viewport メタタグが正しく適用されているか確認する
では nuxt.config.ts、ビューポートを以下で設定します: app.head:
export default defineNuxtConfig({
app: {
head: {
meta: [
{
name: 'viewport',
content: 'width=device-width, initial-scale=1, viewport-fit=cover',
},
],
},
},
});
iOSのセーフエリアは1つのルートラッパーだけで処理する
単一のアプリシェルを作成し、そこにセーフエリアのパディングを適用してください — 複数のネストしたコンポーネントではなく:
html,
body,
#__nuxt {
width: 100%;
min-height: 100%;
margin: 0;
padding: 0;
overflow-x: hidden;
}
* {
box-sizing: border-box;
}
.app-shell {
min-height: 100dvh;
width: 100%;
padding-top: env(safe-area-inset-top);
padding-right: env(safe-area-inset-right);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
}
すべてのページコンテンツを以下でラップします: .app-shellヘッダー、モーダル、レイアウトラッパーで safe-area のパディングが重複すると、UI が欠けたり、逆に大きすぎたりすることがよくあります。
を使用すると、 @capgo/tailwind-capacitor同じパディングを次のようなユーティリティで表現できます: pt-safe pb-safe px-safe その単一のシェル上で。
Capacitor iOS を設定 contentInset まで never 最初に
では capacitor.config.ts、native inset を無効にすることを推奨し、CSS(または Native Navigation のもの contentInsetMode: 'css')に safe area を任せる:
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'out',
ios: {
contentInset: 'never',
},
};
Capacitor の自動コンテンツ inset と CSS を混在させると env(safe-area-inset-*) paddingが原因で、余白が二重に見えることがよくあります。
実際にオーバーフローしている要素を特定する
主な原因は、以下の要素を使用している場合です: 100vwTailwind、 w-screen固定ピクセル幅、または大きな min-width.
Safari Web Inspectorで以下を実行してください:
[...document.querySelectorAll('*')]
.filter(el => el.scrollWidth > document.documentElement.clientWidth)
.map(el => ({
el,
tag: el.tagName,
class: el.className,
scrollWidth: el.scrollWidth,
clientWidth: document.documentElement.clientWidth,
}));
Tailwindを使用する場合は、可能な限り w-screen を使用して w-full 置き換えてください。水平方向のオーバーフロー問題の多くは 100vw / w-screen、重複したセーフエリアのパディング、または固定幅のコンテナに起因し、viewportのmetaタグ自体が原因ではありません。
まとめ
Capacitor 8を使用して、既存のNuxt WebアプリをiOS/Androidのネイティブアプリに変換できました。VueコードベースはデバイスAPIにアクセスしながら、モバイル端末上でネイティブに動作します。
達成したこと:
- Nuxtを静的生成用に設定済み
- 必須プラグイン入りの Capacitor 8 を追加
- iOSとAndroidシミュレータ向けにビルドしてデプロイ
- 開発用にライブリロードを有効化
- iOSでよくあるレイアウト問題(viewport、safe area、overflow)を修正
- Capgo Native NavigationとTransitionsでネイティブ感のあるUIを追加
次のステップ:
- セットアップ Capgo App Storeへの再申請なしでOTAアップデートを実現
- Camera、Geolocation、Push Notificationsなどのネイティブプラグインをさらに追加
- 本番用のアプリアイコンとスプラッシュ画面を設定
- App StoreとGoogle Playへの申請準備
新規プロジェクトを始めるならこちら Nuxtモバイルアプリをゼロから構築する のガイド付きチュートリアルをご覧ください。
リソース
- Nuxt ドキュメント
- Capacitor 8 ドキュメント
- @capgo/capacitor-native-navigation — Liquid Glass タブバーとネイティブ UI
- @capgo/capacitor-transitions — ネイティブ感のあるページ遷移
- @capgo/tailwind-capacitor — Capacitor 用の Tailwind safe-area ユーティリティ
- Capgo - Capacitor アプリ向け Live Updates
Capgo が、より良いアプリをより速く作るのにどう役立つかをご覧ください。 無料アカウントに登録する を今すぐ作成してください。
Capacitor を使って Nuxt アプリを iOS & Android に変換する、の続きへ
使用している場合 Capacitor 8 で Nuxt アプリを iOS & Android に変換する ネイティブプラグインの作業を計画するには、次と連携してください: Capgo プラグインディレクトリ Capgo プラグインディレクトリのプロダクトワークフローについては、 Capgo による Capacitor プラグイン Capgo による Capacitor プラグインの実装詳細については、 プラグインの追加または更新 プラグインの追加または更新に関する実装詳細については、 Ionic Enterprise プラグインの代替案 Ionic Enterprise Plugin Alternatives のプロダクトワークフロー、および Capgo Native Build Capgo Native Builds のプロダクトワークフローについては、