このチュートリアルでは、まず新しい SvelteKit アプリを作成し、Capacitor を使ってネイティブモバイル開発へと移行していきます。Capgo Native Navigation and Transitions を追加してネイティブアプリのような操作感を実現したり、セーフエリア対策に tailwind-capacitor を使用したりすることも可能です。
Capacitor を使用すれば、React Native のような新しいスキルを習得したり、大幅なコード修正を行ったりすることなく、SvelteKit の Web アプリケーションを簡単にネイティブモバイルアプリへ変換できます。
Capacitor を使って SvelteKit アプリをモバイルアプリ化するステップバイステップガイドです。オプションで Capgo による Native Navigation、Transitions、iOS レイアウトのガイダンスも含まれています。
Capacitor について
CapacitorJS は革新的なツールです!あらゆる Web プロジェクトに簡単に統合でき、アプリケーションをネイティブの WebView でラップして、Xcode や Android Studio のプロジェクトを自動生成します。プラグインを使用すれば、JavaScript ブリッジ経由でカメラなどのネイティブデバイス機能にアクセスできます。
Capacitor を使えば、複雑なセットアップや学習コストをかけずに、素晴らしいネイティブモバイルアプリを作成できます。軽量な API と合理化された機能により、プロジェクトへの導入もスムーズです.Capacitor を使って、これほど簡単にフル機能のネイティブアプリを実現できることに驚くはずです!
SvelteKit アプリの準備
新しい SvelteKit アプリを作成するには、次のコマンドを実行してください:
npm create svelte@latest my-app
cd my-app
npm install
npm run build
次の build コマンドを実行すると、新しい dist フォルダがプロジェクトのルートに作成されます。
このフォルダは後ほど Capacitor で使用しますが、まずは正しくセットアップする必要があります。
SvelteKit アプリに Capacitor を追加する
Web アプリをネイティブのモバイルコンテナにパッケージングするには、まずいくつかの初期ステップが必要です。その後は、単一の sync コマンドです。
まず、 Capacitor CLI を 開発用依存関係としてインストールし、プロジェクト内でセットアップします。セットアップ中に、名前やbundle IDのデフォルト値を使用する場合は「enter」を押してください。
次に、コアパッケージとiOSおよびAndroidプラットフォーム用の関連パッケージをインストールします。
最後に、プラットフォームを追加すると、Capacitor がプロジェクトのルートに各プラットフォーム用のフォルダを作成します:
# Install the Capacitor CLI locally
npm install -D @capacitor/cli
# Initialize Capacitor in your SvelteKit project
npx cap init
# Install the required packages
npm install @capacitor/core @capacitor/ios @capacitor/android
# Add the native platforms
npx cap add ios
npx cap add android
これで、SvelteKitプロジェクト内に新しい ios と android フォルダが表示されるはずです。
これらは、本物のNative Buildプロジェクトです!
後でAndroidプロジェクトにアクセスするには、以下をインストールする必要があります: Android Studio。iOSの場合はMacが必要で、以下をインストールしてください: Xcode.
また、プロジェクト内に capacitor.config.ts ファイルがあることを確認してください。これには、同期時に使用される基本的な Capacitor 設定が含まれています。注意すべき点は、 webDirです。これはビルドコマンドの出力先を指している必要があります。現在は正しく設定されていません。
これを修正するには、 capacitor.config.ts ファイルを開いて webDir:
import { CapacitorConfig } from '@capacitor/cli'
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'my-app',
webDir: 'build',
}
export default config
Capacitor の設定を更新したので、次に適切な static adapter パッケージをダウンロードして、SvelteKit プロジェクトを静的アプリケーションに変更しましょう。
npm i -D @sveltejs/adapter-static
パッケージのインストール後、 svelte.config.js ファイルを auto-adapter から static に変更する必要があります:
import adapter from '@sveltejs/adapter-static'
import { vitePreprocess } from '@sveltejs/kit/vite'
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors
preprocess: vitePreprocess(),
kit: {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
adapter: adapter({
// default options are shown. On some platforms
// these options are set automatically — see below
pages: 'build',
assets: 'build',
fallback: null,
precompress: false,
strict: true
})
}
}
export default config
更新された svelte.config.js を使用して、 prerender オプションを追加するために、 +layout.js ページを作成します。 src/routes に以下のexportを追加するだけで +layout.js:
export const prerender = true
ページを追加・更新した後、 +layout.js モバイルプラットフォームを追加し、プロジェクトを再ビルドして build folder
以下のコマンドを実行することで可能です:
npm run build
npx cap sync
最初のコマンドは npm run build SvelteKitプロジェクトをビルドして静的ビルドをコピーし、2番目のコマンドは npx cap sync すべてのWeb code をネイティブプラットフォームの適切な場所に同期し、アプリ内で表示できるようにします。
さらに、syncコマンドによってネイティブプラットフォームの更新やプラグインのインストールが行われる場合があるため、新しい Capacitor プラグインをインストールした際は、再度 npx cap sync 実行する必要があります。
これで、気づかないうちにプロセスはすべて完了しました。それでは、実際にデバイスでアプリを確認してみましょう!
ネイティブアプリのビルドとデプロイ
iOSアプリを開発するには、 Xcode のインストールが必要です。また、Androidアプリの場合は、 Android Studio をインストールしてください。さらに、アプリをストアで配布する場合は、iOSならApple Developer Program、AndroidならGoogle Play Consoleへの登録が必要になります。
ネイティブモバイル開発が初めての方でも、Capacitor CLI を使えば、両方のネイティブプロジェクトを簡単に開くことができます。
npx cap open ios
npx cap open android
ネイティブプロジェクトのセットアップが完了すれば、接続されたデバイスへのアプリのデプロイは簡単です。Android Studioでは、準備が整うのを待つだけで、設定を変更することなく接続デバイスへデプロイできます。例を以下に示します:

Xcodeでは、シミュレーターではなく実機にデプロイするために、Signingアカウントの設定が必要です。初めての場合は、Xcodeのガイドに従って進めてください(ただし、Developer Programへの登録が必要です)。設定後は、上部で選択した接続デバイス上で、再生ボタンを押すだけでアプリを実行できます。例を以下に示します:

おめでとうございます!SvelteKitウェブアプリのモバイルデバイスへのデプロイに成功しました。例を以下に示します:
しかし、開発中にもっと素早く行う方法があります…
Capacitor Live Reload
最近のフレームワークによるHot Reloadには慣れているかと思いますが、嬉しいことに、モバイルデバイス上でも 同じ機能が 最小限の手間で利用可能です!
Live Reloadを使用してローカルで実行中のアプリケーションへのアクセスを有効にする ネットワーク上で Capacitor アプリに特定のURLからコンテンツを読み込ませることで実現できます。
最初のステップは、ローカルのIPアドレスを確認することです。Macを使用している場合は、ターミナルで次のコマンドを実行して確認できます:
ipconfig getifaddr en0
Windowsの場合は、次を実行してください:
ipconfig
その後、IPv4アドレスを探します。
また、次のファイルにエントリを追加することで、Capacitor にサーバーから直接アプリを読み込むよう指示することも可能です: capacitor.config.ts ファイル:
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'my-app',
webDir: 'dist',
bundledWebRuntime: false,
server: {
url: 'http://192.168.x.xx:3000',
cleartext: true
}
};
export default config;
必ず 正しいIPとポートを使用してください。上の例の通りです。
それでは、これらの変更をネイティブプロジェクトにコピーして適用しましょう:
npx cap copy
この copy コマンドは次と似ていますが、 syncただし、 webフォルダへの変更内容のみをコピーし、 ネイティブプロジェクトの更新は行いません。
これで、Android StudioやXcodeを通じてアプリを再度デプロイできます。その後、Svelteアプリに変更を加えると、 アプリが自動的にリロードされ、 変更が反映されます!
注意点として、 カメラなどの新しいプラグインをインストールする場合は、ネイティブプロジェクトの再ビルドが必要です。これはネイティブファイルが変更されるため、実行中に動的に行うことはできないからです。
設定には正しいIPとポートを使用してください。上記の code ブロックでは、デモ用にデフォルトのSvelteKitポートを表示しています。
Capacitor プラグインの使用
これまで何度か触れてきた Capacitor プラグインの実際の使い方を見てみましょう。以下のコマンドを実行して、シンプルなプラグインをインストールできます。
npm i @capacitor/share
特別なものはありませんが、 プラグインを共有を使えば、ネイティブの共有ダイアログが表示されます!そのためには、パッケージをインポートして share() アプリから関数を呼び出すだけなので、次は src/routes/index.svelte を次のように変更します:
<script>
import { Share } from '@capacitor/share';
async function share() {
await Share.share({
title: 'Open Youtube',
text: 'Check new video on youtube',
url: 'https://www.youtube.com',
dialogTitle: 'Share with friends'
});
}
</script>
<h1>Welcome to SvelteKit and Capacitor!</h1>
<button on:click={share}>Share now!</button>
先ほど説明したように、新しいプラグインをインストールするときは、sync 操作を行ってからアプリをデバイスに再デプロイする必要があります。これを行うには、次のコマンドを実行してください:
npx cap sync
ボタンを押すと、美しいネイティブの共有ダイアログが実際に動作する様子を確認できます!
次に、Capgo のナビゲーションとトランジションで、iOS と Android でアプリをよりネイティブに感じさせ、横方向のオーバーフローやセーフエリアの欠けを引き起こす iOS でよくあるレイアウト問題も修正できます。
Capgo Native Navigation and Transitions によるネイティブ感のあるUI
私は長年、 Ionic to build cross-platform applications, but integrating it with SvelteKit is hacky and rarely worth it when you already have Tailwind CSS.
SvelteKit + Capacitor アプリでネイティブなモバイル体験を実現するには、Konsta UIのようなWeb専用のUIキットではなく、Capgo プラグインを使用しましょう:
- @capgo/capacitor-native-navigation — ネイティブのナビゲーションバー、iOS向けのLiquid Glassタブバー、Android向けのブラー加工されたタブバーを提供します。SvelteKitのルーターがルート状態を管理し、プラグインがネイティブの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 }) => {
goto(`/${id}`);
});
アプリシェルにネイティブのページ遷移を追加します:
<script>
import { goto } from '$app/navigation';
import { routerOutlet, page, setDirection } from '@capgo/capacitor-transitions/svelte';
import '@capgo/capacitor-transitions';
function openSettings() {
setDirection('forward');
goto('/settings');
}
</script>
<cap-router-outlet use:routerOutlet>
<cap-page use:page>
<cap-content slot="content">
<slot />
</cap-content>
</cap-page>
</cap-router-outlet>
ルーティングされたページを以下でラップします: 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
では src/app.css:
@import 'tailwindcss';
@plugin "@capgo/tailwind-capacitor/platform";
@plugin "@capgo/tailwind-capacitor/safe-areas";
次のようなユーティリティを使用します: pt-safe, pb-safeや px-safe 散りばめるのではなく env(safe-area-inset-*) 手動で行うのではなく。このプロジェクトは活発に開発されています。SvelteKitの設定で不足しているものがあれば、 GitHub で PR を作成してください.
iOSのレイアウト問題の修正(ビューポート、セーフエリア、横方向のオーバーフロー)
iOSでコンテンツが切れたり、ずれたり、横スクロールが発生したりする場合、単に overflow-x: hidden ビューポートタグを追加・調整するだけでは解決しないことがよくあります。以下のチェック項目を順番に確認してください。
viewport メタタグが正しく適用されているか確認する
では src/app.html、viewport meta tagを以下に設定します: <head>:
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
iOSのセーフエリアを単一のルートラッパーで処理する
単一のアプリシェルを作成し、そこにセーフエリアのパディングを適用します。複数のネストされたコンポーネントに適用しないでください:
html,
body,
body {
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: 'build',
ios: {
contentInset: 'never',
},
};
Capacitor の自動コンテンツ inset と CSS を混在させると env(safe-area-inset-*) paddingが原因で、余白が二重に見えることがよくあります。
実際にオーバーフローしている要素を特定しましょう
主な原因は、以下の要素を使用している場合です: 100vw、Tailwind 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 は、既存のWebプロジェクトをベースにネイティブアプリを構築するのに最適な選択肢です。code を簡単に共有でき、一貫したUIを維持できます。
さらに、 Capgoを活用することで、アプリへの Live Update の追加がより簡単になります。これにより、ユーザーは常に最新の機能やバグ修正を利用できるようになります。
SvelteKitアプリに Capgo を導入する方法については、次の記事をご覧ください:
Capgo を使って、より高品質なアプリをより速く開発する方法を学びましょう。 無料アカウントの登録は こちらから。
SvelteKitとCapacitorによるモバイルアプリ開発から
使用している場合 SvelteKitとCapacitorによるモバイルアプリ開発 CI/CD自動化の計画、および以下との連携へ Capgo CI/CD Capgo CI/CDのプロダクトワークフロー Capgo Native Build Capgo Native Buildsのプロダクトワークフロー Capgo 連携機能 Capgo Integrationsのプロダクトワークフロー CI/CD 連携 CI/CD Integrationの実装詳細について GitHub Actions 連携 GitHub Actions Integration の実装の詳細についてはこちらをご覧ください。