PWA很容易。 你好哈勃

不断了解渐进式Web应用程序。 在理论的最后一部分之后,该继续练习了。

今天,我们将构建一个简单而成熟的PWA“ Hello Habr”。




该应用程序位于https://altrusl.imtqy.com/habr-pwa/hello-habr/ 。 在移动设备上的浏览器中打开后,可以向主屏幕添加快捷方式并以全屏模式启动。

如果有人想在自己的计算机上尝试该示例,则Chrome允许您在本地使用简单的PWA应用程序,而无需安装具有SSL证书的第三方Web服务器。
在本地运行“ Hello Habr”的说明
您必须从本地网站服务器Chrome Web Store安装扩展程序或类似的扩展程序。 当然,没有PHP支持。



可以从GitHub-a上获取Hello Habr文件-https: //github.com/altrusl/habr-pwa/tree/master/hello-habr

将所有内容放在一个目录中,然后将其指向Web服务器。


“ Hello Habr”由一页组成。 他在上面显示图片(徽标)和动画题字。

“ Hello Habr”代码

index.html


<html> <head> <title>Hello Habr</title> <script src="hh.js"></script> <link rel="stylesheet" href="hh.css" /> <script type="text/javascript"> if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(function(registration) { console.log('Registration successful, scope is:', registration.scope); }) .catch(function(error) { console.log('Service worker registration failed, error:', error); }); } </script> </head> <body> <div class="center"> <p id="text"></p> </div> <div id="logo"></div> </body> </html> 

hh.css


 @font-face { font-family: Zaplyv-Heavy; src: url(Zaplyv-Heavy.otf); } body { display: flex; align-items: center; align-content: center; justify-content: center; overflow: auto; } .center { font-family: Zaplyv-Heavy; font-size: 8vmax; } #logo { background-image: url(logo.jpg); background-size: 100%; width: 100px; height: 100px; position: absolute; top: 0; right: 0; margin: 10px; } 

hh.js


 window.onload = function() { fetch("hh.txt?mode=nocache").then(data => data.text()).then(data => { animateText(data) }); } function animateText(data) { var ele = document.getElementById("text"), txt = data.split(""); var interval = setInterval(function(){ if(!txt[0]){ return clearInterval(interval); }; ele.innerHTML += txt.shift(); }, 150); } 

hh.txt


 Hello Hubr 


自定义字体也存在。 总计-一般网站的最少完整资源集。 如果在浏览器中打开index.html,将显示图片和题字。 javascript通过从hh.txt文件(通用PWA应用程序的最简单模型)中提取来加载该题词。

如果打开时没有sw.js,则它将是一个常规网站。 将Service Worker添加到我们的文件中。

sw.js
 // Caches var CURRENT_CACHES = { font: 'font-cache-v1', css:'css-cache-v1', js:'js-cache-v1', site: 'site-cache-v1', image: 'image-cache-v1' }; self.addEventListener('install', (event) => { self.skipWaiting(); console.log('Service Worker has been installed'); }); self.addEventListener('activate', (event) => { var expectedCacheNames = Object.keys(CURRENT_CACHES).map(function(key) { return CURRENT_CACHES[key]; }); // Delete out of date caches event.waitUntil( caches.keys().then(function(cacheNames) { return Promise.all( cacheNames.map(function(cacheName) { if (expectedCacheNames.indexOf(cacheName) == -1) { console.log('Deleting out of date cache:', cacheName); return caches.delete(cacheName); } }) ); }) ); console.log('Service Worker has been activated'); }); self.addEventListener('fetch', function(event) { console.log('Fetching:', event.request.url); event.respondWith(async function() { const cachedResponse = await caches.match(event.request); if (cachedResponse) { console.log("\tCached version found: " + event.request.url); return cachedResponse; } else { console.log("\tGetting from the Internet:" + event.request.url); return await fetchAndCache(event.request); } }()); }); function fetchAndCache(request) { return fetch(request) .then(function(response) { // Check if we received a valid response if (!response.ok) { return response; // throw Error(response.statusText); } var url = new URL(request.url); if (response.status < 400 && response.type === 'basic' && url.search.indexOf("mode=nocache") == -1 ) { var cur_cache; if (response.headers.get('content-type') && response.headers.get('content-type').indexOf("application/javascript") >= 0) { cur_cache = CURRENT_CACHES.js; } else if (response.headers.get('content-type') && response.headers.get('content-type').indexOf("text/css") >= 0) { cur_cache = CURRENT_CACHES.css; } else if (response.headers.get('content-type') && response.headers.get('content-type').indexOf("font") >= 0) { cur_cache = CURRENT_CACHES.font; } else if (response.headers.get('content-type') && response.headers.get('content-type').indexOf("image") >= 0) { cur_cache = CURRENT_CACHES.image; } else if (response.headers.get('content-type') && response.headers.get('content-type').indexOf("text") >= 0) { cur_cache = CURRENT_CACHES.site; } if (cur_cache) { console.log('\tCaching the response to', request.url); return caches.open(cur_cache).then(function(cache) { cache.put(request, response.clone()); return response; }); } } return response; }) .catch(function(error) { console.log('Request failed for: ' + request.url, error); throw error; }); } 


如您所见,我们为每种类型的资源创建五个缓存。 该站点缓存用于html文件。 所有资源均已缓存,但在GET查询中具有“ mode = nocache”的资源除外-这是我们对hh.txt文件的要求,其中带有题词行。
有时您会看到资源是从磁盘缓存中获取的。 在使用Service Worker开发应用程序时,这是一个常见问题,因此最好禁用磁盘缓存(浏览器缓存)。 而不是在我的浏览器中,而是在服务器上-例如,在
.htaccess
 # Cache-Control Headers <ifModule mod_headers.c> <FilesMatch (\.css|\.js|sprites\.png)$> Header unset ETag Header unset Expires Header set Cache-Control "no-cache" </FilesMatch> </IfModule> 

sw.js背后的逻辑很简单-“缓存回落到网络”。 首先,在缓存中检查所请求的资源,如果该资源存在,则将其取出并从那里返回到浏览器。 如果不是,则从网络获取它,然后返回到浏览器,并缓存该资源的副本。

在Chrom-a控制台中首次打开index.html页面之后,将显示有关安装和激活Service Worker的记录。 第二次打开后,将在存储中创建我们的缓存,并将我们的资源放入其中。 还可以看到,在随后的打开期间,仅对hh.txt的请求发送到Web服务器,所有其他资源均取自Service Worker-a。

屏幕截图


本地存储的index.html,hh.css,hh.js,hh.otf,logo.jpg-这是应用程序外壳,是静态资源和数据的外壳,在客户端上用作程序外壳。 该站点正常工作所需的所有动态信息是通过对服务器的javascript请求以及在应用程序shell-e中显示接收到的数据而获得的。 在我们的例子中,这是对text.txt的请求。

为了被称为​​功能齐全的PWA,“ Hello Habr”缺少一件事-智能手机主屏幕上的图标并以全屏模式启动。

为此,您需要在index.html中连接应用程序清单:
manifest.json
 { "short_name": "Hello Habr", "name": "Hello Habr - PWA example", "icons": [ { "src": "logo3.jpg", "type": "image/jpg", "sizes": "192x192" }, { "src": "logo2.jpg", "type": "image/jpg", "sizes": "512x512" } ], "start_url": "index.html", "background_color": "#3367D6", "display": "standalone", "scope": "/habr-pwa/hello-habr/", "theme_color": "#3367D6" } 

它在index.html中连接:
 <link rel="manifest" href="manifest.json"> 


之后,移动浏览器(以各自的方式)将提供在主屏幕上为应用程序创建快捷方式的功能。 通过快捷方式启动时,该应用程序将以独立模式打开-无需浏览器控件。 有关清单选项的更多详细信息,请参见Google Developers

Hello Habr应用程序至少具有PWA的所有功能,实际上就是它。 如您所见,为了将简单站点传输到PWA,您只需要连接清单和Service Worker文件。 sw.js使用的通用性很高。

下次,我们将完成的站点从PWA转移到CMS Joomla(该站点“开箱即用”,带有初始演示数据)。 而且,sw.js将几乎保持不变。

Source: https://habr.com/ru/post/zh-CN419585/


All Articles