在本教程中,我们将从一个新的 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可以轻松将您的React Web应用转换为原生移动应用,无需进行重大修改或学习新的技能,如React Native。
仅需几步,绝大多数 React 应用程序都可以转换为移动应用。
本教程将指导您完成整个过程,首先使用一个新的 React 应用程序,然后将其整合到 Capacitor 中,以进入原生移动应用的领域。您还可以使用 Capgo Native Navigation、Transitions 和 tailwind-capacitor 来实现安全区域。
关于 Capacitor
CapacitorJS 是一个革命性的工具!您可以轻松将其整合到任何 web 项目中,它会将您的应用程序包装在一个原生 webview 中,生成原生 Xcode 和 Android Studio 项目。其插件还提供了访问原生设备功能的 JS 桥,如摄像头。
使用 Capacitor,您可以获得一个无需复杂设置或陡峭学习曲线的精美原生移动应用。其轻薄 API 和流畅的功能使其成为轻松整合到项目中的理想选择。相信我,您将惊叹于如何轻松地使用 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 这个文件夹将由Capacitor稍后使用,但现在我们必须正确地设置它。
This folder will be used by Capacitor later on, but for now, we must set it up correctly.
Adding Capacitor to Your React App
首先,我们可以将Capacitor作为开发依赖项安装,然后在项目中设置它。在设置过程中,您可以按“回车”键以接受名称和包ID的默认值。 sync 接下来,我们需要安装核心包和iOS和Android平台的相关包。
最后,我们可以添加平台,Capacitor将在项目根目录中为每个平台创建文件夹: Capacitor CLI __CAPGO_KEEP_0__
__CAPGO_KEEP_1__
Finally, we can add the platforms, and Capacitor will create folders for each platform at the root of our project:
# 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
原生移动容器 ios 和 android 项目文件夹
这些是真正的原生项目!
要访问 Android 项目,稍后您必须安装 Android Studio对于 iOS,您需要一台 Mac,并且应该安装 Xcode.
此外,您应该找到一个 capacitor.config.ts 文件在您的项目中,这些文件包含一些基本的Capacitor设置,在同步过程中使用。您需要注意的是 webDir, 必须指向您的构建命令的结果。当前,结果不准确。
为了纠正这个问题,请打开 capacitor.config.json 文件并更新 webDir:
{
"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 到原生平台的正确位置,以便在应用中显示。
此外,同步命令可能会更新原生平台并安装插件,当您安装新 Capacitor 插件 已经是时候运行了 npx cap sync 再也不用说了。
没有注意到,你已经完成了,来看看在设备上的应用吧!
构建和部署原生应用
为了开发 iOS 应用,你需要安装 Xcode ,而为了开发 Android 应用,你需要安装 Android Studio 。另外,如果你打算在应用商店上发布你的应用,你需要在 iOS 上注册 Apple Developer Program,和在 Android 上注册 Google Play Console。
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
__CAPGO_KEEP_0__ __CAPGO_KEEP_1__

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

恭喜!您成功将 React 网页应用部署到移动设备。以下是一个示例:
但请稍等,开发期间还有更快的方法……
Capacitor 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: 'out',
bundledWebRuntime: false,
server: {
url: 'http://192.168.x.xx:3000',
cleartext: true
}
};
export default config;
正确的IP和端口 ,我在这个例子中使用了默认的React端口。现在,我们可以通过将这些更改复制到本地项目中来应用这些更改:
命令与
npx cap copy
在Capacitor中使用 copy 类似 sync但是,仅 将 web 文件夹中的更改复制到 而不更新本机项目的配置
您现在可以通过 Android Studio 或 Xcode 再次部署您的应用程序。随后,如果您在 React 应用程序中更改了什么内容 应用程序将自动重新加载 并显示更改!
请记住 如果您安装了新插件,如摄像头插件,它仍然需要重建本机项目。这是因为本机文件已更改,无法在实时进行。
请注意,您应该在配置中使用正确的 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-__CAPGO_KEEP_0__-share
原生感知 UI 与 Capgo 原生导航和过渡
Native-feeling UI with Capgo Native Navigation and Transitions
Ionic 工作了多年 To 构建跨平台应用,但将其与 React 集成起来很hacky,并且当你已经有了 Tailwind CSS.
For a native mobile feel in a React + Capacitor app, use Capgo plugins instead of web-only UI kits like Konsta UI:
- @capgo/capacitor-native-navigation — 原生导航栏、Liquid Glass iOS tab栏和 Android 模糊 tab栏样式。你的 React 路由器保留了路由状态;插件拥有原生浏览器。
- @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 }) => {
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>;
}
将路由页面包裹在 cap-router-outlet, cap-page,和 cap-content,并且呼叫 setDirection('forward') 或 setDirection('back') 在Capacitor中,
在Capacitor中, Using @capgo/capacitor-native-navigation 在Capacitor中, Using @capgo/capacitor-transitions.
在Capacitor中,
在Capacitor中, @capgo/tailwind-capacitor 在Capacitor中, tailwind-capacitor On npm). 它提供了 safe-areas utilities 和其他 Capacitor-友好的 Tailwind 插件:
bun add -D tailwind-capacitor
In src/index.css:
@import 'tailwindcss';
@plugin "@capgo/tailwind-capacitor/platform";
@plugin "@capgo/tailwind-capacitor/safe-areas";
使用 utilities 如 pt-safe, pb-safe, 和 px-safe 而不是手动添加 env(safe-area-inset-*) 。该项目正在积极开发中 — 如果您的 React 设置缺少某些内容,请在 __CAPGO_KEEP_0__ 上打开一个 PR open a PR on GitHub.
如果内容在 iOS 上看起来被裁切、偏移或水平滚动,仅添加或调整视口标签通常无法解决问题。按照以下顺序检查这些问题。
确保视口元标签已正确应用 overflow-x: hidden pagePath
protectedTokens
添加视口元标签 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中:
重复的安全区域填充在标题、模态窗口和布局包装器中经常会使UI看起来被裁剪或过大。 @capgo/tailwind-capacitor@__CAPGO_KEEP_0__/tailwind-__CAPGO_KEEP_1__ pt-safe pb-safe px-safe ,您可以用类似于
Set Capacitor iOS contentInset 设置__CAPGO_KEEP_0__ iOS到 never 首先
在 capacitor.config.ts, 优先使用原生 inset 并让 CSS (或 Native Navigation 的) contentInsetMode: 'css') 来控制安全区域:
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'dist',
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, 重复的安全区域填充或固定宽度容器 — 而不是来自视口元标签本身。
结论
Capacitor 是基于现有 Web 项目构建原生应用的出色选择,提供了一个简单的方法来共享 code 并维护一致的 UI。
并且,通过添加 Capgo,即使是对应用进行实时更新也变得更加容易,从而确保您的用户始终可以访问最新的功能和 bug 修复。
如果您想学习如何将 Capgo 添加到您的 React 应用中,请查看下一篇文章:
继续阅读 Building Mobile Apps with React 和 Capacitor
如果您正在使用 Building Mobile Apps with React 和 Capacitor 为了计划CI/CD自动化,连接它与 Capgo CI/CD 为产品工作流程在Capgo CI/CD中 Capgo 原生构建 为产品工作流程在Capgo 原生构建中 Capgo 集成 为产品工作流程在Capgo 集成中 CI/CD集成 为__CAPGO_KEEP_0__ 原生构建产品页面中的CI/CD集成功能 GitHub Actions Integration GitHub 动作集成