วิธีรับบล็อก 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 — เครื่องมือค้นหาที่ปลูกต้นไม้
