跳过主要内容
教程

Building Mobile Apps with React and Capacitor

Learn how to build a mobile app using React, Capacitor, and add Capgo Native Navigation, Transitions, and iOS layout best practices.

文章来源

马丁·多纳迪厄

作者

瓦莱里亚

审稿人

乔丹

编辑器

Building Mobile Apps with React and Capacitor

在本教程中,我们将从新建一个 React app and transition to native mobile development using Capacitor. You can also add Capgo Native Navigation and Transitions for a native mobile feel, and use tailwind-capacitor for safe areas.

Capacitor allows you to easily convert your React web application into a native mobile app without significant modifications or learning a new skill like React Native.

只需几步,几乎所有 React 应用都可以转换为移动应用。

This tutorial will guide you through the process, starting with a new React app and then incorporating Capacitor to move into the realm of native mobile apps. You can also use Capgo Native Navigation, Transitions, and tailwind-capacitor for safe areas.

About Capacitor

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

With Capacitor, you get a fantastic native mobile app without any complicated setup or steep learning curve. Its slim API and streamlined functionality make it a breeze to integrate into your project. Trust me, you’ll be amazed at how effortless it is to achieve a fully functional native app with Capacitor!

准备您的 React 应用

虽然有多种方法来启动 React 应用,但本教程中我们将使用最简单的方法,提供一个空白的 React 应用:

npx create-react-app my-app

为了创建一个原生移动应用,我们需要一个 export 的项目。因此,让我们在我们的 package.json 中添加一个简单的脚本,可以用来构建和导出 React 项目:

{
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
}

您现在可以无忧无虑地 npm run build ,并且应该能够在项目根目录看到一个新鲜的

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

Adding Capacitor to Your React App

将 Capgo 添加到您的 React 应用中 sync 将任何 Web 应用打包到原生移动容器中,我们必须遵循几个初始步骤,但之后只需执行一个单独的

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

接下来,我们需要安装核心包和iOS和Android平台的相关包。

最后,我们可以添加平台,Capacitor会在项目根目录创建每个平台的文件夹:

# Install the Capacitor CLI locally
npm install -D @capacitor/cli

# Initialize Capacitor in your React 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

到目前为止,您应该能够观察到新的 ioscontext android

文件夹在您的React项目中。

这些是真正的本机项目! Android Studio. For iOS, you need a Mac and should install Xcode.

Additionally, you should find a capacitor.config.ts 文件中包含一些基本的Capacitor设置,这些设置在同步过程中会被使用。您需要注意的是 webDircontext

,它必须指向您的构建命令的结果。目前它是不准确的。 capacitor.config.json __CAPGO_KEEP_0__.config.json 文件并更新:

{
  "appId": "com.example.app",
  "appName": "my-app",
  "webDir": "out",
  "bundledWebRuntime": false
}

您可以通过执行以下命令来尝试它:

npm run build
npx cap sync

第一个命令 npm run build 将仅仅构建您的React项目并导出静态构建。

而第二个命令 npx cap sync 将同步所有的web code 到native平台的正确位置,以便它们可以在应用中显示。

此外,同步命令可能会更新native平台并安装插件,因此当您安装新的 Capacitor 插件时 npx cap sync 需要重新运行

命令。

您可能已经不经意间完成了,所以让我们在设备上看看应用!

构建和部署原生应用程序需要在开发iOS应用程序时需要 Xcode 已安装,并且对于 Android 应用,您需要安装 Android Studio 已安装。另外,如果您打算在应用商店上发布您的应用,则需要在 iOS 中注册 Apple Developer Program,在 Android 中注册 Google Play Console。

如果您是新手,native mobile 开发,您可以使用 Capacitor CLI 来轻松打开两个 native 项目:

npx cap open ios
npx cap open android

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

android-studio-run

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

xcode-run

恭喜!您成功部署了 React web 应用到移动设备。以下是示例:

react-mobile-app

但是,请稍等,有更快的方法可以在开发期间完成此操作…

Capacitor 实时重载

到目前为止,你可能已经习惯了所有现代框架都具有热重载的功能,好消息是你可以轻松地在移动设备上实现相同的功能。 在移动设备上 轻松实现!

通过实时重载,允许你在本地网络上访问你的应用 通过让 __CAPGO_KEEP_0__ app 从特定的 URL 加载内容。 by having the Capacitor app load the content from the specific URL.

在 Windows 上运行:

ipconfig getifaddr en0

然后查找 IPv4 地址。

ipconfig

我们可以通过在我们的文件中添加另一个条目来指示 __CAPGO_KEEP_0__ 直接从服务器加载应用:

We can instruct Capacitor to load the app directly from the server by adding another entry to our capacitor.config.ts entry:

import { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.example.app',
  appName: 'my-app',
  webDir: 'out',
  bundledWebRuntime: false,
  server: {
    url: 'http://192.168.x.xx:3000',
    cleartext: true
  }
};

export default config;

请确保使用 正确的IP和端口,我在本例中使用了默认的React端口。

现在,我们可以将这些更改应用到我们的原生项目中:

npx cap copy

命令与 copy 类似,但它只会 sync将对web文件夹和配置的更改复制到原生项目中,而不更新原生项目。 您现在可以通过Android Studio或Xcode再次部署您的应用程序。随后,如果您在React应用程序中更改了什么内容, 应用程序将自动重新加载

并显示更改! 请注意: 命令与上述命令类似,但它只会将对web文件夹和配置的更改复制到原生项目中,而不更新原生项目。

请注意 如果您安装了新插件,如摄像头插件,它仍然需要重新构建您的原生项目。这是因为原生文件已更改,无法在飞行中完成。

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

使用Capacitor插件

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

npm i @capacitor/share

没有什么特别的关于 分享插件,但它仍然会弹出原生分享对话框!因此,我们现在只需要导入包并从我们的应用程序中调用 share() 函数。让我们将 src/App.js 修改为

import React from 'react';
import { Share } from '@capacitor/share';

function App() {
  const share = async () => {
    await Share.share({
      title: 'Open Youtube',
      text: 'Check new video on youtube',
      url: 'https://www.youtube.com',
      dialogTitle: 'Share with friends'
    });
  };

  return (
    <div>
      <h1>Welcome to React and Capacitor!</h1>
      <p>
        <h2>Cool channel</h2>
        <button onClick={() => share()}>Share now!</button>
      </p>
    </div>
  );
}

export default App;

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

npx cap sync

点击按钮后,您可以看到美丽的原生分享对话框在行动!

react-capacitor-share

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

原生感知UI与Capgo原生导航和过渡

我已经工作了几年, Ionic 来构建跨平台应用,但将其与React集成起来很hacky,并且很少值得一试,因为您已经有 Tailwind CSS.

在一个React + Capacitor应用中,为了获得原生移动感受,使用Capgo插件而不是像Konsta UI这样的仅限Web UI套件:

  • @capgo/capacitor-native-navigation ——原生导航栏、Liquid Glass iOS标签栏和Android模糊标签栏样式。您的React路由器保留路由状态;插件拥有原生浏览器。
  • @capgo/capacitor-transitions — Ionic-style page transitions and iOS edge swipe-back in the WebView layer, without adopting 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',
  },
});

渲染液态玻璃标签栏(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 }) => {
  navigate(`/${id}`);
});

在应用壳中添加原生页面过渡:

import { useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import '@capgo/capacitor-transitions';
import { initTransitions, setDirection, setupRouterOutlet } from '@capgo/capacitor-transitions/react';

initTransitions({ platform: 'auto' });

export function AppShell() {
  const navigate = useNavigate();
  const outletRef = useRef<HTMLElement>(null);

  useEffect(() => {
    if (outletRef.current) {
      setupRouterOutlet(outletRef.current, { platform: 'auto', swipeGesture: 'auto' });
    }
  }, []);

  const openSettings = () => {
    setDirection('forward');
    navigate('/settings');
  };

  return <cap-router-outlet ref={outletRef}>{/* routes */}</cap-router-outlet>;
}

Wrap routed pages in cap-router-outlet, cap-page,和 cap-content,并调用 setDirection('forward')setDirection('back') 在 Capacitor live-update 替代方案比较页面中见到:

在 Appflow 比较/迁移营销复制中见到: Using @capgo/capacitor-native-navigation@capgo/capacitor-transitions.

安全区域

在Tailwind CSS中,使用 @capgo/tailwind-capacitor (发布于 tailwind-capacitor @npm safe-areas utilities and other Capacitor-friendly Tailwind plugins:

bun add -D tailwind-capacitor

@__CAPGO_KEEP_0__ src/index.css:

@import 'tailwindcss';
@plugin "@capgo/tailwind-capacitor/platform";
@plugin "@capgo/tailwind-capacitor/safe-areas";

友好的Tailwind插件: pt-safe, pb-safepx-safe 使用类似于 env(safe-area-inset-*) 手动配置。该项目正在积极开发中 — 如果您的 React 设置中缺少某些内容,请 在 GitHub 上提交 PR.

修复 iOS 布局问题(视口、安全区域和水平溢出)

如果 iOS 内容看起来被裁切、偏移或水平滚动,请尝试 overflow-x: hidden 或仅仅调整视口标签通常无法解决问题。按照以下顺序检查这些问题。

确保视口元标签已正确应用

index.html 添加视口元标签 <head>:

<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />

仅从根包装器中处理 iOS 安全区域

html,
body,
#root {
  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将所有页面内容包装在 . 中:

With @capgo/tailwind-capacitor,你可以使用类似于 pt-safe pb-safe px-safe on that single shell.

设置CapacitoriOS contentInsetnever 首先

In capacitor.config.ts,优先使用原生边距禁用并让CSS(或Native Navigation的) contentInsetMode: 'css')来控制安全区域:

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

混合Capacitor的自动内容边距与CSS env(safe-area-inset-*) padding是双倍间距的常见原因。

找到真实的溢出元素

通常的罪魁祸首是使用 100vw, Tailwind w-screen, 固定像素宽度,或一个大 min-width.

In 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 with w-full 可能的时。许多水平溢出问题来自 100vw / w-screen, 重复的安全区域填充,或一个固定宽度容器 —— 不是来自视口元标签本身。

结论

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

并且通过添加 Capgo让您的应用程序拥有实时更新功能,使您的用户始终能够访问最新的功能和bug修复。

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

继续阅读《使用React和Capacitor构建移动应用》

如果您正在使用 《使用React和Capacitor构建移动应用》 来规划CI/CD自动化,连接它与 Capgo CI/CD 为Capgo CI/CD中的产品工作流程 Capgo Native Builds 为Capgo Native Builds中的产品工作流程 Capgo Integrations 为Capgo产品工作流程中的集成 CI/CD集成 为CI/CD集成中的实现细节 GitHub动作集成 为GitHub动作集成中的实现细节

Capacitor 应用程序的即时更新

当 web-layer 错误处于活跃状态时,通过 Capgo 将修复推送到应用程序,而不是等待几天的应用商店审批。用户在后台接收更新,而本机更改保持在正常审批路径中。

来自 Martin 的人性化支持

立即开始

最新博客文章

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