วิธีรับบล็อก Jekyll ทำงานแบบออฟไลน์โดยใช้พนักงานบริการ
เผยแพร่แล้ว: 2017-01-26ไบต์สั้น: คุณรู้หรือไม่ว่า ด้วยการถือกำเนิดของ Service Workers เราสามารถเริ่มทำให้เว็บไซต์ทำงานแบบออฟไลน์ได้! เว็บแอปดังกล่าวเรียกว่า PWAs (Progressive Web Apps) ในวิธีการนี้ ฉันจะช่วยให้คุณใช้พนักงานบริการเพื่อทำให้บล็อก/เว็บไซต์ที่ใช้ Jekyll ทำงานแบบออฟไลน์และมีสิ่งเจ๋งๆ ที่มาพร้อมกับมัน
(หมายเหตุ : ตัวอย่างโค้ดในบทความนำมาจากที่เก็บโค้ดในบล็อกของฉัน สามารถอ้างอิงได้หากต้องการ หากคุณยังใหม่กับ Jekyll คุณสามารถอ่าน 3 Series Article ใน CSS Tricks ได้)
พื้นหลัง
ก่อนหน้านี้เคยเป็น App Cache ที่ใช้ไฟล์ yuk YAML ซึ่งมีการเข้ารหัสที่ยากมากในธรรมชาติ และไม่สามารถใช้เพื่อแคชเนื้อหาและหน้าเว็บแบบไดนามิกได้ เข้ามา พนักงานบริการ. Javascript API แบบธรรมดาที่ใช้เหตุการณ์ธรรมดาเพื่อแคชพนักงานบริการแบบไดนามิกเพื่อจัดเก็บสินทรัพย์ เพื่อให้สามารถใช้เพื่อให้บริการหน้าเว็บเมื่อไม่มีเครือข่าย
พนักงานบริการลงจอดใน Chrome Canary ในปี 2014 แต่ข้อมูลจำเพาะยังคงได้รับการปรับปรุง/เพิ่มเติมและออกแบบ ในปี 2015 และ 2016 ทีมงาน Chrome ของ Google ได้เผยแพร่เทคโนโลยีใหม่นี้ในเบราว์เซอร์อย่างหนัก มีเพียง Apple เท่านั้นที่ไม่รองรับสิ่งนี้ (แม้ในขณะที่เขียนบทความนี้) บนอุปกรณ์ของพวกเขา (ด้วยเหตุผลที่ไม่ทราบสาเหตุ) [พวกเขาไม่ได้เข้าร่วมในการอภิปรายข้อมูลจำเพาะเกี่ยวกับพนักงานบริการด้วยเช่นกัน]
พนักงานบริการคืออะไร? โดยพื้นฐานแล้วมันเป็นพนักงานเว็บเกี่ยวกับสเตียรอยด์ คุณลักษณะหนึ่งของผู้ปฏิบัติงานบนเว็บคือ งานทั้งหมดของผู้ปฏิบัติงานเว็บทำงานแยกจากกัน (แบบอะซิงโครนัส) จากเธรดการเรียกใช้ JavaScript หลัก (วนรอบเหตุการณ์) ฟีเจอร์นี้ช่วยเรียกใช้งานที่ใช้ CPU หรือหน่วยความจำสูง เช่น การคำนวณที่ซับซ้อนโดยไม่กระทบต่อประสิทธิภาพของอินเทอร์เฟซผู้ใช้ของเว็บแอป
Service Worker ให้เราแคช (เก็บไว้นาน) ทรัพย์สิน เช่น JavaScript, CSS, HTML, รูปภาพ, ไฟล์ฟอนต์ในแคชของผู้ให้บริการแคชของเบราว์เซอร์ ดังนั้นครั้งต่อไปที่ผู้ใช้โหลดหน้านั้นจะถูกโหลดแทบจะในทันที . และเนื่องจากในกลยุทธ์การแคชนี้ เบราว์เซอร์จะค้นหาความพร้อมใช้งานของสินทรัพย์ก่อนจากแคชของเจ้าหน้าที่บริการ หน้าเว็บจึงใช้งานได้แม้ในขณะที่ออฟไลน์! หากไม่มีเนื้อหาในแคช คำขอเครือข่ายจะถูกส่งเพื่อดึงข้อมูล
พนักงานบริการยังเปิดใช้งานการแจ้งเตือนแบบพุชที่เห็นได้ทั่วไปในหลายเว็บไซต์ในทุกวันนี้ รวมถึง Facebook, Whatsapp บนเว็บและ Twitter เราจะพูดถึงคุณลักษณะออฟไลน์เป็นหลัก วิธีการนี้ใช้เฉพาะกับ Jekyll อย่างไรก็ตาม โดยทั่วไปแล้วรหัสพนักงานบริการส่วนใหญ่ใช้กับเว็บไซต์ใดก็ได้
เนื่องจาก Jekyll ให้บริการเนื้อหาแบบสแตติก ( เป็นเครื่องสร้างไซต์แบบคงที่ duh! ) รหัสพนักงานบริการของเราจึงเป็นพื้นฐานและเข้าใจง่าย
มากันเถอะ:
ในเพจที่เกี่ยวข้องทั้งหมด สคริปต์ต่อไปนี้จะถูกดำเนินการ มันทำสิ่งต่อไปนี้:
- ตรวจสอบการมีอยู่ของ API พนักงานบริการในเบราว์เซอร์และการลงทะเบียนพนักงานบริการ
- เมื่อพนักงานบริการเปิดใช้งานแล้ว ให้ส่งข้อความสั้นๆ สั้นๆ ว่า toast/chip ไปยังผู้ใช้ว่าเว็บไซต์พร้อมใช้งานแบบออฟไลน์แล้ว
ฟังก์ชัน showOfflineToast() { ให้ offlineToast = document.querySelector('.offline-ready'); offlineToast.classList.add('ใช้งานอยู่'); setTimeout(ฟังก์ชัน(){ offlineToast.className = offlineToast.className.replace("ใช้งานอยู่", "").trim(); }, 5500); } // (1) ถ้า (navigator.serviceWorker) { navigator.serviceWorker.register ('/sw.js').then (ฟังก์ชัน (reg) { ถ้า (!reg.installing) กลับมา; console.log("[*] ServiceWorker กำลังติดตั้ง..."); var worker = reg.installing; worker.addEventListener ('statechange', ฟังก์ชัน () { if (worker.state == 'ซ้ำซ้อน') { console.log('[*] การติดตั้งล้มเหลว'); } ถ้า (worker.state == 'ติดตั้ง') { console.log('[*] ติดตั้งสำเร็จ!'); } // (2) ถ้า (worker.state == 'เปิดใช้งาน' && !navigator.serviceWorker.controller) { showOfflineToast(); } }); }); }
คุณสามารถเพิ่มโค้ดชิ้นนี้ในไฟล์ที่บอกว่า serviceWorker.html ภายในไดเร็กทอรี include ของโค้ด Jekyll ของคุณและ รวม ไว้ใน default.html โดยใช้เอ็นจินการสร้างเทมเพลตเหลวของ Jekyll
<!DOCTYPE html> <html> {% รวม head.html %} <body> {% รวม header.html %} <div class="page-content"> <div class="wrapper"> {{ เนื้อหา }} </div> </div> {% รวม footer.html %} <!-- มีโค้ดด้านบนในแท็กสคริปต์--> {% รวม serviceWorker.html %} <div class="offline-ready">ไซต์พร้อมใช้งานแบบออฟไลน์แล้ว</div> </body> </html>
ตอนนี้เป็นรหัสพนักงานบริการจริงที่ทำมายากล รหัสนี้อยู่ใน sw.js ที่รูทของ Jekyll Code ของคุณ
//sw.js --- เลย์เอาต์: null --- const staticCacheName = "gdad-s-river-static-v61"; console.log("กำลังติดตั้งพนักงานบริการ"); const filesToCache = [ "/", {% สำหรับหน้าใน site.html_pages %} '{{ page.url }}', {% สิ้นสุดสำหรับ %} {% สำหรับการโพสต์ใน site.posts %} '{{ post.url }}', {% สิ้นสุดสำหรับ %} // เป็นแบบอัตโนมัติแทนการป้อนด้วยตนเอง "/assets/images/bhavri-github-callbacks.png", "/assets/images/bhavri-github-issues.png", "/assets/images/jakethecake-svg-line-anime.png", "/assets/images/svg-animated-mast-text-shapes-tweet.png", "css/main.css", "/เกี่ยวกับ/", "/index.html" ];
staticCacheName คือเวอร์ชันแคชที่จะอัปเดตทุกครั้งที่ฉันทำการเปลี่ยนแปลงบางอย่างกับการตอบสนองที่แคชไว้ (เช่น ฉันทำการเปลี่ยนแปลงในไฟล์ CSS หรือโพสต์ในบล็อก) และฉันแค่กำหนดคำขอที่ฉันต้องการสกัดกั้นและแคชในอาร์เรย์ (ใช้ในตัวอย่างถัดไป)
//sw.js self.addEventListener ("ติดตั้ง", ฟังก์ชัน (e){ self.skip รอ (); e. waitUntil( caches.open (staticCacheName) จากนั้น (ฟังก์ชัน (แคช){ ส่งคืน cache.addAll (filesToCache); }) ) });
self.skipWaiting กล่าวคือทุกครั้งที่ไฟล์ sw.js นี้เปลี่ยนแปลง เวอร์ชันใหม่กว่าของผู้ปฏิบัติงานบริการไม่ควรเข้าคิว แต่เปิดใช้งานทันที (อาจมีผู้ใช้แจ้งให้รีเฟรชหน้าเว็บโดยให้ข้อความเช่น หน้าเว็บได้รับการปรับปรุง/เปลี่ยนแปลง คลิก รีเฟรช เพื่อโหลดโพสต์ใหม่หรืออะไรก็ตาม ) เวอร์ชันเก่าทิ้งไป
e.waitUntil อ้างจากเว็บไซต์ MDN:
“The ExtendableEvent.waitUntil() วิธีการขยายอายุของเหตุการณ์ สำหรับผู้ปฏิบัติงานบริการ การยืดอายุของเหตุการณ์จะป้องกันไม่ให้เบราว์เซอร์ยุติพนักงานบริการก่อนที่การดำเนินการแบบอะซิงโครนัสภายในเหตุการณ์จะเสร็จสิ้น”
ฉันเปิดแคชชื่อ gdad-s-river-static-v61 ซึ่งส่งคืนสัญญาด้วยชื่อแคชของฉัน จากนั้นฉันเรียก cache.addAll (ซึ่งใช้การดึงข้อมูล API ในพื้นหลัง) ซึ่งจะดึงคำขอทั้งหมดใน อาร์เรย์ที่จัดเตรียมไว้และแคชไว้
มาชมคลิปต่อไป!
//sw.js self.addEventListener ("เปิดใช้งาน", ฟังก์ชั่น (e){ e. waitUntil( caches.keys().then(ฟังก์ชัน(cacheNames){ กลับ Promise.all( cacheNames.filter (ฟังก์ชัน (ชื่อแคช){ ส่งคืน cacheName.startsWith("gdad-s-river-static-") && cacheName != staticCacheName; }).map(ฟังก์ชัน(ชื่อแคช){ ส่งคืน cache.delete (ชื่อแคช); }) )ß }) ) });
เมื่อพนักงานบริการเปิดใช้งาน ฉันมั่นใจว่าพนักงานบริการที่ไม่ใช่เวอร์ชันล่าสุดจะถูกลบ ตัวอย่างเช่น หากเวอร์ชันแคชล่าสุดของฉันคือ gdad-s-river-static-v61 และมีคนยังคงอยู่ใน gdad-s-river-static-v58 ในการเยี่ยมชมครั้งต่อไปของเขา/เธอ ฉันต้องการให้ไคลเอนต์นั้นไม่สนใจ ปั๊มทีละเวอร์ชัน แต่ให้ลบเวอร์ชันนั้นออกอย่างตรงไปตรงมาเพื่อติดตั้งเวอร์ชันล่าสุด
//sw.js self.addEventListener ("ดึงข้อมูล", ฟังก์ชัน (e){ e.respondWith( caches.match (e.request) จากนั้น (ฟังก์ชั่น (ตอบสนอง) { ตอบกลับ || ดึงข้อมูล (e.request); }) ) });
ในการดึงข้อมูล ฉันแค่บอกพนักงานบริการถึงวิธีการตอบสนองต่อคำขอเฉพาะที่ทำขึ้น (เนื่องจากเรากำลังแย่งชิงการตอบสนองที่ให้อำนาจ พนักงานบริการจะทำงานบนเว็บไซต์หรือที่รู้จักว่า https ที่ปลอดภัยเท่านั้น) ฉันบอกให้จับคู่คำขอกับคำขอที่แคชไว้ในเบราว์เซอร์ และหากไม่พบการตอบสนองต่อคำขอนั้นโดยเฉพาะ ให้ดึงข้อมูลผ่านเครือข่าย มิฉะนั้นจะให้บริการจากแคช
ธาดา! พนักงานบริการทำให้บล็อกขับเคลื่อน Jekyll ออฟไลน์!
เซอร์ไพรส์! สิ่งดีๆ:
คนเกียจคร้าน: สิ่งนี้จะไม่ทำงานบนอุปกรณ์ iOS
หากคุณเพิ่มไฟล์ web app manifest.json ที่รูทของโปรเจ็กต์ดังนี้:
{ "name": "gdad-s-river", "short_name": "gdad-s-แม่น้ำ", "theme_color": "#2196f3", "background_color": "#2196f3", "display": "แบบสแตนด์อโลน", "ขอบเขต": "/", "start_url": "/", "ไอคอน": [ { "src": "assets/images/favicon_images/android-icon-36x36.png", "ขนาด": "36x36", "type": "image\/png", "ความหนาแน่น": "0.75" }, { "src": "assets/images/favicon_images/android-icon-48x48.png", "ขนาด": "48x48", "type": "image\/png", "ความหนาแน่น": "1.0" }, { "src": "assets/images/favicon_images/android-icon-72x72.png", "ขนาด": "72x72", "type": "image\/png", "ความหนาแน่น": "1.5" }, { "src": "assets/images/favicon_images/android-icon-96x96.png", "ขนาด": "96x96", "type": "image\/png", "ความหนาแน่น": "2.0" }, { "src": "assets/images/favicon_images/android-icon-144x144.png", "ขนาด": "144x144", "type": "image\/png", "ความหนาแน่น": "3.0" }, { "src": "assets/images/favicon_images/android-icon-192x192.png", "ขนาด": "192x192", "type": "image\/png", "ความหนาแน่น": "4.0" } ] }
และเพิ่มลงในไฟล์ head.html ภายในแท็ก head
<head> <!-- ของบางอย่าง --> <link rel="manifest" href="/manifest.json"> <!-- ของบางอย่าง --> </head>
จากนั้น ในการเข้าชมเว็บไซต์ของคุณครั้งที่สอง (ภายใน 5 นาที) ผู้ใช้จะแจ้งให้เพิ่มเว็บไซต์ของคุณไปที่หน้าจอหลัก (เพื่อให้มีไอคอนอยู่ เช่นเดียวกับแอปที่มาพร้อมเครื่องอื่นๆ) ซึ่งคุณจะมีส่วนร่วมได้เช่นเดียวกัน แอพ
ทรัพยากร
- รายละเอียดของคุณสมบัติออฟไลน์ของพนักงานบริการและกลยุทธ์การแคชสามารถพบได้ในตำราอาหารออฟไลน์ของ Jake Archibald ที่ยอดเยี่ยมนี้
- หลักสูตร Udacity ฟรีที่มีรายละเอียดมากเกี่ยวกับทุกสิ่งที่คุณจำเป็นต้องรู้เกี่ยวกับพนักงานบริการและ IndexDB
คุณพบว่าบทความนี้ในบล็อก Jekyll น่าสนใจและเป็นประโยชน์หรือไม่ อย่าลืมแบ่งปันมุมมองและข้อเสนอแนะของคุณ
อ่าน เพิ่มเติม : Ecosia — เครื่องมือค้นหาที่ปลูกต้นไม้