Edit the Blog Post Header component above this, then place your content here, then fill out the Related Articles section below, if possible. You should have at least one related article and ideally, all three.
Feel free to add supplementary content to the sidebar at right, but please retain the Twitter component (it can live at the bottom of your added content).
This text component can be edited or deleted as necessary.
Related articles only have an image (the squarer version of the banner) and a title. This text can be deleted. Place 1-3 related articles.
假如莎翁成为React Native开发者,也会思考:“共享,还是不共享,这是一个问题。”
如果用React Native构建应用,您可能也会如此自问☝️。无论是以Android TV、Apple TV还是以Fire TV为目标平台,导航、状态管理、业务逻辑、用户界面组件在大多数情况下都是一样的,甚至可能用的是同一套库。那为什么还要分开维护代码库呢?
有了Vega OS,我们有机会从一开始就把这件事做好。比起再推出一个把您与某个目标平台锁死的方案,我们的目标之一是轻松同时搞定多个电视平台。不同电视操作系统之间共享的代码达到70-85%,具体视您的应用架构而定。在这篇博客中,我们将带您深入了解它的工作原理,并弄清楚哪些代码“要共享,哪些不要”。
准备好开始了吗?
我们已经在GitHub上发布了一些项目。您可以挑一个契合自己工作流的项目直接开做,也可以接着往下看,我们会为您介绍工作区设置、部分保证运转的工具,以及现在可以共享(及不应共享)的代码。
👋 Multi-TV Hello World-初学者模板(仅提供英文版)
📺 React Native Multi-TV App Sample–生产参考应用(仅提供英文版)
🤖 Vega Multi-TV Migration代理技能-使用代理技能进行AI辅助迁移(仅提供英文版)
那么跨电视平台共享代码应该如何实操呢? 我们预想的设置是:共享代码统一存放,操作系统的特定功能(视频播放、原生集成、平台差异)保持隔离。
要实施这一方案,我们要利用Yarn v4工作区,把Vega项目重构为monorepo。而在Vega这边,您继续像以前一样使用Vega SDK即可。至于其他平台,我们会使用Expo TV。只要一个Expo项目,就能拥有开箱即用的体验,获得Android TV、Apple TV和Web支持。您可以将其拆分为三个工作区:
根package.json负责协调各子项目的构建。每个工作区都有自己的依赖项和构建配置,但会通过工作区导入来共享公共代码。
核心规则是操作系统包可通过共享代码导入,但共享代码绝不能通过操作系统包导入。
注意: Vega SDK默认使用npm,但该monorepo方案则使用Yarn v4工作区。 确保全程使用Yarn命令(yarn安装、yarn工作区等),避免包管理器发生冲突。
虽然工作区结构奠定了坚实基础,但要真正实现代码共享,还需要两个工具。
第一个就是VMRP(Vega模块解析器预设)。您的共享代码使用的是标准的React Native导入(如react-native-gesture-handler或react-native-reanimated),但Vega使用的则是这些库的自移植版本。VMRP是一个Babel预设,可在构建时将标准导入自动替换为Vega版本,以此保持共享代码的干净与可移植性。
您可以在Vega包的babel.config.js中进行配置:
配置好后,在进行Vega构建时,共享代码中的'react-native-gesture-handler'就会自动解析为@amazon-devices/react-native-gesture-handler。无需条件导入,也无需平台判断。
第二个就是Vega Studio的monorepo支持。打开项目时,它会自动检测您的工作区布局,并自动导入Vega子包。
在设置>Vega>功能中启用: 这套monorepo可帮您自动处理包发现、工作区同步以及构建任务的协调。
不是所有代码都要放入packages/shared/。有些代码在不同平台上的表现完全一致,有些需要操作系统特定实现,还有一些则介于两者之间。可以按照以下方法进行判断。
见效最简单,复用率也最高。您的API调用、Redux/Zustand存储、数据转换、验证逻辑、格式化实用工具,通常都不依赖任何操作系统特定库。经验之谈:如果代码既不触摸原生API,也不渲染到屏幕上,就可以放入packages/shared/。
Multi-TV App Sample的动态内容加载很好地体现了这一点。目录API客户端、数据转换和类型定义都在同一个共享包中,并且所有平台共用相同数据层。
您的大部分用户界面组件都是可以共享的。按钮、卡片、列表、布局、模态和网格视图通常都是标准的React Native组件,无需任何修改即可跨平台运行。
有意思的是平台特定样式。React Native的文件扩展解析可以轻松解决这个问题。先将基础组件写为Banner.tsx,然后添加平台特定扩展文件Banner.kepler.tsx,Metro会在构建时选择正确文件。要注意的是,您的Metro要先配置为支持monorepo解析。Hello World和Multi-TV App Sample这两个仓库中均已包含此配置。
Hello World仓库中的HeaderLogo组件演示了这一模式,即通过.kepler.tsx、.android.tsx、.ios.tsx和.web.tsx多种变体加载不同平台标志。
如果差异很小,不值得单独拆成文件,您也可以使用Platform.select()。
电视应用中的导航模式分为两种:
跨屏路由(在页面、选项卡、抽屉菜单之间跳转)通常是可以完全共享的。如果您使用的是React Navigation(Vega通过react-navigation包提供支持),则屏幕定义、路由配置和导航结构在所有平台上的表现都是一样的。
空间/焦点导航(使用遥控器方向键,在屏幕元素间移动焦点)则会真正体现出平台差异。Multi-TV App Sample使用React TV空间导航处理所有平台上的焦点移动,但是每个操作系统中负责捕获遥控器按键事件的底层机制并不相同。RemoteControlManager有.android.ts、.ios.ts和.kepler.ts三个文件,这是因为每个平台触发的按键事件不一样。焦点逻辑是共享的,但输入处理是分叉的。
电视应用需要在不同的屏幕尺寸和显示密度下都能正常显示。这里的模式和用户界面是一样的:共享设计系统(如令牌、间距、排版缩放),对于需要视平台调整的地方,则使用平台特定文件或Platform.select()。对于生产应用,建议构建完善的主题层,配合响应式布局,而不是仅仅依赖简单的缩放。
Hello World存储库内含缩放实用工具,以1920x1080为基准,折算不同电视屏幕的尺寸。缩放逻辑本身可以共用,但对于安全区域或过扫描等问题,则可能要针对不同平台进行单独微调。
为达到最佳性能,生产流媒体应用通常会使用操作系统自带的媒体播放器。您可以遵循这一方法,使用各操作系统自带的原生播放器,或使用支持跨平台的抽象层,如react-native-video(现已获得Vega支持)。除非用了这类抽象层,否则您的媒体播放应该位于操作系统特定包中。
内容启动器、应用内购买、亚马逊设备消息传递以及类似功能的底层API是各操作系统独有的,目前需要在Vega和Fire OS上分别实现。我们正在努力将这些功能迁移到统一的React Native库下面,但目前还是先把这些功能按便于日后整合的方式组织好。把这些功能放入各平台包中,提供清晰接口,以便共享代码进行调用。
提前说明一点,像按钮和文本这类简单的VUIC组件可以轻松迁移到React Native对应版本上。但要替换轮播和进度条组件就没那么简单了。在分析阶段就把这些依赖项识别出来,以免迁移到一半时才反应过来。
直接触摸原生代码的任何内容(自定义TurboModules、DRM实现、硬件特定功能)应保持平台特定。没有别的处理方式。
Multi-TV Hello World仓库时能够最快看到实际效果的方式。这种Hello World项目含有一个共享标头组件,可使用同一套代码库渲染Vega、Android TV、Apple TV和Web。
有关更接近生产应用的内容,请参阅React Native Multi-TV App Sample(仅提供英文版)。该电视应用模板包含以下内容:
通过同一个monorepo支持Android TV、Apple TV、Fire TV (Fire OS)、Fire TV (Vega OS)和Web。这是一个很好的参考,能探索共享工作区模式如何支持大规模应用。
我们还将整个迁移流程打包成了一个三阶段的代理技能,可配合Kiro、Claude或其他AI编码助手使用。GitHub支持使用:vega-multi-tv-migration。
要在Kiro中使用,只需将vega-multi-tv-migration directory复制到~/.kiro/skills/中,然后开始一段关于应用迁移的对话。它会根据您的对话上下文自动激活。
这项技能会执行静态代码分析并提供一份执行摘要,内含预估代码复用比例、依赖项分类(哪些要共享、哪些要保持操作系统特定、哪些由VMRP处理)以及一份跨屏迁移计划。
“分析我的Vega应用,看看如何实现多平台迁移。”
这一步会创建monorepo脚手架,将代码移动到共享包和vega包中,配置Metro进行monorepo解析,并设置VMRP。完成这一步后,您的Vega应用应该能像之前一样正常构建和运行,不过共享代码已得到妥善分离。
“根据第1阶段的分析结果,把我的Vega项目转换成基于yarn工作区的monorepo。”
这一步会设置好Expo TV包,并针对Vega特定依赖项给出替代方案:
“使用Expo TV添加Android TV和Apple TV支持。把我的Vega特定依赖项替换为标准React Native的对应版本。”
我们并非空口而谈,实际上,有一些合作伙伴已经在用Vega构建多平台电视应用,并且看到了切实效果。欢迎前往我们的开发者社区,了解开发者如何跨电视操作系统复用其React Native Vega,或阅读关于启用Vega的Zattoo如何跨平台简化电视应用开发流程的内容。这些案例研究展示了共享工作区方案在生产环境中的实用优势。
踩坑后的经验总结: