优先检查 shouldRasterize 和 opaque:设 webView.layer.shouldRasterize = YES、rasterizationScale 为屏幕缩放比,背景设为不透明,禁用 scrollView.bounces,加 CSS 禁用高亮与选中,ECharts 用 canvas 渲染,本地 HTML 改用 loadHTMLString 加载,WebGL 资源需同域或内联,Three.js 启用 antialias: false 和 low-power。
shouldRasterize 和 opaque
iOS 上用 WKWebView 展示 HTML5 可视化(比如 ECharts、D3 或 Three.js)时,滚动/缩放/动画卡顿,大概率不是 JS 性能问题,而是图层合成没配对。原生侧若没显式开启光栅化或设错透明度,系统会频繁重绘离屏内容。
实操建议:
webView.layer.shouldRasterize = YES,并搭配 webView.layer.rasterizationScale = [UIScreen mainScreen].scale
webView.backgroundColor = UIColor.whiteColor,且确保 HTML 无透明背景(避免触发半透明合成)webView.scrollView.bounces = NO(弹性回弹会强制触发额外 layout)webkit-tap-highlight-color 和 user-select
HTML 页面里带交互的可视化(如可拖拽图表),iOS 默认会插入点击高亮、长按选中文本等合成层,这些和 Canvas 渲染争抢 GPU 资源。尤其在 requestAnimationFrame 循环中,哪怕只是 CSS 伪类重绘

必须加的 CSS:
body {
-webkit-tap-highlight-color: transparent;
-webkit-user-select: none;
user-select: none;
touch-action: manipulation; /* 阻止双指缩放干扰 */
}注意:如果用了 ECharts,还要在初始化时设 renderer: 'canvas'(别用 svg,iOS 上 SVG 合成开销更大)
loadFileURL:allowingReadAccessToURL: 直接读 bundle很多方案让 JS 从 bundle 读取 HTML + JS + 图片,看似省网络,但 iOS 对沙盒内 file:// 协议的资源加载有隐式安全检查,每次 fetch 或 new Image() 都会触发 IPC,可视化动辄上百个资源请求,延迟直接拉满。
更稳的路径:
mainBundle,用 loadHTMLString:baseURL: 加载,baseURL 设为 [NSBundle mainBundle].bundleURL
data: URI 内联(适合小于 10KB 的图标/小图)file:///var/.../xxx.png 这种硬编码路径limitsNavigationsToAppBoundDomains 和 Metal 后备iOS 16+ 对 WKWebView 的 WebGL 限制变严,若页面含跨域资源(比如 CDN 上的 glsl 着色器、纹理贴图),即使 CORS 允许,limitsNavigationsToAppBoundDomains = YES(默认值)也会拦截,导致 WebGLRenderingContext 创建失败,进而触发降级到 CPU 渲染,发热卡顿。
处理方式:
WKWebViewConfiguration 中设 limitsNavigationsToAppBoundDomains = NO,并配置 App Attest 或关联域名(否则上架被拒)antialias: false 和 powerPreference: 'low-power',iOS GPU 降频比你想象中更激进真正难调的是混合渲染场景——比如 Canvas 上叠了原生按钮,又开了 WKWebView 的 allowsInlineMediaPlayback,这时候图层树一乱,再好的 JS 也救不回 12fps。得用 Xcode 的 Debug View Hierarchy 实时看 layer 切片,而不是盯着 Chrome DevTools 里的 FPS 数字。