关于 framework-to-capacitor
为将 Next.js、Nuxt、Vite 等框架项目接入 Capacitor 的开发者提供配置指导,重点是生成可复制的静态资源并打通构建与同步流程。还涵盖服务端功能限制、路由和深度链接问题的处理。
主要功能
- 01配置框架生成静态构建
- 02设置 Capacitor webDir
- 03串联构建与 cap sync
- 04排查路由和深度链接
- 05识别运行时服务端功能限制
适用场景
- 01修复 cap sync 找不到 index.html
- 02让框架项目构建为移动端静态资源
- 03排查应用白屏或重载路由错误
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ cap-go/ capgo-skills --skill framework-to-capacitor安装后在 Claude Code 中输入/framework-to-capacitor确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
metadata.jsonreferences/angular.mdnextjs.mdother-frameworks.mdreact.mdsvelte.mdvue-nuxt.md详细介绍
将框架接入 Capacitor
让框架生成静态构建包,供 Capacitor 复制到原生项目中,并配置脚本,将 build -> cap sync 合并为一步。
适用场景
在以下情况使用:
- 将 Capacitor 添加到 Next.js、Nuxt、Angular、SvelteKit、Vite(React/Vue/Svelte/Solid)、React Router、Qwik 或 Astro 项目。
npx cap sync失败,并提示The web assets directory (./dist) must contain an index.html file.或Could not find the web assets directory: ./dist.- 应用启动后显示白屏,或在重新加载或打开深层链接后加载了错误页面。
- 框架构建因仅支持 SSR 的功能而失败(例如
output: 'export'错误、prerender错误、API 路由、中间件、服务端操作)。
以下情况不要使用:
- 商店就绪情况、原生体验、权限、账单、审核风险 →
webapp-to-capacitor、capacitor-app-store、capacitor-apple-review-preflight。 - Cordova/PhoneGap 应用 →
cordova-to-capacitor。 - Capacitor 版本升级 →
capacitor-app-upgrades。 - 实时更新设置 →
capgo-live-updates。
当前项目概况
检测到的框架和构建依赖:
!node -e "const fs=require('fs');if(!fs.existsSync('package.json'))process.exit(0);const pkg=JSON.parse(fs.readFileSync('package.json','utf8'));const matchers=['next','nuxt','react','react-router','@react-router/dev','vue','@angular/core','@angular/build','@sveltejs/kit','@sveltejs/adapter-static','@builder.io/qwik','@qwik.dev/core','astro','@remix-run/react','solid-js','@solidjs/start','vite','@capacitor/core','@capacitor/cli'];const out=[];for(const section of ['dependencies','devDependencies']){for(const [name,version] of Object.entries(pkg[section]||{})){if(matchers.includes(name))out.push(section+'.'+name+'='+version)}}for(const [name,cmd] of Object.entries(pkg.scripts||{})){if(['build','export','generate','sync','cap:sync'].includes(name))out.push('scripts.'+name+'='+cmd)}console.log(out.join('\n'))"
相关框架和 Capacitor 配置路径:
!find . -maxdepth 3 -not -path '*/node_modules/*' \( -name 'next.config.*' -o -name 'nuxt.config.*' -o -name 'vite.config.*' -o -name 'angular.json' -o -name 'svelte.config.*' -o -name 'react-router.config.*' -o -name 'astro.config.*' -o -name 'capacitor.config.json' -o -name 'capacitor.config.ts' -o -name 'capacitor.config.js' \)
核心事实(适用于所有框架)
- Capacitor 会将
webDir复制到原生应用中。它不会运行 Node。运行时不存在 SSR、API 路由、中间件、ISR、服务端操作、cookies()/headers()和图片优化服务器。请将这些功能迁移到托管后端,并通过 HTTPS 调用。 - 应用通过
capacitor://localhost(iOS)和https://localhost(Android)提供服务。后端必须允许这些来源进行 CORS,或使用CapacitorHttp。 - 对于任何没有文件扩展名的路径,Capacitor 本地服务器都会返回根目录的
index.html。基于 History 模式的 SPA 路由(createWebHistory、BrowserRouter、Angular 默认的PathLocationStrategy)可以正常工作;无需使用哈希路由。 - 同一回退机制意味着,带有逐路由 HTML 文件的页面(Next.js 导出、SvelteKit 预渲染、Astro)不会通过无扩展名的 URL 提供。冷启动或执行
location.reload()访问/settings/时,会加载根目录的index.html。请让导航在客户端完成,并通过App.addListener('appUrlOpen', ...)和路由器处理深层链接。 - 资源路径:框架的基础路径保持为
/(Vite 的base、Angular 的<base href="/">,Next 的basePath/assetPrefix不要设置)。用于 Web 托管的 CDN 或子路径基础路径会导致应用无法加载资源;请使用单独的移动端构建配置。 - 环境变量会在构建时内联(Next.js 的
NEXT_PUBLIC_*、Vite 的VITE_*、Nuxt 的NUXT_PUBLIC_*、SvelteKit 的PUBLIC_*、Angular 的environment.ts)。每次执行cap sync前都要重新构建;生产构建切勿指向localhost。 - Capacitor 8 需要 Node 22+。Capacitor 9(目前为
@next,尚未正式发布)需要 Node 24+。一些框架的大版本也会提高 Node 最低版本要求(SvelteKit 3:Node 22.17+)。
流程
- 阅读快照,确定框架、主版本和当前构建输出目录。如果单体仓库中包含多个应用,请询问哪个应用会发布到移动端。
- 加载匹配的参考文档(仅加载正在使用的那份):
package.json 中的框架 | 加载 | webDir |
|---|---|---|
next | references/nextjs.md | out |
nuxt | references/vue-nuxt.md | .output/public |
vue + vite(无 Nuxt) | references/vue-nuxt.md | dist |
react + vite、react-router/@react-router/dev、CRA | references/react.md | dist、build/client 或 build |
@angular/core | references/angular.md | dist/<project>/browser |
@sveltejs/kit 或 svelte + vite | references/svelte.md | build 或 dist |
solid-js、@builder.io/qwik/@qwik.dev/core、astro、@remix-run/* | references/other-frameworks.md | 不固定 |
- 更改配置前,盘点仅在服务端运行的功能(搜索
app/api/、pages/api/、middleware.ts/proxy.ts、'use server'、getServerSideProps、+page.server.ts、+server.ts、server/api/、@angular/ssr)。向用户报告清单,并在删除任何内容前,就每项功能的迁移去向达成一致(外部 API、客户端请求或原生插件)。 - 确保静态构建正常运行,并检查输出目录:其根目录下必须包含
index.html。 - 安装并初始化 Capacitor(安装时使用仓库的包管理器):
npm install @capacitor/core @capacitor/ios @capacitor/android
npm install -D @capacitor/cli
npx cap init "App Name" com.company.app --web-dir <webDir>
npx cap add ios
npx cap add android
- 添加一个始终先构建再同步的脚本,例如
"build:mobile": "<framework build> && cap sync"。 - 在两个平台上运行以下验证。
最小配置(Capacitor 6 起,androidScheme: 'https' 为默认值;仅在需要保留旧版源时设置):
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.company.app',
appName: 'App Name',
webDir: 'dist',
};
export default config;
实时重载
Capacitor 8:npx cap run ios -l --host <LAN-IP> --port <port>。Capacitor 9:npx cap run ios --url http://<LAN-IP>:<port>(-l/--host/--port/--https 标志已合并到 --url 中)。开发服务器必须监听局域网(在 Vite 中使用 --host 0.0.0.0 / server.host: true)。切勿将 server.url 提交到 capacitor.config.* 中。
验证
npm run build
test -f <webDir>/index.html && echo "index.html OK"
npx cap sync
npx cap run ios # or open in Xcode
npx cap run android
然后在设备/模拟器上:
- 应用打开后应显示首屏,启动画面之后不应出现白屏闪烁。
- 导航到嵌套路由,再将应用切到后台并恢复,确认路由仍然保留。
- 打开深层链接(
xcrun simctl openurl booted <url>/adb shell am start -a android.intent.action.VIEW -d <url>),确认其跳转到正确的屏幕。 - 检查 WebView(Safari Web Inspector /
chrome://inspect),查看 JS/CSS 是否出现 404,以及是否存在 CORS 错误。 grep -rn "localhost:\|127.0.0.1" <webDir>不应返回任何意外结果。
错误处理
| 症状 / 错误 | 原因 | 解决方法 |
|---|---|---|
The web assets directory (./dist) must contain an index.html file. | webDir 指向了错误的文件夹,或 SSR 构建没有 index.html | 将 webDir 设置为上文列出的静态输出目录;启用静态 / SPA 模式 |
Could not find the web assets directory: ./out. | 尚未运行构建,或输出目录不同 | 先运行构建;将 webDir 与实际文件夹保持一致 |
白屏,控制台提示 Failed to load resource,涉及 /_next/... 或 /assets/... | 非根路径 base path / CDN assetPrefix | 移动端构建使用 / 作为 base |
| 白屏,没有 404 | 启动时出现 JS 错误(通常是预渲染期间使用了 window / document,或导入了仅限 SSR 的模块) | 检查 WebView 控制台;为仅限浏览器的代码添加保护 |
| 重新加载或深层链接打开主页,或出现 hydration 错误 | Capacitor 会将扩展名缺失的路径映射到根目录的 index.html | 使用客户端导航和 appUrlOpen 处理程序;参见框架参考 |
Page "/x/[id]" is missing "generateStaticParams()"(Next.js) | 导出模式下使用了动态路由 | 预生成参数,或改用查询字符串 / 客户端路由 |
Image Optimization using the default loader is not compatible with output: export | 使用了 next/image 默认加载器 | 设置 images.unoptimized: true 或使用自定义加载器 |
| API 调用在浏览器中正常,在设备上失败 | capacitor://localhost / https://localhost 的 CORS 问题,或 URL 中写入了 localhost | 在后端允许相应来源,或启用 CapacitorHttp;修正环境变量 |
参考资料
references/nextjs.md- Next.js 14-16 静态导出、App Router 陷阱、动态路由、图片。references/react.md- Vite React、React Router 框架 SPA 模式、CRA 旧版用法。references/vue-nuxt.md- Vue + Vite、Nuxt 4 SPA generate。references/angular.md- Angular 17+ application builder 输出、移除 SSR。references/svelte.md- 使用 adapter-static 的 SvelteKit 2 和 3、纯 Svelte + Vite。references/other-frameworks.md- Solid、Qwik、Astro、Remix v2。
相关技能:webapp-to-capacitor(商店就绪)、capacitor-deep-linking、safe-area-handling、capgo-live-updates。