点击上方 程序员成长指北,关注公众号
回复1,加入高级Node交流群
前言
如何解决传统 WebView 所面临的三大核心问题 —— 性能、外观和集成性,以及 Mobile Bridge 如何成为我们移动开发策略中的关键转折点,甚至帮助我们加速向 React Native 的迁移。今日前端早读课文章由 @Mauricio de Meirelles 分享,@飘飘编译。
Shopify 的移动应用大约有 600 个界面,虽然这些界面都对商家使用移动端体验有所贡献,但并不是每个界面对日常操作都同样重要。
对于那些关键界面,我们毫无疑问地选择使用原生或 React Native 来开发,以确保提供最好的使用体验。但如果将同样的开发方式应用到其他不那么关键的界面上,代价就非常高昂,同时还会严重拖慢开发进度。
我们的挑战很明确:我们需要一种高效的方式,把这些 “非关键” 界面集成到移动应用中,而不需要再为 Web 和移动端分别开发。
WebView 看起来是一个合理的选择,但它往往难以提供良好的用户体验 —— 经常显得慢、不流畅,而且跟原生界面风格不一致,容易让人感觉脱节。
我们不满足于这些限制,而是把它当作一次机会:我们是否能 “重塑” WebView,让它更快、更美观、看起来更像原生界面?这也正是我们创建 Mobile Bridge 框架的出发点。这个框架专门用来增强 WebView,让网页内容可以无缝融入我们的移动应用。
在这篇文章中,我们会分享我们是如何解决传统 WebView 在性能、外观和集成方面的主要问题,以及 Mobile Bridge 如何成为我们移动开发策略中的关键工具,甚至帮助我们加速向 React Native 的迁移。
WebView 的难题
WebView 一直不被看好,主要是因为用户一眼就能看出它不是 App 的原生部分。它们看起来脱节、运行缓慢,给人不好的使用体验。
为了改善这些问题,我们启动了一个项目,设定了三个关键目标:
让 WebView 更快
让 WebView 看起来像原生界面
让 WebView 用起来像原生界面
1、让 WebView 更快 🚀
我们首先着手找出 WebView 为什么加载缓慢。结果发现,主要问题出在认证流程上。每次加载 Web 页面时,WebView 都要经过好几次跳转来完成身份验证,这就导致了明显的延迟。
为了解决这个问题,我们提出了一个简单的方案:在应用启动时,就在后台预加载并完成 WebView 的身份认证。
为此,我们分别为 iOS 和 Android 构建了原生模块,可以实现以下功能:
在后台预加载 WebView(无需等待)
使用过的 WebView 不再丢弃,而是保留在缓存中
重复利用缓存的 WebView,用户就不会再遇到无谓的等待
通过这种方式,我们将 WebView 的加载时间提升了大约 6 倍 ——P75(75% 用户体验到的加载时间)从 6 秒缩短到 1.4 秒,这其中包括了网络延迟和页面渲染时间。
左图为优化前,右图为优化后
2、让 WebView 看起来更像原生界面
在解决了性能问题之后,我们开始着手提升 WebView 的外观和使用感受,重点是去除那些让它看起来不像原生界面的元素。我们主要改进了以下几个方面:
缩放功能:我们通过注入 JavaScript 来禁用页面缩放功能。
文本选择:通过添加 CSS 样式,取消了文本可选中功能。
不必要的界面元素:我们隐藏了 WebView 中一些在移动端不需要的后台管理界面组件,比如标题组件(Title component)和页面底部(Page footer)。
Polaris 样式覆盖:我们对 Polaris(Shopify 的 UI 组件库)中的组件进行了样式调整,使它们在视觉上更贴合原生应用的设计风格。
经过这些改进,我们的 WebView 在视觉风格和交互方式上更加接近原生界面,遵循了统一的用户体验设计标准。
优化前(左)与优化后(右)对比图
3、让 WebView 用起来更像原生界面
想要让 WebView 真正 “用起来像原生应用”,关键是要实现 Web 与移动端之间的简单通信。它们需要能够轻松地共享数据、追踪用户操作,并快速做出响应,比如知道用户何时导航、完成了什么操作,或者页面发生了哪些变化。
为此,我们开发了 Mobile Bridge 框架,它基于 Shopify 的 @remote-ui/rpc 库,能够在 Web 与移动端之间建立顺畅的双向通信通道。
解决页面标题和操作问题
我们首先处理的是标题栏的问题。在原生应用中,页面的标题和操作按钮(如 “保存”、“编辑”)通常显示在导航栏,而不是页面本身。为了让 WebView 与这一原生模式一致,我们在 Mobile Bridge 中设计了可以设置标题栏和操作按钮的 API。
接着,我们修改了 Polaris 的 Page 组件,让它将自己的标题和操作按钮传送给 Mobile Bridge,然后由 Mobile Bridge 将它们渲染到原生导航栏中。这样一来,WebView 瞬间看起来更像原生界面了。
优化前(左)与优化后(右)对比
解决 WebView 中的导航问题
导航功能是另一个关键挑战。在浏览器中,点击链接通常会重新加载整个页面,但原生应用则是将新页面 “压入” 导航堆栈中。如果我们每次导航都创建一个新的 WebView,就会导致用户的会话数据和动态内容丢失,体验既慢又令人沮丧。
为了解决这个问题,我们开发了一个名为 TransportableView 的新组件。它可以让我们在屏幕之间 “移动” 现有的 WebView,而不丢失任何状态或数据。TransportableView 可以把当前 WebView 实例直接转移到另一个屏幕上使用,这样即使用户返回上一个页面,也不会丢失任何内容或连接。
处理返回导航的问题
TransportableView 成功解决了 “前进导航” 的问题,因为我们总是在 WebView 进入新页面时展示一个全屏加载动画,用户不会看到前一页的内容短暂出现。
但如果是 “返回导航” 呢?如果不加处理,用户在返回或预览某些页面时可能会看到空白或损坏的界面,这就破坏了我们想要实现的原生体验。
为了解决这个问题,我们在 WebView 移动前会快速拍一张当前界面的 “快照”。当用户返回时,先显示这张静态图片,确保界面内容是完整的。等到实际的 WebView 完全加载好之后,我们再将这张快照移除。
iOS 上快照的捕捉与还原示意图:
以原生方式处理弹窗(Modal)
Web 页面中的弹窗通常是覆盖在当前内容之上的,而在移动应用中,弹窗通常作为独立的屏幕出现,并伴随原生的过渡动画。为了与这一行为保持一致,我们将弹窗处理为原生屏幕,并通过和前文页面跳转相同的方式来传递 WebView。
其中一个关键优化是:我们对 Polaris 的 Modal 组件进行了自定义处理,让它在原生动画完成之后再开始渲染内容。这样能保持过渡过程流畅,避免内容闪烁。
优化前(左)与优化后(右)对比图
更进一步的优化
在做完上述优化后,我们的 WebView 已经有了巨大的提升,但我们并没有就此止步。为了让体验更加无缝,我们还把已有的原生功能直接集成到了 WebView 中。
一个很好的例子就是日期选择器(Date Picker)。我们的很多分析类页面都采用 WebView,而日期选择器是查看报表的重要交互。虽然 Web 上的日期选择器在浏览器中运行良好,但在 App 里却不够 “原生”。既然我们已有原生版本的日期选择器组件,我们就通过 Mobile Bridge 把它集成进 WebView。
这种将原生与 Web 元素融合的方式,让用户体验变得更加自然、顺畅。
优化前(左)与优化后(右)对比图
我们还让 WebView 可以无缝调用原生功能。现在,Web 内容不仅能直接触发原生界面,还能轻松地获取返回结果。
在我们目前的应用中,已有一些实际应用场景,例如:
“添加到钱包” 功能:支持 iOS 和 Android,用户可以直接从 WebView 触发
原生条码扫描器:用于库存管理,集成在 WebView 中,商家可以快速扫描条码自动填写字段,大大提升工作效率
条码扫描器(左)和添加到钱包功能(右)
这种混合式方案让我们能够快速推出基于 Web 的新功能,同时为用户提供更丰富、更接近原生体验的使用感受。
Mobile Bridge 的未来发展
目前,Mobile Bridge 可以让 Web 触发原生界面元素,但这些原生元素必须事先在 App 中实现。这在一定程度上限制了发布速度,也让旧版本的 App 无法享受到新功能的升级。
为了解决这个问题,我们正在尝试使用 Shopify 的 remote-dom 技术,让 Polaris 组件可以通过 Web 代码在 App 中以原生方式渲染。
这种方式可以让我们在保留业务逻辑在 Web 端的同时,把界面组件交由原生端渲染。这样不仅带来更大的灵活性,还显著提升了整个混合应用的用户体验。
下面是我们基于这一方案构建的原型示例,你能猜出哪一部分是 WebView,哪一部分是原生的吗?
Mobile Bridge:Shopify 的变革者
Mobile Bridge 所带来的改进是如此显著,以至于 WebView 现在已经成为我们移动端开发战略中不可或缺的一部分。我们大量使用 WebView 来实现重要但非关键的功能,从而避免在 Web 和移动端重复开发。
而对于应用中所有关键功能,我们仍然坚持使用原生或 React Native 来提供最优质的体验。
我们已经将 Mobile Bridge 开源为一个独立的库,并开始将其整合进 Shopify 的其他产品中,比如 Balance、POS 和 Shop。这意味着更多应用也能采用这种强大的混合开发模式,从而享受到更快的开发周期和更好的用户体验。
Mobile Bridge 彻底改变了我们对 Web 与移动集成方式的看法 —— 它让我们可以拥有 Web 开发的灵活性与速度,同时为用户提供接近原生的流畅体验。它还释放了大量工程资源,让我们能将更多精力投入到提升关键原生界面的质量上。
译者:@飘飘
作者:@Mauricio de Meirelles
原文:https://shopify.engineering/mobilebridge-native-webviews
Node 社群
我组建了一个氛围特别好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你对Node.js学习感兴趣的话(后续有计划也可以),我们可以一起进行Node.js相关的交流、学习、共建。下方加 考拉 好友回复「Node」即可。
“分享、点赞、在看” 支持一波👍