资讯专栏INFORMATION COLUMN

Web离线技术(一)—— 技术选型

null1145 / 1612人阅读

摘要:上面提到在安卓完全不需要像这样大费周章的绕弯路,所以安卓可能就不需要这个自定义的,这样又会导致面临着与安卓差异化严重问题。

前言

最早接触离线包的概念要追溯到16年初,项目迎来大改版,其中重点项目之一就是离线包方案的制定与实施。离线包顾名思义就是将H5/CSS/JS和资源文件打包提前下发到App中,这样App在加载网页的时候实际上加载的是本地的文件,减少网络请求来提高网页的渲染速度,并实现动态更新效果。

就目前情况来看,离线包的方案也是层出不穷的,在文末参考部分,总结了一些文章入口,如果有这方面的需求的也可以进行参考。

回归主题,本篇将从iOS现有的四种离线方案进行探讨分析,目的在于探索一个最佳方案来实施我们的离线包功能,也希望对你能有所帮助。

目录

1. 构建离线包管理平台

2. 离线包加载方案探究

3. fallback 技术

4. 总结

一、构建离线包管理平台

1.后端使用离线包管理平台把同一个业务模块相关的页面和资源打包成一个zip压缩包文件,同时对文件加密/签名。

2.客户端根据本地数据库表,和服务端进行版本校验,做增量、全量更新操作,做解压/解密/校验等工作。

3.根据数据库表,打开某个业务时转接到打开离线包的入口页面,即我们常见的index.html。

4.拦截网络请求,对于离线包已经有的文件,直接读取离线包数据返回,否则走http协议缓存逻辑。

对于离线包平台的构建是十分有必要的,建议如果实施离线包方案,那就同步实施离线包平台构建,负责离线包的增删改功能,当然这就不单单是客户端的事情了。

本篇着重讨论第四步,拦截网络请求。 二、离线包加载方案探究 方案一:获取沙盒html路径直接加载index.html

1.将所有的h5文件都放入一个文件夹中。

2.将这个文件夹以相对路径的方式倒入到工程代码中。

3.获取本地的文件路径。

这个方案就是将部署在服务器上面的前端代码直接解压到本地沙盒。加载js的时候直接加载本地沙盒中的html进行离线加载。将每个前端的模块都定义为一个应用,打上id下发给客户端,当用户点击对应模块的时候根据id去沙盒查找对应的离线资源进行加载实现秒开。

优点:简单。

缺点:

    实际上我们在访问本地html的时候可以看到实际路径为file:///.../index.html。这是在使用file协议访问html,有些html样式并不支持file协议,在样式和功能上会有缺失,还会有一些api上的差异,前端开发好的代码可能部署到沙盒里导致有些资源无法使用,产生一些适配问题。

    访问本地资源可能会导致资源路径泄漏产生安全问题。

    还会有一些浏览器的安全设置无法通过。

    无法实现跨域资源请求,会让前端开发人员无法访问外部cdn。

file协议&http协议:file协议主要用于访问本地计算机中的文件,好比通过资源管理器打开文件一样,针对本地的,即file协议是访问你本机的文件资源。http协议访问本地html是在本地起了一台http服务器,然后你访问自己电脑上的本地服务器,http服务器再去访问你本机的文件资源。

浏览器对两种协议的处理有时会不同,譬如某些网页中直接调用file协议来打开图片,这样的功能会被浏览器的安全设置阻挡,因为默认上,html是运行于客户端的超文本语言,从安全性上来讲,服务端不能对客户端进行本地操作。即使有一些象cookie这类的本地操作,也是需要进行安全级别设置的。倘若你需要载入外部cdn的资源,比如livereload、browserSync等工具的使用,由于浏览器的同源策略,从本地文件系统载入外部文件将会失败,会抛出安全性异常。

总的来说,这个方案会对前端产生严重的入侵,限制了前端只能通过相对路径对js,css,image等资源的加载,还有file协议的跨域问题导致无法引入外部cdn,这样会限制前端开发,虽然用起来最简单,但这并不是一个好的方案。

方案二:使用protocol拦截

既然直接加载本地html不是最好方案,那我们将加载html后的所以资源请求全部拦截,映射为本地资源重新组装request进行http请求并加载,是否可行呢?当然可行了,但是往下看:

UIWebView上,protocol拦截确实是我们的首选方案,创建个子类,在子类里面实现protocol的代理方法即可实现对所有请求的拦截,当然也包括html里面对资源加载的请求。

那么在WKWebView上,这个方案是行不通的,关于这方面的解释已经很多了,WKWebView在独立于app进程之外的进程中执行网络请求,请求数据不经过主进程,因此,在WKWebView上直接使用 NSURLProtocol 无法拦截请求。当然通过私有api可以解决问题,但依然存在缺陷,post请求body数据被清空。由于WKWebView在独立进程里执行网络请求。一旦注册http(s) scheme后,网络请求将从Network Process发送到App Process,这样 NSURLProtocol 才能拦截网络请求。在webkit2的设计里使用MessageQueue进行进程之间的通信,Network Process会将请求encode成一个Message,然后通过 IPC 发送给 App Process。出于性能的原因,encode的时候HTTPBody和HTTPBodyStream这两个字段被丢弃掉了。

此段引自:《WKWebView》

关于丢Body的解决方案可以戳上文详细查看。如果使用Get请求拦截离线资源可以通过设置自定义的customScheme:进行拦截,例如customScheme://.../.css,拦截后加载本地离线资源。但是使用私有api又会面临另外一个风险:被拒

说一点题外话,目前据我所了解到百度App安卓就是采用的请求拦截方式,但是,是安卓,看下图:

图片来源《百度APP-Android H5首屏优化实践》

通过上图可以分析第11、12步,WebView对html解析的时候可以发现资源请求并拦截,返回对应的缓存资源并渲染。实际上这个方案在iOS上是行不通的,安卓可以使用自家浏览器,可以魔改浏览器,比如支付宝的UC,百度的T7等。iOS应用内是不允许使用魔改浏览器的,很遗憾,也就是说苹果爸爸开放了什么,我们才能使用什么。

总结来说,这个方案并不会对前端产生入侵,但对于body的拦截和对私有api的使用,产生上架被拒风险,另外protocol是一个全局的拦截,可能也并不是我们想要的,所以这个方案仍然不推荐。

方案三:WKURLSchemeHandler

WKURLSchemeHandler是iOS11就推出的,用于处理自定义请求的方案,不过并不能处理Http、Https等常规scheme。

WKWebViewConfiguration开放了setURLSchemeHandler:forURLScheme:函数,需要指定一个自定义的scheme和一个用来处理WKURLSchemeHandler回调的自定义对象。

根据注释来看,如果注册了一个无效的scheme或者使用WebKit内部已经处理的scheme将会引发异常。我们最好使用WKWebView的handlesURLScheme:类方法来检查给定scheme的可用性,以免带来一些未知问题。

WKURLSchemeHandler提供了两个回调函数由上面自定义的对象来处理:

- (void)webView:(WKWebView *)webView startURLSchemeTask:(id )urlSchemeTask;
- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id )urlSchemeTask;

通过urlSchemeTaskrequest对象可以拿到请求对应的url,如果是我们自定义的scheme就去拦截它,并加载本地资源。

实际上这个方案解决了资源拦截的问题,但是它依然有很多短板:

    因为使用的自定义scheme,并不是http协议,所以它依然无法解决跨域问题。

    由于自定义了scheme,对于前端来说,需要额外将scheme设置为我们自定义的,这又会给前端带来大量的改造,所以对前端还是产生了入侵。

    上面提到在安卓完全不需要像iOS这样大费周章的绕弯路,所以安卓可能就不需要这个自定义的scheme,这样又会导致面临着与安卓差异化严重问题。

所以这样来看,WKURLSchemeHandler的拦截方案也并不是特别友好。真的是感觉到了苹果爸爸对于离线包的恶意

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/7360.html

相关文章

  • 构建离线web应用(二)

    摘要:提及缓存时,不仅仅是指存储,还包括浏览器内用来保存数据以供离线使用的策略。当请求成功返回时,利用返回的数据更新页面并缓存返回的数据。这种方案主要应用用户频繁手动更新内容的场景,比如用户的收件箱或者文章内容。我们打算应用的策略。 上一篇文章中,我们成功尝试使用 service workers。我们也可以在应用中缓存一些资源。这篇文章我们准备了解这些:service workers 以及缓...

    curlyCheng 评论0 收藏0
  • 前端每周清单:Node.js 微服务实践,Vue.js 与 GraphQL,Angular 组件技巧

    摘要:前端每周清单第期微服务实践,与,组件技巧,攻防作者王下邀月熊编辑徐川前端每周清单专注前端领域内容,以对外文资料的搜集为主,帮助开发者了解一周前端热点分为新闻热点开发教程工程实践深度阅读开源项目巅峰人生等栏目。 前端每周清单第 26 期:Node.js 微服务实践,Vue.js 与 GraphQL,Angular 组件技巧,HeadlessChrome 攻防 作者:王下邀月熊 编辑:徐川...

    wall2flower 评论0 收藏0
  • 数据浪潮之间的前端工程师

    摘要:数据浪潮之间的前端工程师十年来,波澜壮阔的移动互联网浪潮促进了技术的迅猛发展,随着浏览器性能网络带宽等基础设施的提升,也能够承载起包含复杂交互可视化计算逻辑需求的富客户端应用。 showImg(https://segmentfault.com/img/remote/1460000016874425); 本文是架构师 2018-10 月刊的卷首语,归纳于自笔者的技术之路系列文章,也是对 ...

    mdluo 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<