理解 WebView

译者 | 子非
译文 | https://juejin.im/post/5ce76ee4f265da1b8d15f700
作者 |kirupa
原文 | https://www.kirupa.com/apps/webview.htm

我们通常使用 Chrome, Firefox, Safari, Internet Explorer 和 Edge 等浏览器来浏览网页。你也许正在使用其中一种浏览器阅读本文!虽然浏览器对于访问互联网内容的任务来说非常流行,它们还有一些我们从未过多关注过的竞争对手。这些竞争对手以 WebView 的形式被我们所熟知。这片文章将讲解 WebView 的神秘之处以及为什么它这么棒。

WebView 入门知识

让我们来点无聊的定义。WebView 是一种嵌入式浏览器,原生应用可以用它来展示网络内容。这句话有两部分要注意:

第一,原生应用(亦称 app)。原生应用由专门为特定平台设计的编程语言和 UI 框架编写:

换句话说,应用不是指在浏览器中运行的跨平台网络应用。相反,你的应用主要是用像 Swift、Objective-C、Java、C++、C# 语言来编写的。这种工作方式与系统更加贴近。在这样的背景下,你使用的大多数应用都应该是原生应用。许多流行的应用,比如你的台式机/笔记本上的 Microsoft Office 也是如此。

第二个处需要注意的是嵌入式浏览器。我们都知道浏览器是什么。它是让我们可以在网上冲浪的独立应用:

如果你把浏览器想象成两部分,一部分是 UI(地址栏,导航栏按钮等),其它部分是把标记跟代码转换成我们可见和可交互视图的引擎。

WebView 就是浏览器引擎部分,你可以像插入 iframe 一样将 Webview 插入到你的原生应用中,并且编程化的告诉它将会加载什么网页内容。

把所有的这些概念放到一起并简单整合下,WebView 只是一个可视化的组件/控件/微件等。这样我们可以用它来作为我们原生 app 的视觉部分。当你使用原生应用时,WebView 可能只是被隐藏在普通的原生 UI 元素中,你甚至用不到注意到它。

你的 WebView 就像是原生组件海洋里一座对 Web 友好的岛。对于你的应用来说这座岛的内容不需要存储在本地。你的 WebView 通常会从 http:// 或者 https:// 地址下载网络内容。这意味着你可以从服务器中获取部分(或全部)Web 应用并且依赖 Webview 将这部分内容展示在原生应用中:

这种灵活性打开了一个浏览器端的 Web 应用和希望展示在原生应用中的 Web 应用代码之间可重用的世界。这一切听起来真的非常棒……

运行在你的 WebView 中的 JavaScript 有能力调用原生的系统 API。这意味着你不必受到 Web 代码通常必须遵守的传统浏览器安全沙箱的限制。下图解释了使这样成为可能的架构差异:

默认情况下,在 WebView 或 Web 浏览器中运行的任何 Web 代码都与应用的其余部分保持隔离。这样做是出于安全原因,主要是为降低恶意的 JavaScript 代码对系统造成的伤害。如果浏览器或 WebView 出现故障,那很不幸,但可以接受。如果整个系统发生故障,那很不幸……并且这样不能接受。对于任意 Web 内容,这种安全级别很有意义。你永远不能完全信任加载的 Web 内容。WebView 的情况并非如此。对于 WebView 方案,开发人员通常可以完全控制加载的内容。恶意代码进入并在设备上造成混乱的可能性非常低。

这就是为什么对于 WebView,开发人员可以使用各种受支持的方式来覆盖默认的安全行为,并让 Web 代码和原生应用代码相互通信。这种沟通通常称为 bridge。你可以在前面的图表中看到 bridge 可视化为 Native Bridge 和 JavaScript Bridge 的一部分。详细了解这些 bridge 的内容超出了本文的范围,但要点如下:为 Web 编写的相同 JavaScript 不仅可以在 WebView 中运行,还可以调用原生 API 并帮助你的应用更深入地集成酷炫的系统级功能,如传感器,存储,日历/联系人等。

WebView 用例

现在我们已经了解了 WebView 的概况以及他们所拥有的一些强大作用,让我们退后一步,看看我们一些在原生应用中受欢迎的 WebView 的用例情况。

App 内置浏览器

WebView 最常见的用途之一是显示链接的内容。在移动设备上启动浏览器,将用户从一个应用切换到另一个应用以及希望他们找到返回应用的操作尤其令人失望。WebView 通过在应用本身内完全加载链接的内容来很好地解决这个问题。

看看下面的视频,了解当我们点击 Twitter 或 Facebook 应用中的链接时会发生什么:
Twitter 和 Facebook 都没有在默认浏览器中加载链接的内容。他们使用 WebView 伪造应用内浏览器并将内容呈现为应用体验本身的一部分。Twitter 的应用内浏览器看起来非常简单,但 Facebook 则更进一步,做了一个看起来很棒的地址栏甚至还有一个漂亮的菜单:

选择 Twitter 和 Facebook 做例子是因为我安装了这两个应用,并且可以随时录制视频与大家分享。有许多应用通过依赖 WebView 作为应用内浏览器来以类似的方式打开链接。

广告

广告仍然是原生应用最流行的赚钱方式之一。这些广告大部分是如何投放的?答案是通过 WebView 提供的 Web 内容:

虽然原生广告确实存在,但大多数原生解决方案在幕后使用 WebView,并从集中式广告服务器提供类似于你在浏览器中看到的广告。

全屏混合应用

到目前为止,我们一直在将 WebView 视为舞台上的次要支持角色,并由原生应用和其他原生 UI 元素完全支配。WebView 具有成为明星的深度和广度,并且在一大类应用中 WebView 内部加载的 Web 内容构成了整个应用用户体验:

这些应用被称为混合应用。从技术角度来看,这些仍然是原生应用。事实上,这些应用所做的唯一原生操作就是托管 WebView,而 WebView 又加载 Web 内容和用户交互的所有 UI。混合应用很受欢迎有几个原因。最大的一个是开发人员生产力。如果你有一个在浏览器中运行的响应式 Web 应用,那么在各种设备上使用相同的应用作为混合应用会非常简单:

当你对 Web 应用进行更新时,所有使用它的设备都可以立即使用该更改,因为内容来自一个集中位置,也就是你的服务器:

如果你必须使用纯原生应用,不仅需要为构建应用的每个平台更新项目,你可能必须经历耗时的应用审核过程才能使你的更新在所有的应用商店获取到。从部署和更新的角度来看,混合应用非常方便。将这种便利性与原生设备访问相结合能为你的 Web 应用提供超能力,这样你就拥有了一个成功的技术解决方案。WebView 使一切成为可能。

原生应用扩展

你将看到 WebView 使用的最后一个大类与可扩展性有关。许多原生应用(尤其是桌面应用)为你提供了一种通过安装加载项或扩展程序来扩展其功能的方法。由于 Web 技术的简单性和强大,这些加载项和扩展通常以 HTML、CSS 和 JavaScript 而不是 C++,C# 或其他方式构建。一个流行的例子是 Microsoft Office。构成 Microsoft Office 的各种应用尽可能是原生和经典的方式,但是为其构建扩展的方法之一就涉及 Web 技术。例如,一个流行的此类扩展是维基百科应用:

这些基于 Web 的扩展程序(如维基百科)在 Word 等 Office 应用中的表现方式是通过——是的,WebView:

WebView 中显示的实际内容来自此URL。当你在浏览器中访问该页面时,你并没有真正看到很多内容。是原生应用功能和 Web 代码(通过 WebView 暴露)的功能之间的交集使体验工作完整。作为 Word 应用内维基百科扩展的用户,你可能永远不会有疑问幕后发生了什么,因为功能已经被很好地集成,我们要的仅仅是它能正常工作。

WebView(通常)并不特别

WebView 非常棒。虽然看起来它们看起来像是完全特殊和独特的野兽,记住,它们只不过是一个在应用中设置好位置和大小的浏览器,而且不会放置任何花哨的 UI。其实还有更多东西,但这是它的精髓。在大多数情况下,除非你要调用原生 API,否则不必在 WebView 中专门测试 Web 应用。除此以外,你在 WebView 中看到的内容与你在浏览器中看到的内容相同,尤其是使用同一渲染引擎时:

在 iOS 上,Web 渲染引擎始终是 WebKit,与 Safari 和 Chrome 相同。是的,你没看错。iOS 上的 Chrome 实际上使用了 WebKit。

在 Android 上的渲染引擎通常是 Blink,与 Chrome 相同。

在 Windows,Linux 和 macOS 上,由于这些是更宽松的桌面平台,因此在选择 WebView 风格和渲染引擎时会有很大的灵活性。你看到的流行渲染引擎将是 Blink(Chrome)和 Trident(Internet Explorer),但是没有一个引擎可以依赖。这完全取决于应用以及它正在使用的 WebView 引擎。

我们可以花更多的时间来了解 WebView,并更深入地了解它们提供的一些特殊行为,但这会让我们偏离主题。对于我们在本篇文章要讲的东西,不偏离主题并宽泛了解WebView 才是正确的——至少到目前为止。

Chrome 81 正式发布 !消灭混合内容最后一步~

Chrome 81 于前天正式发布了,这个版本其实最初是计划在 3 月 17 号 发布的,但由于冠状病毒(COVID-19)爆发而导致推迟到了现在。Chrome 81 的延迟也扰乱了 Google 正常的六周发布时间表。因此 Google 此前也宣布,下一个版本将直接跳过 Chrome 82 ,直接发布 Chrome 83。 下面我就来带大家看看 Chrome 81 有哪些重要的更新。

发布于:1月以前  |  104次阅读  |  详细内容 »

当浏览器全面禁用三方 Cookie

苹果公司前不久对 Safari 浏览器进行一次重大更新,这次更新完全禁用了第三方 Cookie,这意味着,默认情况下,各大广告商或网站将无法对你的个人隐私进行追踪。而微软和 Mozilla 等也纷纷采取了措施禁用第三方 Cookie,但是由于这些浏览器市场份额较小,并没有给市场带来巨大的冲击。

发布于:1月以前  |  91次阅读  |  详细内容 »

H5 直播的疯狂点赞动画是如何实现的?

直播有一个很重要的互动:点赞。 为了烘托直播间的氛围,直播相对于普通视频或者文本内容,点赞通常有两个特殊需求: 点赞动作无限次,引导用户疯狂点赞 直播间的所有疯狂点赞,都需要在所有用户界面都动画展现出来(广播用户使用websocket消息)

发布于:1月以前  |  88次阅读  |  详细内容 »

探索 Serverless 中的前端开发模式

最近关于 Serverless 的讨论越来越多。看似与前端关系不大的 Serverless,其实早已和前端有了渊源,并且将对前端开发模式产生变革性的影响。本文主要就根据个人理解和总结,从前端开发模式的演进、基于 Serverless 的前端开发案例以及 Serverless 开发最佳实践等方面,与大家探讨 Serverless 中的前端开发模式。本人也有幸在 QCon2019 分享了这一主题。

发布于:1月以前  |  115次阅读  |  详细内容 »

前端需要了解的9种设计模式

设计模式是对软件设计开发过程中反复出现的某类问题的通用解决方案。设计模式更多的是指导思想和方法论,而不是现成的代码,当然每种设计模式都有每种语言中的具体实现方式。学习设计模式更多的是理解各种模式的内在思想和解决的问题,毕竟这是前人无数经验总结成的最佳实践,而代码实现则是对加深理解的辅助。

发布于:1月以前  |  95次阅读  |  详细内容 »

为什么你的网页需要 CSP?

内容安全策略(CSP)是一个 HTTP Header,CSP 通过告诉浏览器一系列规则,严格规定页面中哪些资源允许有哪些来源, 不在指定范围内的统统拒绝。

发布于:1月以前  |  86次阅读  |  详细内容 »

10 种跨域解决方案(附终极方案)

嗯。又来了,又说到跨域了,这是一个老生常谈的话题,以前我觉得这种基础文章没有什么好写的,会想着你去了解底层啊,不是很简单吗。但是最近在开发一个 「vscode 插件」 发现,当你刚入门一样东西的时候,你不会想这么多,因为你对他不熟悉,当你遇到不会的东西,你就是想先找到解决方案,然后通过这个解决方案再去深入理解。

发布于:1月以前  |  140次阅读  |  详细内容 »

移动 Web 最佳实践(干货长文,建议收藏)

笔者在公司用 web 技术开发移动端应用已经有一年多的时间了,开始主要以 vue 技术栈配合 native 为主,目前演进成 vue + react native 技术架构,vue 主要负责开发 OA 业务,比如报销、出差、crm 等等,react native 主要负责即时通信部分,是在 mattermost-mobile的基础上修改的(mattermost 是一个开源的即时通讯方案)。

发布于:1月以前  |  99次阅读  |  详细内容 »

不可错过的实用前端工具

给大家整理了 25 个前端相关的学习网站和一些靠谱的小工具,包括一些小游戏、教程、社区网站和博客,以及一些资源网站,希望可以帮助到大家!

发布于:1月以前  |  92次阅读  |  详细内容 »

理解 WebView

我们通常使用 Chrome, Firefox, Safari, Internet Explorer 和 Edge 等浏览器来浏览网页。你也许正在使用其中一种浏览器阅读本文!虽然浏览器对于访问互联网内容的任务来说非常流行,它们还有一些我们从未过多关注过的竞争对手。这些竞争对手以 WebView 的形式被我们所熟知。这片文章将讲解 WebView 的神秘之处以及为什么它这么棒。

发布于:1月以前  |  94次阅读  |  详细内容 »

Facebook 前端技术栈重构分享

当我们考虑如何构建一个新的网络应用—一个为现代浏览器设计的、具有用户对Facebook(我们已知的)所有期望的功能,我们现有的技术栈无法支持我们所需要的类似于桌面应用的感觉和性能。

发布于:1月以前  |  95次阅读  |  详细内容 »

最多阅读

为Electron程序添加运行时日志 1年以前  |  4812次阅读
初探 React 组件 1年以前  |  2169次阅读
wordpress标签页的制作 1年以前  |  2056次阅读
Node.js下通过配置host访问URL 1年以前  |  1995次阅读
js动态创建类和实例化 1年以前  |  1975次阅读
500行PHP代码搞定富文本安全过滤 1年以前  |  1954次阅读
22个HTML5的初级技巧 1年以前  |  1902次阅读
使用 SRI 增强 localStorage 代码安全 1年以前  |  1901次阅读
浅谈浏览器的原生拖拽事件 1年以前  |  1869次阅读
第三版主题上线 1年以前  |  1859次阅读
CSS清除浮动 1年以前  |  1855次阅读
2014年度总结 1年以前  |  1805次阅读
【译】V8 团队眼中的 ES6、ES7及未来 1年以前  |  1799次阅读
利用服务器返回header来传输数据 1年以前  |  1788次阅读
获取元素的计算的样式 1年以前  |  1784次阅读