原文转载自「刘悦的技术博客」https://v3u.cn/a_id_216

PWA(Progressive web apps,渐进式 Web 利用)应用古代的 Web API 以及传统的渐进式加强策略来创立跨平台 Web 应用程序,说白了,PWA能够让咱们的站点以原生APP的模式运行,但相比于装置原生APP利用,拜访PWA显然更加容易和迅速,还能够通过链接来分享PWA利用。

有许多出名的网络平台曾经将 PWA 计划落地,比方Twitter。抉择加强的网站体验而不是原生利用。事实上应用PWA也的确从中取得了不言而喻的好处。https://www.pwastats.com 这个网站上分享了许多案例钻研,PWA相比于传统利用有以下益处:

1、缩小利用装置后的加载工夫,通过 Service Workers 来进行缓存,以此来节俭带宽和工夫。

2、当利用有可用的更新时,能够只更新产生扭转的那局部内容。相比之下,对于一个原生利用而言,即使是最渺小的改变也须要强制用户去进行热更新或者再次下载整个利用。
3、外观和应用感触与原生平台更加融为一体——利用图标被搁置在主屏幕上,利用能够全屏运行等。
凭借零碎告诉和推送音讯与用户放弃连贯,对用户产生更多的吸引力,并且进步转换效率。

诚然,从零开始研发PWA利用会有肯定的老本,但如果咱们自身就领有基于Web的站点,那么就能够通过减少对应的配置文件和服务进行降级操作,间接领有PWA利用。

HTTPS服务

首先PWA要求站点的申请形式为HTTPS,如果是生产环境,能够通过为Nginx服务器配置SSL的形式进行适配,然而线下环境测试PWA时就有点吃力了,所以通过openssl工具为本地域名localhost做自签证书:

openssl req -x509 -out localhost.crt -keyout localhost.key \    -newkey rsa:2048 -nodes -sha256 \    -days 3650 \    -subj '/CN=localhost' -extensions EXT -config <( \     printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

产出:localhost.crt和localhost.key文件,key是私用密钥openssl格局,通常是rsa算法。csr是证书申请文件,用于申请证书,在制作csr文件的时,必须应用本人的私钥来签订申,还能够设定一个密钥。

将文件放到我的项目的根目录下,随后在构建我的项目服务的时候配置即可,以Tornado为例:

server = httpserver.HTTPServer(app,xheaders=True,ssl_options={          "certfile": "./localhost.crt",          "keyfile": "./localhost.key",      })    # 指定端口  server.listen(443)

这里通过设置ssl\_options参数来导入私钥和证书,同时将端口改为HTTPS默认端口号443。如此,在本地也能够对PWA进行测试了,当然了,如果不须要本地操作,也能够跳过这步。

manifest.json配置文件

为了实现 PWA 利用增加至桌面的性能,除了要求站点反对 HTTPS 之外,还须要筹备 manifest.json 文件去配置利用的图标、名称等信息。

以本站为例,在站点根目录创立manifest.json文件:

{      "name": "刘悦的技术博客",      "short_name": "刘悦的技术博客",      "description": "刘悦的技术博客",      "icons": [          {              "src": "https://v3u.cn/v3u/Public/images/pwa192.png",              "sizes": "192x192",              "type": "image/png"          },          {              "src": "https://v3u.cn/v3u/Public/images/pwa512.png",              "sizes": "512x512",              "type": "image/png"          }      ],      "background_color": "#FFF",       "theme_color": "#FFF",       "display": "standalone",       "orientation": "portrait",      "start_url": "/",       "scope": "/"   }

由上至下,顺次是 PWA 利用的名称、形容、图标文件、banner色彩、显示方式、开始页面的链接和 PWA 的作用域。为此咱们须要提供两张不同分辨率的站点图标文件:

ServiceWorker服务

Service Worker是一个注册在指定源和门路下的事件驱动型Web Worker。它充当了Web应用程序与浏览器之间的代理服务器,进行资源在文件级别下的缓存与操控,拦挡页面申请,实现在不同的状况下对不同申请的响应策略。

Service Worker实质上就是一个Web Worker,因而它具备Web Worker的特点:无奈操作DOM、脱离主线程、独立上下文。

Service Worker还具备这些特点:只能在Https下应用、运行在浏览器后盾,不受页面刷新影响、更弱小的离线缓存能力(应用Cache API)、申请拦挡能力、齐全异步,不能应用同步API、继续运行,第一次拜访页面后,Service Worker就会装置激活并继续运行,直到手动销毁。

以本站为例,在站点根目录创立sw.js文件,留神Service Worker文件地位肯定得在根目录,如果不在根目录也要通过重写或者url映射让其能够通过根目录门路进行拜访,如:https://v3u.cn/sw.js,否则浏览器会检测不到Service Worker服务:

var CACHE_NAME = 'v3u-cache-v1';  var urlsToCache = [      '/',      '/v3u/Public/css/tidy_min.css'  ];    self.addEventListener('install', function (event) {      event.waitUntil(          caches.open(CACHE_NAME).then(function (cache) {              console.log('Open cache');              return cache.addAll(urlsToCache);          }).then(function () {              self.skipWaiting();          })      );  }); 

当咱们为页面注册Service Worker后,Service Worker开始进行装置,装置胜利之后,会在worker中触发install事件;如果装置失败,则进入废除状态。

如果Service Worker逻辑文件更新(相干资源文件变动或者外部逻辑更新等),Service Worker会重新安装,如果这个时候,页面仍然存在激活状态下的worker(旧的Service Worker),那么新的worker会进入waiting状态进行期待,直到咱们被动去操作worker强制其更新,或者期待用户敞开所有页面,这个时候新的worker才会进入到激活状态。

在install事件中,咱们应用caches.open办法关上cache对象,并通过cache.addAll缓存所有咱们列出的文件。如果Service Worker存在更新,咱们应用skipWaiting跳过期待,间接强制新的worker进入激活状态。

随后,增加fetch事件:

self.addEventListener('fetch', function(event){          if(event.request.method !== 'GET') return;          event.respondWith(              caches.match(event.request).then(function(response){                  if(response){                      console.log('return caches');                      return response;                  }else{                      return fetch(event.request).catch(function(){                          if(/\.html$/.test(event.request.url))                              return caches.match('/html/neterror.html');                      });                  }              })          )      });

这里只监听了全站的GET申请形式,即咱们只心愿管制资源申请。通过caches.match查看申请是否命中了缓存,如果命中,则间接返回缓存给用户,避免反复申请,节约资源。如果没有命中,则将应用fetch办法申请网络资源并返回给用户。当网络状态异样时(fetch().catch()),返回404页面的缓存给用户,告知用户以后处于无网络状态,不能拜访相干页面。指定了一些页面和文件进行缓存,咱们心愿用户在无网络的状况下只能拜访到咱们指定缓存的页面。

当然,还有另外一种状况,咱们指定了一些页面进行缓存(罕用页面),当用户拜访到一些不罕用页面时,再对其进行缓存。这样,咱们能够对资源配置进行优化,不过多的占用用户本地资源去缓存所有页面,因为PWA的缓冲自身是存储到客户端的,对于非所有用户的罕用页面,按需缓存:

self.addEventListener('fetch', function(event){          if(event.request.method !== 'GET') return;          event.respondWith(              caches.match(event.request).then(function(response){                  if(response){                      console.log('return caches');                      return response;                  }else{                      return fetch(event.request).then(function(res){                          var responseToCache = res.clone();                          caches.open(CACHE_NAME).then(function(cache){                              catch.put(event.request, responseToCache);                          })                          return res;                      });                    }              })          )      });

至此,ServiceWorker服务文件就撰写实现了。

生产环境上线配置:

别离将manifest.json和sw.js文件别离上传到生产环境之后,在页面的head标签中进行申明:

<link rel="manifest" href="manifest.json">

申明后,留神拜访一下是否正确返回:https://v3u.cn/manifest.json

随后在页面中注册Service Worker服务:

<script>    if ('serviceWorker' in navigator) {      window.addEventListener('load', () =>          navigator.serviceWorker.register("/sw.js?v0")              .catch(() => {}) // ignore      );  }  </script>

这里首先判断以后浏览器的navigator是否反对serviceWorker,随后应用navigator.serviceWorker.register函数来注册Service Worker。其中,参数为要执行的worker逻辑文件门路,留神这个门路是基于origin的,而非以后文件。

接着键入组合键,关上chrome浏览器的开发者工具:

Mac零碎上的“⌥+⌘+I”

Win零碎上的“F12+Ctrl+Shift+I”

在Chrome 的利用标签下进行查看,看利用清单有没有读出你的 PWA 利用信息配置文件:

随后在serviceWorker标签下查看serviceWorker是否正确运行:

接着拜访站点,在地址栏即可增加PWA利用:

拜访成果:

结语

渐进式加强和响应式设计曾经能够让咱们构建对挪动端十分敌对的站点,而PWA则又在咱们的身后轻轻地推了一把,黄河之水源可滥觞,星星之火正在燎原,一年以内,咱们都将感到PWA的灼人温度。

原文转载自「刘悦的技术博客」 https://v3u.cn/a_id_216