简介:PWA 这个名词出来有一段时间了,一直没能实践下,业务上暂时也还没什么动机能上的。但是越来越多的大厂,包括 饿了么、Twitter、阿里等,都开始在生产环境大量使用相关技术,是时候重新来看看这个东东了。不过,PWA ...
PWA 这个名词出来有一段时间了,一直没能实践下,业务上暂时也还没什么动机能上的。但是越来越多的大厂,包括 饿了么、Twitter、阿里等,都开始在生产环境大量使用相关技术,是时候重新来看看这个东东了。 不过,PWA主要是给 SPA 来使用的,我们目前的业务确实还用不上。那就用一下其中的 Service Worker这个东东吧,试试对我们的 H5 秒开有没有什么功效。根据之前测试的情况,目前我们APP里的 WebView,处理缓存是存在问题的,理论上我们的静态资源都是强缓存的,但实际上发现,很多时候,页面仍然会重新请求静态资源,导致H5加载速度比较慢。如果能使用 Service Worker技术,主动 地缓存静态资源,而不是被动地交给浏览器处理,是不是能够解决静态资源的缓存问题呢? service worker Service Worker (下文简称SW),能够拦截作用域(scope)下的页面,以及该页面发出的请求,包括 跨越请求 。 浏览器支持情况 根据 https://caniuse.com/#feat=serviceworkers 的数据,android 5 之后,WebView 就支持 serviceworker;iOS 11.3 之后,也支持了。 找到这个MDN的链接 https://mdn.github.io/sw-test/ ,来测试 serviceworker 的缓存情况。 经过实际的测试,iOS 11.3上,Safari是支持 serviceworker的,在 iphone simulator里,通过添加 com.apple.developer.WebKit.ServiceWorkers YES ,WKWebView也可以支持 serviceworker,但是!但是,iOS的 APP里 WKWebView 是不支持 serviceworker 的!!库克这个糟老头子,实在是坑啊…… ServiceWorkerGlobalScope SW 的JS是在单独的进程这执行的,有自己的全局作用域,也有自己的全局变量(状态)。但是,根据 https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope 的说明,SW 的去全局状态,当SW被中断或者重启时,会被重置为默认状态,不会 持久化。因此,我们 不应该 在SW中设置自定义的全局变量,因为这些变量的状态,并没有持久化。 事件
作用时机
SW和主页面通信
// in app.jsnavigator.serviceWorker.controller.postMessage({ name: "hello", age: 30, deep: { arr: [ 1, 2, 3], test: true, }});// in sw.jsself.addEventListener("message", function (event) { console.log(event.data);});
// in sw.jsself.clients.matchAll().then(function (clients) { console.log("clients in sw: ", clients); clients.forEach(function (client) { client.postMessage({ hello: "word", yes: true, nest: { obj: {age: 31}, num: -23, bool: false, }, }); });});// in app.jsnavigator.serviceWorker.addEventListener("message", function(event){ console.log("message from sw: ", event.data);}); 跨域请求 Request.mode 根据 https://developer.mozilla.org/en-US/docs/Web/API/Request/mode 文档的介绍,跨域请求中,需要特别关注 Request.mode 这个 readonly 属性,这个属性会决定,在 Response 中,我们可以读取到哪些属性。Request.mode 包括以下几个值: same-origin no-cors cors navigate 。在不同的情况下,Request.mode的默认值是不一样的,重点要关注 no-cors 和 cors
Response.type 对应上述的 Request.mode,还存在一个只读的 Response.type 属性,用来判断当前的响应,是一个什么类型的请求,包括这些值:
CORS crossorigin 通常情况下,我们页面里的静态资源,包括 <img> <link> <script> 都会通过单独的域名来加载,这个域名一般和主页面的域名 不同,在 html5 里允许我们设置元素的 crossorigin 属性,来主动控制是否发送用户的credentials,包括 Cookie 。crossorigin 在默认情况下(即元素上不设置该属性),不会发起 CORS 请求;该属性只有2个可能的值:
service worker 拦截跨域请求 serviceworker可以拦截作用域下发起的所有请求,包括 跨越请求 。通常在缓存静态资源的时候,我们需要确保资源是正确响应的(比如返回http状态码200),如果返回的是 404 或者 500 之类的,那么就不应该缓存该资源。但是在 跨域 的请求下,默认的 Request.mode no-cors 我们 不能 读取返回的状态码,也就不知道资源是否OK;因此需要设置跨域资源的 cors 属性,比如页面里静态资源,设置 crossorigin=anonymous ,这样会触发浏览器发起 CORS 请求,也就要求我们的服务器返回header中,增加 Access-Control-Allow-Origin 来允许我们跨域访问该资源。 上线方案 针对我厂的情况,在移动端H5页面,我们主域名是 m.renrendai.com,引用的JS、css、图片等静态资源,使用的是 s0.renrendai.com,存在静态资源跨域的情况,因此,需要以下准备工作:
PS: 考虑到后期可能会上线 PC 端的对应缓存方案,针对 s0.renrendai.com 的 nginx 配置修改,可能要动态的根据请求 Origin 来返回不同的 Access-Control-Allow-Origin 值。 相关资料
本文仅代表作者个人观点,不代表巅云官方发声,对观点有疑义请先联系作者本人进行修改,若内容非法请联系平台管理员,邮箱2522407257@qq.com。更多相关资讯,请到巅云www.yinxi.net学习互联网营销技术请到巅云建站www.yx10011.com。 |