Skip to content

Stage06|JSB & Native Bridge ​

Lesson078|Web 与 Native 的运行环境为什么不完全一致 ​

Tags: #Creator2.x #Stage06 #Web #Native #PlatformDifficulty: ⭐⭐⭐⭐☆


真实问题:Web 能播音,iOS 无声,应该先改哪一行 ​

Web 浏览器允许用户点击后播放音频;iOS 需要用户手势解锁 Audio Session;Native 文件路径和 Web URL也不是同一语义。

环境差异至少包括:

text
JavaScript Engine
文件系统/沙盒
网络安全与域名
音频会话/权限
GPU/纹理格式
线程与生命周期
基础库/OS版本

一、本课目标 ​

Creator 让业务代码尽量跨平台复用,但“相同 API”只代表抽象接口相同,不代表底层行为、性能和生命周期完全相同。


二、运行时差异 ​

维度WebNative
JS 引擎浏览器提供应用嵌入式运行时
渲染WebGL / 浏览器Native Renderer / 图形 API
文件浏览器沙盒和 Web API应用沙盒和原生文件系统
音频WebAudio / HTML Audio原生音频实现
网络浏览器安全策略原生网络栈或引擎封装
调试DevToolsJS 调试器 + Native 调试器

具体实现随 Creator 版本和平台变化,表格只说明抽象边界。


三、文件系统差异 ​

Web 中通常不能任意访问用户磁盘;Native 中也受到应用沙盒、权限和平台目录约束。

text
资源只读目录
可写目录
缓存目录
临时目录
外部存储或平台共享目录

路径分隔符、编码、大小写和权限都可能不同。不要硬编码桌面开发机绝对路径。


四、JavaScript Engine 差异 ​

不同引擎可能在以下方面不同:

  • 语法支持和 Polyfill。
  • JIT/AOT 能力。
  • GC 策略。
  • 堆内存限制。
  • 异常堆栈格式。
  • 定时器和微任务行为。

构建前应确认目标 Native 运行时支持的 JavaScript 特性,不能只依据当前浏览器。


五、渲染和纹理差异 ​

text
WebGL 能力
Native 图形 API
GPU 驱动
纹理压缩格式
RenderTarget
Shader 编译

同一 Shader 在 Web 预览可运行,Native 设备上仍可能因为精度、扩展、驱动或格式出现差异。


六、网络和安全策略 ​

Web 可能受:

  • CORS。
  • HTTPS Mixed Content。
  • 浏览器缓存。
  • 域名和 Cookie 策略。

Native 可能受:

  • 平台网络权限。
  • 证书和系统版本。
  • App Transport Security 等平台规则。
  • 后台网络限制。

相同 URL 在不同平台失败,需要分别检查平台层错误。


七、生命周期差异 ​

移动 Native 应用可能经历:

text
前台
→ 失去焦点
→ 后台
→ 被系统挂起
→ 恢复
→ 被系统终止

Web 页面也可能隐藏、冻结或被浏览器回收,但事件和资源策略不同。倒计时、音频、网络和资源恢复必须监听对应平台生命周期。


八、调试策略 ​

text
先在 Web 快速验证业务逻辑
→ Native 构建验证平台分支
→ 目标设备复现
→ 同时收集 JS 日志和 Native 日志
→ 必要时使用 C++ 断点和符号

“Web 正常”只能缩小范围,不能结束排查。


九、案例:Web 音频正常,iOS 无声 ​

排查层次:

text
AudioClip 是否加载
→ Creator Audio API 参数
→ Native Audio Binding
→ iOS 音频会话和静音策略
→ 前后台恢复
→ 设备音量和权限

如果问题只出现在 Native,优先比较平台适配和生命周期,而不是重写全部业务逻辑。


十、常见误区 ​

误区一:跨平台 API 保证完全相同行为 ​

它提供共同抽象,平台限制仍然存在。

误区二:浏览器支持的 JavaScript 语法 Native 一定支持 ​

要看嵌入式 JS Engine 版本和构建转换。

误区三:Native 可以任意访问文件系统 ​

应用沙盒和平台权限仍然限制路径。

误区四:模拟器能代替真机性能测试 ​

GPU、内存、驱动和生命周期差异很大。


十一、练习与答案 ​

  1. Web 与 Native 至少有哪些运行时差异?
  2. 为什么不能硬编码开发机文件路径?
  3. Web Shader 正常但 Native 异常,应检查什么?
  4. 为什么需要同时收集 JS 和 Native 日志?

答案:

  1. JS 引擎、文件、渲染、音频、网络、线程和生命周期。
  2. 平台沙盒、权限、分隔符和可写目录不同。
  3. 图形 API、扩展、精度、纹理格式、驱动和平台 Shader 编译。
  4. 问题可能发生在业务、绑定、C++ 或平台层。

Creator 2.4.x 双端差异实验 ​

EnvMatrixProbe.ts ​

ts
const { ccclass } = cc._decorator;

@ccclass
export default class EnvMatrixProbe extends cc.Component {
    start() {
        cc.log(
            '[env]',
            'native=', cc.sys.isNative,
            'platform=', cc.sys.platform,
            'os=', cc.sys.os
        );
    }

    async run(action: string, fn: () => Promise<void>) {
        const begin = Date.now();
        try {
            await fn();
            cc.log('[env]', action, 'ok', Date.now() - begin);
        } catch (error) {
            cc.error('[env]', action, 'failed', error);
        }
    }
}

逐项实验 ​

  1. 冷启动并记录首屏。
  2. 用户点击后播放短音频,再自动播放一次。
  3. 写入/读取一条设置。
  4. 访问一个资源和一个远程 URL。
  5. 切后台再恢复。
  6. 在同一设备 WebView/Native(若项目支持)对照。

结果按“能力、权限、错误码、回退”记录,不按平台名写大量散落分支。

能力适配层 ​

ts
interface AudioService {
    unlockByUserGesture(): Promise<void>;
    play(id: string): Promise<void>;
}

interface FileService {
    read(key: string): Promise<string | null>;
}

业务只调用接口;Web/Native 实现负责路径、权限、会话和错误。这样平台差异在边界内可测试。

真实项目故障:Web 资源路径在 Native 失效 ​

代码保存 /assets/config.json,Native 包中不存在这个开发机 URL。正确做法是:

  • 静态资源用 Creator 资源入口;
  • 动态资源用 resources/Bundle 逻辑路径;
  • 用户数据用平台可写沙盒接口;
  • 远程数据使用 HTTPS 与合法域名;
  • 统一错误/超时/回退。

诊断矩阵 ​

能力Web 先查Native 先查
音频autoplay/用户手势Audio Session/权限/格式
文件URL/浏览器存储沙盒路径/权限
网络CORS/HTTPS域名/证书/网络权限
纹理WebGL 支持GPU 格式/内存
生命周期页面可见性后台/暂停/原生回调

版本边界与练习答案 ​

Web/Native 差异受浏览器、OS、基础库和 Creator 2.4.x 构建影响。课程不写死平台限制数值,发布前查当前官方文档。

  1. 为什么能力适配层比 if platform 分散更好? 集中处理权限、错误和回退,业务语义一致且可测试。
  2. Web 音频正常是否证明 Native 音频资源正确? 不证明,音频会话、格式和用户手势规则可能不同。
  3. 用户数据为什么不能用 assets 路径写? assets/通常是发布资源,设备上不可写或不是持久数据目录。
  4. 差异实验要固定什么? Creator 版本、构建配置、设备、OS、网络、缓存和用户动作。

十二、本课总结 ​

text
跨平台复用的是接口和大部分业务,不是完全相同的底层环境。
Web 用于快速验证,Native 和真机用于最终确认。

十三、下一课预告 ​

text
Lesson079|主线程、渲染、网络、音频与平台线程边界