mcpField
C
capacitor-performance

capacitor-performance

github.com/cap-go开发731.2k 次安装2 周前更新
代码仓库

关于 capacitor-performance

用于诊断和改善 Capacitor 应用性能的技能,面向排查启动缓慢、卡顿、内存增长或原生调用延迟的开发者。它将 WebView、桥接、原生处理和网络分别分析,并强调在真实设备上测量改动效果。

主要功能

  1. 01区分 WebView、桥接、原生与网络瓶颈
  2. 02提供 iOS 和 Android 性能分析参考
  3. 03指导桥接负载与内存用量排查
  4. 04检查启动顺序和监听器清理
  5. 05验证改动前后的性能

适用场景

  1. 01调查设备上的冷启动缓慢
  2. 02诊断卡顿或内存增长
  3. 03减少图像和文件处理延迟
  4. 04判断延迟主要来自原生调用还是网络等待

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cap-go/capgo-skills --skill capacitor-performance

安装后在 Claude Code 中输入/capacitor-performance确认已加载。

附带文件metadata.jsonreferences/profiling.md

详细介绍

Capacitor 性能

先找出瓶颈(WebView JS、桥接层、原生端或网络),再针对具体原因进行修复。通用 Web 建议(代码分割、图片压缩、虚拟列表)仍然适用;本技能侧重于 Capacitor 中的不同之处。

适用场景

触发条件:

  • 冷启动缓慢、启动画面停留时间过长,或首屏空白数秒。
  • 拍照、打开大文件或从后台返回后,应用“重启”或显示白屏。
  • 原生调用感觉缓慢,尤其是处理图片、文件或大型 HTTP 响应时。
  • 仅在设备上出现滚动或动画卡顿(通常是较旧的 Android WebView)。
  • 内存随时间不断增长;监听器越积越多。

不适用场景:

  • 崩溃、原生堆栈跟踪 → debugging-capacitor、capacitor-native-observability。
  • 从设备获取日志 → ios-android-logs。
  • 离线存储设计 / SQLite 迁移 → capacitor-offline-first、sqlite-to-fast-sql。
  • 启动画面配置 → capacitor-splash-screen;键盘调整大小导致卡顿 → capacitor-keyboard。
  • OTA 包体积和增量更新 → capgo-live-updates。

流程

  1. 在真实设备上使用接近发布版本的构建复现问题。 调试构建会记录每次桥接调用并禁用优化;模拟器无法体现内存和 GPU 限制。
  2. 使用下方的性能分析表进行分类:JS 主线程繁忙、桥接负载过大、原生线程繁忙,或正在等待网络。
  3. 检查常见陷阱列表。大多数 Capacitor 特有的性能退化都属于其中一种。
  4. 一次修复一个问题,并使用相同的命令 / 跟踪记录重新测量。 向用户报告修复前后的数据。

性能分析速查表

问题工具
JS 长任务、布局、绘制(iOS)Safari > Develop > device > app > Timelines。发布构建需要设置 ios.webContentsDebuggingEnabled: true(iOS 16.4 及更高版本默认可检查调试构建)。
JS 长任务、内存堆(Android)chrome://inspect > Performance / Memory。
原生 CPU、内存分配、泄漏(iOS)Xcode > Product > Profile > Time Profiler / Allocations / Leaks;在 Xcode Organizer > Metrics 中查看现场数据。
原生 CPU / 内存(Android)Android Studio > Profiler。
Android 冷启动时间adb shell am force-stop <appId> && adb shell am start -W -n <appId>/.MainActivity(读取 TotalTime)。
Android 帧统计adb shell dumpsys gfxinfo <appId>(卡顿帧百分比)。
Android WebView 版本adb shell dumpsys webviewupdate(当前提供程序和版本)。

详情和操作指南:references/profiling.md。

Capacitor 特有陷阱

  1. 通过桥接传输 Base64。 每次插件调用和响应都会通过桥接进行 JSON 序列化。数 MB 的 Base64 字符串会让两个线程都卡住,还可能导致 WebView 进程终止。
    • 相机(@capacitor/camera 8.1+ API):使用 takePhoto / chooseFromGallery 并显示 result.webPath;设置 targetWidth/targetHeight/quality。除非要上传,否则避免读取完整分辨率的 Base64。较旧的 getPhoto / pickImages 已弃用。
    • 文件:传递路径;将 Capacitor.convertFileSrc(uri) 用作 <img>/<video> 的 src;对于大型读取,使用 Filesystem.readFileInChunks;上传和下载使用 @capacitor/file-transfer。
  2. 内存压力下 WebView 进程被终止。 iOS 会记录 WebView process terminated;Capacitor 会重置桥接并重新加载页面,因此内存中的 JS 状态会丢失(看起来像是重启)。Android 会调用 onRenderProcessGone;如果未处理,应用会被终止。降低峰值内存占用(参见陷阱 1、大型画布和解码后的图像),持久化关键状态,并在加载时恢复。
  3. 大响应使用 CapacitorHttp。 设置 plugins.CapacitorHttp.enabled: true 后,fetch/XMLHttpRequest 会通过原生层路由,响应正文也会经过桥接。它非常适合处理 CORS/ Cookie,但大型下载或流式传输会变慢。大文件请使用 file-transfer。
  4. 把 Preferences 当作数据库。 @capacitor/preferences(UserDefaults / SharedPreferences)适用于少量键值数据。大型 JSON 块会被整体读写,导致启动变慢;请使用 SQLite(例如 @capgo/capacitor-fast-sql)。
  5. 发布版本中的日志记录。 loggingBehavior 默认为 debug(仅在调试版本中记录日志)。如果将其设为 production,每次桥接调用都会在发布版本中记录日志;请将其改回 debug 或 none。
  6. 配置中残留开发服务器。 如果发布的构建中 server.url 指向局域网或实时重载服务器,应用就会通过网络加载,离线时无法运行。发布前请移除;在 Capacitor 9 中,使用 npx cap run <platform> --url 进行实时重载,而不是编辑配置。
  7. 旧版 Android System WebView。 性能和 CSS 支持取决于可更新的 WebView,而不是操作系统版本。android.minWebViewVersion(默认值为 60)只会显示错误/server.errorPath,不会更新任何内容。在低端 WebView 上,开销较大的 CSS(backdrop-filter,滚动内容上的大型 box-shadow/filter)会导致卡顿。
  8. 监听器泄漏。 addListener 返回 Promise<PluginListenerHandle>;请等待该 Promise 完成,并在卸载时调用 remove()。每次路由更改都重新注册会导致原生回调成倍增加(appStateChange、keyboardWillShow、地理定位 watchPosition——使用 clearWatch 清除)。
  9. 启动顺序。 仅在首次有意义的内容渲染后隐藏启动画面(launchAutoHide: false + SplashScreen.hide()),并将非关键插件调用(分析初始化、权限检查)延后到首次绘制之后。请注意,Capacitor 9 将 Android launchFadeOutDuration 的默认值从 200 改为 0。
  10. 插件导入不是启动开销。 导入 @capacitor/* 包会创建轻量级代理;其 Web 实现已通过 registerPlugin 延迟加载。请延迟加载开销较大的 JS 库(图表、PDF、地图 SDK JS)和路由。

验证

  • 使用同一设备、同一构建类型对比前后数据:冷启动 TotalTime(Android),或 Instruments App Launch / Organizer 启动时间(iOS),卡顿帧百分比,以及 Allocations/Profiler 中的峰值内存。
  • 对发布配置执行 grep:grep -nE '"url"|loggingBehavior|webContentsDebuggingEnabled' capacitor.config.*,并确认没有开发用的 server.url。
  • 对于陷阱 1,搜索完整大小的 Base64 用法:grep -rnE "resultType: *CameraResultType.Base64|readFile\(|getPhoto\(" src/。
  • 将应用切到后台,打开相机 10 次后返回:页面不得重新加载(iOS),应用不得崩溃(Android)。

错误处理

消息 / 现象含义解决方法
WebView process terminated(Xcode 控制台)WKWebView 内容进程被终止(内存问题)陷阱 1/2:降低峰值内存,持久化状态。
Android logcat 中的 Render process ... gone / 重负载页面加载后应用退出渲染进程崩溃或被终止降低内存使用量;如需恢复,通过 WebViewListener onRenderProcessGone 实现处理逻辑。
ANR in <appId>(logcat)主线程阻塞超过 5 s,通常是繁重的插件工作在 UI 线程上执行在自定义插件中将原生工作移出主线程;使用 Android Studio 进行性能分析。
Message from debugger: Terminated due to memory issueiOS jetsam 终止了整个应用使用 Allocations 工具分析;减少图像解码和缓存。
logcat 报错,提示 WebView 版本低于 minWebViewVersion设备上的 WebView 版本过旧请用户更新 Android System WebView;显示 server.errorPath 页面。

参考资料

仅在需要时加载:

  • references/profiling.md:分步跟踪(Safari Timelines、Chrome Performance、Instruments 模板、Android Profiler、adb 命令)以及如何解读。

评论

支持 Markdown