跳过主要内容
Tutorial

使用SvelteKit和Capacitor构建移动应用

了解如何使用SvelteKit、Capacitor和优化Capgo原生导航、过渡和iOS布局最佳实践来构建一个移动应用

Martin Donadieu

Martin Donadieu

内容营销人员

使用SvelteKit和Capacitor构建移动应用

在本教程中,我们将从一个新的 SvelteKit 应用开始,转向使用Capacitor进行原生移动开发。您还可以添加Capgo原生导航和过渡以获得原生移动体验,并使用tailwind-capacitor来安全区域。

Capacitor使您能够轻松将SvelteKit Web应用转换为原生移动应用,无需进行重大修改或学习新的技能,如React Native。

按照此步骤指南,将您的 SvelteKit 应用程序转换为使用 Capacitor 的移动应用程序,支持 Capgo 的原生导航、过渡和 iOS 布局指南。

关于 Capacitor

CapacitorJS 是一个革命性的工具!它可以轻松地集成到任何 web 项目中,将您的应用程序包装在一个原生 webview 中,并为您生成 native Xcode 和 Android Studio 项目。其插件提供访问原生设备功能的 JavaScript 桥,如摄像头。

Capacitor enables you to create a fantastic native mobile app without any complicated setup or steep learning curve. Its slim API and streamlined functionality make it easy to integrate into your project. You’ll be amazed at how simple it is to achieve a fully functional native app with Capacitor!

为 SvelteKit 应用程序做准备

要创建一个新的 SvelteKit 应用程序,请运行以下命令:

npm create svelte@latest my-app
cd my-app
npm install
npm run build

运行命令后,您应该在项目根目录看到一个新文件夹。 build 此文件夹将由 __CAPGO_KEEP_0__ 后续使用,但现在我们需要正确设置它。 dist 将 __CAPGO_KEEP_0__ 添加到您的 SvelteKit 应用程序中

This folder will be used by Capacitor later, but for now, we need to set it up correctly.

Adding Capacitor to Your SvelteKit App

__CAPGO_KEEP_0__ sync command.

首先,安装 Capacitor CLI 作为开发依赖项并在项目中设置它。在设置过程中,您可以按“回车”键以接受名称和包ID的默认值。

接下来,安装核心包和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项目中看到新的 iosandroid 文件夹。这些是真正的本机项目!

ios folder is a real native project!

为了以后访问 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设置,让我们将Sveltekit项目更改为静态应用程序,通过下载适当的静态适配器包:

npm i -D @sveltejs/adapter-static

安装包后,我们需要修改 svelte.config.js 文件从自动适配器更改为静态:

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 并且只需在"+layout.js"文件中添加以下内容: 在添加和更新"+layout.js"文件后,我们需要添加我们的移动平台,重新构建项目以创建"build"文件夹::

export const prerender = true

您可以通过运行以下命令来完成: 第一个命令 将会构建您的SvelteKit项目并复制静态构建,而第二个命令 将同步所有的web __CAPGO_KEEP_0__ 到native平台的正确位置,以便在app中显示。 第一个命令会构建您的SvelteKit项目并复制静态构建,而第二个命令会同步所有的web __CAPGO_KEEP_0__ 到native平台的正确位置,以便在app中显示。

第一个命令会构建您的SvelteKit项目并复制静态构建,而第二个命令会同步所有的web __CAPGO_KEEP_0__ 到native平台的正确位置,以便在app中显示。

npm run build
npx cap sync

第一个命令会构建您的SvelteKit项目并复制静态构建,而第二个命令会同步所有的web __CAPGO_KEEP_0__ 到native平台的正确位置,以便在app中显示。 npm run build 第一个命令会构建您的SvelteKit项目并复制静态构建,而第二个命令会同步所有的web __CAPGO_KEEP_0__ 到native平台的正确位置,以便在app中显示。 npx cap sync 第一个命令会构建您的SvelteKit项目并复制静态构建,而第二个命令会同步所有的web code 到native平台的正确位置,以便在app中显示。

另外,同步命令可能会更新本机平台并安装插件,因此当您安装新__CAPGO_KEEP_0__插件时,需要重新运行 Capacitor plugins您可能没有意识到,您已经完成了整个过程,所以让我们在设备上看看应用程序! npx cap sync 构建和部署本机应用

为了开发iOS应用,您需要安装

Xcode

,并且为了开发Android应用,您需要安装 Android Studio 。此外,如果您打算将应用程序分发到应用商店,则需要为iOS注册Apple Developer Program,并为Android注册Google Play Console。 如果您是本机移动开发的新手,可以使用__CAPGO_KEEP_0__ __CAPGO_KEEP_1__轻松打开两种本机项目: iOS

If you’re new to native mobile development, you can use the Capacitor CLI to easily open both native projects:

npx cap open ios
npx cap open android

一旦您设置了本地项目,部署应用到连接设备就变得简单了。在 Android Studio 中,只需等待所有内容就绪,然后您就可以在不更改任何设置的情况下将应用部署到连接设备。以下是一个例子:

android-studio-run

在 Xcode 中,您需要设置签名账户才能将应用部署到真实设备,而不是仅仅是模拟器。如果您之前没有这样做过,Xcode 将指导您完成此过程(但请再次注意,您需要注册开发者计划)。之后,您可以简单地点击播放以在连接设备上运行应用,您可以在顶部选择设备。以下是一个例子:

xcode-run

恭喜!您已经成功将 SvelteKit 网络应用部署到移动设备。以下是一个例子:

sveltekit-mobile-app

但等一下,还有更快的方法可以在开发期间完成此操作……

Capacitor Live Reload

到目前为止,您可能习惯于所有现代框架都具有热重载的功能,好消息是您可以在移动设备上实现相同的功能 在移动设备上 只需花费最少的努力!

启用对本地托管应用的访问,使用实时重载 On your network 通过让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和端口 ,如上面的示例所示。现在,我们可以将这些更改应用到我们的原生项目中:

The

npx cap copy

The copy 命令与 sync但它只会 将对 web 文件夹的修改 和配置复制过去,而不更新原生项目。

您可以通过 Android Studio 或 Xcode 再次部署您的应用程序。之后,如果您在 Svelte 应用程序中更改了什么内容, 应用程序将自动重新加载 并显示更改!

请注意 如果您安装了新插件,如摄像头插件,它仍然需要重新构建原生项目。这是因为原生文件被修改,不能在实时进行。

请注意,您应该在配置中使用正确的 IP 和端口。上面的 code 块显示了示例目的地端口。

使用 Capacitor 插件

让我们看看如何使用一个 Capacitor 插件的示例,之前我们提到过几次。要实现这一点,我们可以通过运行以下命令安装一个简单的插件:

npm i @capacitor/share

There’s nothing fancy about the 分享插件,但它会弹出原生分享对话框! 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>

到这个:

npx cap sync

如前所述,当安装新插件时,我们需要执行同步操作,然后重新部署应用到设备上。要实现这一点,请运行以下命令:

Next, you can make the app feel more native on iOS and Android with Capgo navigation and transitions, and fix common iOS layout issues that cause horizontal overflow or cropped safe areas.

接下来,您可以让应用在iOS和Android上感觉更原生,使用Capgo导航和过渡,并修复常见的iOS布局问题,导致水平溢出或裁切安全区域。

原生感知UI与__CAPGO_KEEP_0__原生导航和过渡 我已经与Ionic工作了多年 为了在 SvelteKit 中构建跨平台应用,但将其与 SvelteKit 集成起来是hacky且不值得的,尤其是当你已经有 Tailwind CSS.

在 SvelteKit + Capacitor 应用中,使用 Capgo 插件来实现原生移动体验,而不是使用像 Konsta UI 这样的仅限 web UI 套件:

  • @capgo/capacitor-native-navigation — 原生导航栏、Liquid Glass iOS tab栏和 Android 模糊 tab栏样式。你的 SvelteKit 路由器保留了路由状态;插件拥有原生浏览器。
  • @capgo/capacitor-transitions — 在 WebView层中实现Ionic样式页面过渡和iOS边缘滑动返回,且不需要采用Ionic UI。

安装两者:

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 tab栏(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-本机导航使用@capgo/capacitor-过渡.

安全区域与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-safepx-safeenv(safe-area-inset-*) 而不是手动添加 open a PR on GitHub.

在 __CAPGO_KEEP_0__ 上打开一个 PR

iOS 布局问题(视口、安全区域和水平溢出) overflow-x: hidden 如果内容看起来被裁剪、偏移或水平滚动在 iOS 上,添加更多

或调整视口标签通常无法解决问题。按照以下顺序检查这些问题。

In src/app.html, 在设置视口元标签时 <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。在头部、模态对话框和布局包装器中重复设置安全区域填充通常会使 UI 看起来被裁剪或过大。

使用 @capgo/tailwind-capacitor,您可以使用类似于 pt-safe pb-safe px-safe 的工具表达相同的填充。

设置 Capacitor iOS contentInset 安全区域 never first

In capacitor.config.ts, prefer native inset disabled and let CSS (or Native Navigation’s contentInsetMode: 'css') own the safe area:

const config: CapacitorConfig = {
  appId: 'com.example.myapp',
  appName: 'my-app',
  webDir: 'build',
  ios: {
    contentInset: 'never',
  },
};

Mixing Capacitor’s automatic content inset with CSS env(safe-area-inset-*) padding is a common cause of double spacing.

Find the real overflowing element

The usual culprit is an element using 100vw, Tailwind w-screen, a fixed pixel width, or a large min-width.

In Safari Web Inspector, run:

[...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,
  }));

With Tailwind, replace w-screen 当可能时 w-full 水平溢出问题通常来自 100vw / w-screen、重复的安全区域填充或固定宽度容器,而不是viewport meta标签本身。

结论

Capacitor 是基于现有 web 项目构建原生应用的优秀选择,提供了一个简单的方式来共享 code 并保持一致的 UI。

并且, Capgo 使得添加实时更新到您的应用程序变得更加容易,从而确保您的用户始终可以访问最新的功能和 bug 修复。

如果您想学习如何将 Capgo 添加到您的 SvelteKit 应用程序中,请查看下一篇文章:

了解 Capgo 如何帮助您快速构建更好的应用程序, 注册免费账户 今天。

继续使用 Building Mobile Apps with SvelteKit 和 Capacitor

如果您正在使用 Building Mobile Apps with SvelteKit 和 Capacitor 来规划 CI/CD 自动化,连接它与 Capgo CI/CD 为产品工作流程在 Capgo CI/CD 中 Capgo 原生构建 为产品工作流程在 Capgo 原生构建中 Capgo 集成 为产品工作流程在 Capgo 集成中 CI/CD 集成 为 CI/CD 集成的实现细节 GitHub 的操作集成 为 GitHub 操作集成的实现细节。

为 Capacitor 应用提供实时更新

当 web-layer 的 bug 在线时,通过 Capgo 直接将修复推送给用户,而不是等待几天的 app store 审核。用户在后台接收更新,而原生代码仍在正常的审查路径中。

立即开始

最新博客

Capgo 为您提供创建真正专业的移动应用所需的最佳见解。