สร้าง PWA ด้วย Webpack และ Workbox

เผยแพร่แล้ว: 2022-03-10
สรุปโดยย่อ ↬ บทช่วยสอนนี้จะช่วยให้คุณแปลงแอปที่ไม่ได้ทำงานแบบออฟไลน์เป็น PWA ที่ทำงานออฟไลน์และแสดงไอคอนอัปเดตที่พร้อมใช้งาน คุณจะได้เรียนรู้วิธีเตรียมแคชเนื้อหาล่วงหน้าด้วยเวิร์กบ็อกซ์ จัดการแคชแบบไดนามิก รวมถึงจัดการการอัปเดต PWA ของคุณ ปฏิบัติตามและดูว่าคุณสามารถใช้เทคนิคเหล่านี้กับเว็บไซต์ของคุณได้อย่างไร

Progressive Web App (PWA) คือไซต์ที่ใช้เทคโนโลยีสมัยใหม่เพื่อมอบประสบการณ์ที่เหมือนแอปบนเว็บ เป็นคำศัพท์เฉพาะสำหรับเทคโนโลยีใหม่ๆ เช่น 'รายการแอปบนเว็บ', 'พนักงานบริการ' และอื่นๆ เมื่อรวมเข้าด้วยกัน เทคโนโลยีเหล่านี้จะช่วยให้คุณมอบประสบการณ์ผู้ใช้ที่รวดเร็วและมีส่วนร่วมกับเว็บไซต์ของคุณ

บทความนี้เป็นบทแนะนำทีละขั้นตอนสำหรับการเพิ่มพนักงานบริการไปยังเว็บไซต์หน้าเดียวที่มีอยู่ เจ้าหน้าที่บริการจะอนุญาตให้คุณทำให้เว็บไซต์ของคุณทำงานแบบออฟไลน์ได้ในขณะที่ยังแจ้งให้ผู้ใช้ทราบเกี่ยวกับการอัปเดตในเว็บไซต์ของคุณ โปรดทราบว่าสิ่งนี้อิงจากโปรเจ็กต์ขนาดเล็กที่มาพร้อมกับ Webpack ดังนั้นเราจะใช้ปลั๊กอิน Workbox Webpack (Workbox v4)

การใช้เครื่องมือเพื่อสร้างพนักงานบริการของคุณเป็นวิธีที่แนะนำ เนื่องจากจะช่วยให้คุณจัดการแคชได้อย่างมีประสิทธิภาพ เราจะใช้ Workbox ซึ่งเป็นชุดของไลบรารีที่ทำให้ง่ายต่อการสร้างรหัสพนักงานบริการของคุณ เพื่อสร้างพนักงานบริการของเราในบทช่วยสอนนี้

คุณสามารถใช้ Workbox ได้สามวิธีขึ้นอยู่กับโปรเจ็กต์ของคุณ:

  1. มี อินเทอร์เฟซบรรทัดคำสั่ง ซึ่งช่วยให้คุณรวมเวิร์กบ็อกซ์เข้ากับแอปพลิเคชันใดๆ ที่คุณมี
  2. มี โมดูล Node.js ซึ่งช่วยให้คุณรวมเวิร์กบ็อกซ์เข้ากับเครื่องมือสร้างโหนดใด ๆ เช่นอึกหรือเสียงฮึดฮัด
  3. มี ปลั๊กอิน webpack ซึ่งช่วยให้คุณรวมเข้ากับโปรเจ็กต์ที่สร้างด้วย Webpack ได้อย่างง่ายดาย

Webpack เป็นตัวรวมโมดูล เพื่อลดความซับซ้อน คุณสามารถคิดว่ามันเป็นเครื่องมือที่จัดการการพึ่งพา JavaScript ของคุณ ช่วยให้คุณสามารถนำเข้าโค้ด JavaScript จากไลบรารีและรวม JavaScript ของคุณเข้าด้วยกันเป็นไฟล์เดียวหรือหลายไฟล์

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

ในการเริ่มต้น ให้โคลนที่เก็บต่อไปนี้บนคอมพิวเตอร์ของคุณ:

 git clone [email protected]:jadjoubran/workbox-tutorial-v4.git cd workbox-tutorial-v4 npm install npm run dev

จากนั้นไปที่ https://localhost:8080/ คุณควรจะเห็นแอปสกุลเงินที่เราจะใช้ตลอดบทช่วยสอนนี้:

ภาพหน้าจอของแอปสกุลเงินที่เรากำลังสร้างในบทความนี้
'สกุลเงิน' คือ กปภ. ที่แสดงค่าธรรมเนียมการแปลงสกุลเงินเทียบกับสกุลเงินยูโร (€) (ตัวอย่างขนาดใหญ่)

เริ่มต้นด้วย App Shell

เปลือกแอปพลิเคชัน (หรือ 'เปลือกแอป') เป็นรูปแบบที่ได้รับแรงบันดาลใจจากแอปที่มาพร้อมเครื่อง จะช่วยให้แอปของคุณมีรูปลักษณ์ที่เป็นธรรมชาติมากขึ้น เพียงแค่ให้แอปมีเลย์เอาต์และโครงสร้างโดยไม่มีข้อมูลใด ๆ ซึ่งเป็นหน้าจอเปลี่ยนผ่านที่มุ่งปรับปรุงประสบการณ์การโหลดเว็บแอปของคุณ

ต่อไปนี้คือตัวอย่างบางส่วนของเชลล์แอปจากแอปที่มาพร้อมเครื่อง:

เชลล์แอป Google Inbox
Google Inbox App Shell: สองสามมิลลิวินาทีก่อนที่อีเมลจะโหลดเข้าสู่ App Shell (ตัวอย่างขนาดใหญ่)
เชลล์แอพ Twitter ดั้งเดิม
แอพเนทีฟของ Twitter บน Android: App Shell แสดงแถบนำทาง แท็บ และตัวโหลด (ตัวอย่างขนาดใหญ่)

และนี่คือตัวอย่างเชลล์แอปจาก PWAs:

App Shell ของ PWA . ของ Twitter
เปลือกแอปของ PWA ของ Twitter (ตัวอย่างขนาดใหญ่)
App Shell ของ PWA . ของ Flipkart
เปลือกแอปของ PWA ของ Flipkart (ตัวอย่างขนาดใหญ่)

ผู้ใช้ชอบประสบการณ์การโหลด App Shell เพราะไม่ชอบหน้าจอเปล่า หน้าจอว่างทำให้ผู้ใช้รู้สึกว่าเว็บไซต์ไม่โหลด มันทำให้พวกเขารู้สึกว่าเว็บไซต์ติดขัด

App Shell จะพยายามลงสีโครงสร้างการนำทางของแอปโดยเร็วที่สุด เช่น แถบนำทาง แถบแท็บ และตัวโหลดที่แสดงว่าเนื้อหาที่คุณร้องขอกำลังถูกโหลด

คุณจะสร้าง App Shell ได้อย่างไร?

รูปแบบเชลล์ของแอปจัดลำดับความสำคัญการโหลด HTML, CSS และ JavaScript ที่จะแสดงผลก่อน ซึ่งหมายความว่าเราจำเป็นต้องให้ความสำคัญกับทรัพยากรเหล่านั้นอย่างเต็มที่ ดังนั้นคุณต้องอินไลน์เนื้อหาเหล่านั้น ดังนั้น ในการสร้าง App Shell คุณเพียงแค่ต้องอินไลน์ HTML, CSS และ JavaScript ที่รับผิดชอบ App Shell แน่นอน คุณไม่ควรอินไลน์ทุกอย่างแต่ควรอยู่ภายในขีดจำกัดทั้งหมดประมาณ 30 ถึง 40KB

คุณสามารถดู App Shell แบบอินไลน์ได้ใน index.html คุณสามารถตรวจสอบซอร์สโค้ดได้โดยดูที่ไฟล์ index.html และดูตัวอย่างได้ในเบราว์เซอร์โดยลบองค์ประกอบ <main> ในเครื่องมือ dev:

สกุลเงิน PWA App Shell พร้อมแถบนำทาง & ตัวโหลด
App Shell ที่เรากำลังสร้างในบทความนี้ (ตัวอย่างขนาดใหญ่)

มันทำงานแบบออฟไลน์หรือไม่?

มาจำลองออฟไลน์กันเถอะ! เปิด DevTools ไปที่แท็บเครือข่ายและทำเครื่องหมายที่ช่อง 'ออฟไลน์' เมื่อคุณโหลดหน้าซ้ำ คุณจะเห็นว่าเราจะได้รับหน้าออฟไลน์ของเบราว์เซอร์

หน้าข้อผิดพลาดออฟไลน์ของเบราว์เซอร์
การร้องขอไปยังโฮมเพจล้มเหลว ดังนั้นเราจึงเห็นผลชัดเจน (ตัวอย่างขนาดใหญ่)

นั่นเป็นเพราะคำขอเริ่มต้นไปยัง / (ซึ่งจะโหลดไฟล์ index.html ) จะล้มเหลวเนื่องจากอินเทอร์เน็ตออฟไลน์ วิธีเดียวที่เราจะกู้คืนจากความล้มเหลวของคำขอนั้นคือการมีพนักงานบริการ

ลองนึกภาพคำขอโดยไม่มีพนักงานบริการ:

แอนิเมชั่นของคำขอเครือข่ายที่เปลี่ยนจากเบราว์เซอร์ของลูกค้าไปยังอินเทอร์เน็ต
คำขอเครือข่ายเปลี่ยนจากเบราว์เซอร์ไปยังอินเทอร์เน็ตและย้อนกลับ (ไอคอนจาก flaticon.com) (ตัวอย่างขนาดใหญ่)

พนักงานบริการคือพร็อกซีเครือข่ายที่ตั้งโปรแกรมได้ ซึ่งหมายความว่าอยู่ระหว่างหน้าเว็บของคุณและอินเทอร์เน็ต ซึ่งช่วยให้คุณควบคุมคำขอเครือข่ายขาเข้าและขาออกได้

แอนิเมชั่นของคำขอเครือข่ายที่ถูกขัดขวางโดยพนักงานบริการ
คำขอเครือข่ายถูกขัดขวางโดยพนักงานบริการ (ไอคอนจาก flaticon.com) (ตัวอย่างขนาดใหญ่)

สิ่งนี้มีประโยชน์เพราะตอนนี้เราสามารถกำหนดเส้นทางคำขอที่ล้มเหลวนี้ใหม่ไปยังแคชได้ (สมมติว่าเรามีเนื้อหาในแคช)

แอนิเมชั่นของคำขอเครือข่ายถูกดักฟังโดยพนักงานบริการและเปลี่ยนเส้นทางไปยังแคช
คำขอเครือข่ายถูกเปลี่ยนเส้นทางไปยังแคชเมื่อมีอยู่แล้วในแคช (ไอคอนจาก flaticon.com) (ตัวอย่างขนาดใหญ่)

พนักงานบริการยังเป็น Web Worker ประเภทหนึ่ง ซึ่งหมายความว่าทำงานแยกจากหน้าหลักของคุณ และไม่สามารถเข้าถึง window หรือวัตถุ document ได้

Precache The App Shell

เพื่อให้แอปของเราทำงานแบบออฟไลน์ เราจะเริ่มต้นด้วยการแคชล่วงหน้าของแอปเชลล์

เริ่มต้นด้วยการติดตั้งปลั๊กอิน Webpack Workbox:

 npm install --save-dev workbox-webpack-plugin

จากนั้นเราจะเปิดไฟล์ index.js และลงทะเบียนพนักงานบริการ:

 if ("serviceWorker" in navigator){ window.addEventListener("load", () => { navigator.serviceWorker.register("/sw.js"); }) }

ถัดไป เปิดไฟล์ webpack.config.js และกำหนดค่าปลั๊กอิน Webpack ของ Workbox:

 //add at the top const WorkboxWebpackPlugin = require("workbox-webpack-plugin"); //add inside the plugins array: plugins: [ … , new WorkboxWebpackPlugin.InjectManifest({ swSrc: "./src/src-sw.js", swDest: "sw.js" }) ]

ซึ่งจะสั่งให้ Workbox ใช้ไฟล์ ./src/src-sw.js ของเราเป็นฐาน ไฟล์ที่สร้างขึ้นจะเรียกว่า sw.js และจะอยู่ในโฟลเดอร์ dist

จากนั้นสร้างไฟล์ ./src/src-sw.js ที่ระดับรูทและเขียนสิ่งต่อไปนี้ไว้ข้างใน:

 workbox.precaching.precacheAndRoute(self.__precacheManifest);

หมายเหตุ : ตัวแปร self.__precacheManifest จะถูกนำเข้าจากไฟล์ที่จะสร้างแบบไดนามิกโดยเวิร์กบ็อกซ์

ตอนนี้ คุณพร้อมที่จะสร้างโค้ดของคุณด้วย npm run build และ Workbox จะสร้างไฟล์สองไฟล์ภายในโฟลเดอร์ dist :

  • precache-manifest.66cf63077c7e4a70ba741ee9e6a8da29.js
  • sw.js

sw.js นำเข้าเวิร์กบ็อกซ์จาก CDN เช่นเดียวกับ precache-manifest.[chunkhash].js

 //precache-manifest.[chunkhash].js file self.__precacheManifest = (self.__precacheManifest || []).concat([ "revision": "ba8f7488757693a5a5b1e712ac29cc28", "url": "index.html" }, "url": "main.49467c51ac5e0cb2b58e.js" ]);

รายการ precache แสดงรายการชื่อของไฟล์ที่ประมวลผลโดย webpack และจบลงในโฟลเดอร์ dist ของคุณ เราจะใช้ไฟล์เหล่านี้เพื่อเตรียมแคชล่วงหน้าในเบราว์เซอร์ ซึ่งหมายความว่าเมื่อเว็บไซต์ของคุณโหลดในครั้งแรกและลงทะเบียนพนักงานบริการ เว็บไซต์จะแคชสินทรัพย์เหล่านี้เพื่อให้สามารถใช้งานได้ในครั้งต่อไป

คุณยังสังเกตได้ว่าบางรายการมี 'การแก้ไข' ในขณะที่บางรายการไม่มี นั่นเป็นเพราะว่าบางครั้งการแก้ไขสามารถอนุมานได้จาก chunkhash จากชื่อไฟล์ ตัวอย่างเช่น มาดูชื่อไฟล์กันดีกว่า main.49467c51ac5e0cb2b58e.js มีการแก้ไขอยู่ในชื่อไฟล์ซึ่งเป็น chunkhash 49467c51ac5e0cb2b58e

ซึ่งช่วยให้ Workbox เข้าใจว่าไฟล์ของคุณเปลี่ยนแปลงเมื่อใด เพื่อล้างหรืออัปเดตไฟล์ที่เปลี่ยนแปลงเท่านั้น แทนที่จะทิ้งแคชทั้งหมดทุกครั้งที่คุณเผยแพร่เวอร์ชันใหม่ของพนักงานบริการ

ครั้งแรกที่คุณโหลดหน้า เจ้าหน้าที่บริการจะทำการติดตั้ง คุณสามารถเห็นได้ใน DevTools ขั้นแรก ร้องขอไฟล์ sw.js ซึ่งจะร้องขอไฟล์อื่นๆ ทั้งหมด มีการทำเครื่องหมายด้วยไอคอนรูปเฟืองอย่างชัดเจน

สกรีนช็อตของแท็บเครือข่าย DevTools เมื่อติดตั้งพนักงานบริการ
คำขอที่มีเครื่องหมาย ️ เป็นคำขอที่เริ่มต้นโดยพนักงานบริการ (ตัวอย่างขนาดใหญ่)

ดังนั้น Workbox จะเริ่มต้นและจะทำการ precache ไฟล์ทั้งหมดที่อยู่ใน precache-manifest สิ่งสำคัญคือต้องตรวจสอบอีกครั้งว่าคุณไม่มีไฟล์ที่ไม่จำเป็นในไฟล์ precache -manifest เช่น ไฟล์ .map หรือไฟล์ที่ไม่ได้เป็นส่วนหนึ่งของเชลล์แอป

ในแท็บเครือข่าย เราจะเห็นคำขอที่มาจากพนักงานบริการ และตอนนี้หากคุณพยายามออฟไลน์ เปลือกของแอปนั้นได้รับแคชล่วงหน้าแล้ว ดังนั้นมันจึงทำงานแม้ว่าเราจะออฟไลน์อยู่!

สกรีนช็อตของแท็บ Dev Tools Network ที่แสดงการเรียก API ล้มเหลว
การเรียก API ล้มเหลวเมื่อเราออฟไลน์ (ตัวอย่างขนาดใหญ่)

แคชเส้นทางไดนามิก

คุณสังเกตไหมว่าเมื่อเราออฟไลน์ เปลือกของแอปทำงานได้ แต่ไม่ใช่ข้อมูลของเรา นั่นเป็นเพราะการเรียก API เหล่านี้ไม่ได้เป็นส่วนหนึ่งของ precached app shell เมื่อไม่มีการเชื่อมต่ออินเทอร์เน็ต คำขอเหล่านี้จะล้มเหลวและผู้ใช้จะไม่เห็นข้อมูลสกุลเงิน

อย่างไรก็ตาม คำขอเหล่านี้ไม่สามารถพรีแคชล่วงหน้าได้ เนื่องจากค่าของคำขอเหล่านี้มาจาก API นอกจากนี้ เมื่อคุณเริ่มมีหลายหน้า คุณไม่ต้องการแคชคำขอ API ทั้งหมดในครั้งเดียว คุณต้องการแคชไว้เมื่อผู้ใช้เข้าชมหน้านั้นแทน

เราเรียกสิ่งเหล่านี้ว่า 'ข้อมูลแบบไดนามิก' มักจะรวมถึงการเรียก API เช่นเดียวกับรูปภาพและทรัพย์สินอื่นๆ ที่ร้องขอเมื่อผู้ใช้ดำเนินการบางอย่างในเว็บไซต์ของคุณ (เช่น เมื่อพวกเขาเรียกดูหน้าใหม่)

คุณสามารถแคชสิ่งเหล่านี้ได้โดยใช้โมดูลการกำหนดเส้นทางของ Workbox โดยใช้วิธีดังนี้:

 //add in src/src-sw.js workbox.routing.registerRoute( /https:\/\/api\.exchangeratesapi\.io\/latest/, new workbox.strategies.NetworkFirst({ cacheName: "currencies", plugins: [ new workbox.expiration.Plugin({ maxAgeSeconds: 10 * 60 // 10 minutes }) ] }) );

การดำเนินการนี้จะตั้งค่าการแคชแบบไดนามิกสำหรับ URL คำขอใดๆ ที่ตรงกับ URL https://api.exchangeratesapi.io/latest

กลยุทธ์แคชที่เราใช้ในที่นี้เรียกว่า NetworkFirst ; มีอีกสองตัวที่มักใช้:

  1. CacheFirst
  2. StaleWhileRevalidate

CacheFirst จะค้นหาในแคชก่อน หากไม่พบก็จะได้รับจากเครือข่าย StaleWhileRevalidate จะไปที่เครือข่ายและแคชพร้อมกัน ส่งคืนการตอบกลับของแคชไปยังหน้า (ในขณะที่อยู่ในพื้นหลัง) แคชจะใช้การตอบสนองของเครือข่ายใหม่เพื่ออัปเดตแคชในครั้งต่อไปที่มีการใช้งาน

สำหรับกรณีการใช้งาน เราต้องเลือกใช้ NetworkFirst เพราะเรากำลังรับมือกับอัตราแลกเปลี่ยนที่เปลี่ยนแปลงบ่อยมาก อย่างไรก็ตาม เมื่อผู้ใช้ออฟไลน์ อย่างน้อย เราสามารถแสดงอัตราให้พวกเขาเหมือนเมื่อ 10 นาทีที่แล้ว นั่นคือเหตุผลที่เราใช้ปลั๊กอินการหมดอายุโดยตั้งค่า maxAgeSeconds เป็น 10 * 60 วินาที

จัดการการอัปเดตแอป

ทุกครั้งที่ผู้ใช้โหลดหน้าของคุณ เบราว์เซอร์จะเรียกใช้รหัส navigator.serviceWorker.register แม้ว่าพนักงานบริการจะได้รับการติดตั้งและใช้งานอยู่แล้ว ซึ่งช่วยให้เบราว์เซอร์ตรวจพบว่ามีพนักงานบริการเวอร์ชันใหม่หรือไม่ เมื่อเบราว์เซอร์สังเกตเห็นว่าไฟล์นั้นไม่มีการเปลี่ยนแปลง มันก็แค่ข้ามการโทรลงทะเบียน เมื่อไฟล์นั้นเปลี่ยนแปลงไป เบราว์เซอร์จะเข้าใจว่ามีพนักงานบริการรุ่นใหม่ ดังนั้นจึง ติดตั้งผู้ปฏิบัติงานบริการใหม่ควบคู่ไปกับพนักงานบริการที่กำลังทำงาน อยู่

อย่างไรก็ตาม จะหยุดชั่วคราวที่ขั้นตอนการ installed/waiting เนื่องจากสามารถเปิดใช้งานพนักงานบริการได้เพียงคนเดียวในเวลาเดียวกัน

วงจรชีวิตของพนักงานบริการ: แยกวิเคราะห์ ติดตั้ง/รอ เปิดใช้งาน & ซ้ำซ้อน
วงจรชีวิตที่เรียบง่ายของพนักงานบริการ (ตัวอย่างขนาดใหญ่)

เฉพาะเมื่อปิดหน้าต่างเบราว์เซอร์ทั้งหมดที่ควบคุมโดยพนักงานบริการคนก่อน จึงจะปลอดภัยสำหรับการเปิดใช้งานพนักงานบริการใหม่

คุณยังสามารถควบคุมสิ่งนั้นได้ด้วยตนเองโดยการเรียก skipWaiting() (หรือ self.skipWaiting() เนื่องจาก self เป็นบริบทการดำเนินการทั่วโลกในพนักงานบริการ) อย่างไรก็ตาม ส่วนใหญ่คุณควรทำอย่างนั้นหลังจากถามผู้ใช้ว่าต้องการรับการอัปเดตล่าสุดหรือไม่

โชคดีที่ workbox-window ช่วยให้เราบรรลุเป้าหมายนี้ เป็นไลบรารีหน้าต่างใหม่ที่เปิดตัวใน Workbox v4 ที่มีจุดมุ่งหมายเพื่อลดความซับซ้อนของงานทั่วไปที่ด้านข้างของหน้าต่าง

เริ่มต้นด้วยการติดตั้งดังต่อไปนี้:

 npm install workbox-window

ถัดไป นำเข้า Workbox ที่ด้านบนของไฟล์ index.js :

 import { Workbox } from "workbox-window";

จากนั้นเราจะแทนที่รหัสการลงทะเบียนของเราด้วยด้านล่าง:

 if ("serviceWorker" in navigator) { window.addEventListener("load", () => { const wb = new Workbox("/sw.js"); wb.register(); }); }

จากนั้นเราจะพบปุ่มอัปเดตซึ่งมีรหัส อัปเดตแอป และฟังเหตุการณ์ workbox-waiting งาน:

 //add before the wb.register() const updateButton = document.querySelector("#app-update"); // Fires when the registered service worker has installed but is waiting to activate. wb.addEventListener("waiting", event => { updateButton.classList.add("show"); updateButton.addEventListener("click", () => { // Set up a listener that will reload the page as soon as the previously waiting service worker has taken control. wb.addEventListener("controlling", event => { window.location.reload(); }); // Send a message telling the service worker to skip waiting. // This will trigger the `controlling` event handler above. wb.messageSW({ type: "SKIP_WAITING" }); }); });

รหัสนี้จะแสดงปุ่มอัปเดตเมื่อมีการอัปเดตใหม่ (ดังนั้น เมื่อพนักงานบริการอยู่ในสถานะรอ) และจะส่งข้อความ SKIP_WAITING ไปยังพนักงานบริการ

เราจำเป็นต้องอัปเดตไฟล์พนักงานบริการและจัดการเหตุการณ์ SKIP_WAITING ให้เรียก skipWaiting :

 //add in src-sw.js addEventListener("message", event => { if (event.data && event.data.type === "SKIP_WAITING") { skipWaiting(); });

ตอนนี้ให้รัน npm run dev จากนั้นโหลดหน้าซ้ำ ไปที่รหัสของคุณและอัปเดตชื่อแถบนำทางเป็น "Navbar v2" โหลดหน้าซ้ำอีกครั้ง และคุณควรจะเห็นไอคอนอัปเดต

ห่อ

ขณะนี้เว็บไซต์ของเราทำงานแบบออฟไลน์และสามารถแจ้งให้ผู้ใช้ทราบเกี่ยวกับการอัปเดตใหม่ๆ โปรดจำไว้ว่า ปัจจัยที่สำคัญที่สุดในการสร้างการประปาส่วนภูมิภาคคือประสบการณ์ของผู้ใช้ มุ่งเน้นที่การสร้างประสบการณ์ที่ผู้ใช้ของคุณใช้งานง่ายเสมอ เราในฐานะนักพัฒนา มักจะตื่นเต้นกับเทคโนโลยีมากเกินไป และมักจะจบลงด้วยการลืมผู้ใช้ของเรา

หากคุณต้องการก้าวไปอีกขั้น คุณสามารถเพิ่มรายการเว็บแอป ซึ่งจะทำให้ผู้ใช้ของคุณเพิ่มไซต์ลงในหน้าจอหลักได้ และหากคุณต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับ Workbox คุณสามารถค้นหาเอกสารอย่างเป็นทางการได้จากเว็บไซต์ Workbox

อ่านเพิ่มเติม เกี่ยวกับ SmashingMag:

  • คุณสามารถสร้างรายได้ด้วยแอพมือถือหรือ กปภ. ได้หรือไม่?
  • คู่มือที่กว้างขวางสำหรับแอปพลิเคชันเว็บแบบก้าวหน้า
  • Native และ PWA: ทางเลือก ไม่ใช่ผู้ท้าชิง!
  • การสร้าง กปภ. โดยใช้ Angular 6