ฟีเจอร์ทางสถาปัตยกรรมทั่วไปของเว็บแอปพลิเคชันแบบหน้าเดียว (SPA) คือชุด HTML, CSS และ JavaScript เพียงเล็กน้อยที่จำเป็นต่อการเพิ่มประสิทธิภาพฟังก์ชันการทำงานทั่วโลกของแอปพลิเคชัน ในทางปฏิบัติแล้ว เครื่องมือดังกล่าวมักจะเป็นส่วนหัว การนำทาง และองค์ประกอบอินเทอร์เฟซผู้ใช้ทั่วไปอื่นๆ ที่คงอยู่ในทุกหน้า เมื่อโปรแกรมทำงานของบริการแคช HTML ของ UI ขั้นต่ำและเนื้อหาที่อ้างอิงนี้ล่วงหน้า เราเรียกการดำเนินการนี้ว่า Application Shell
Application Shell มีบทบาทสำคัญในประสิทธิภาพที่แอปพลิเคชันเว็บรับรู้ แอปเป็นสิ่งแรกที่โหลด ดังนั้นจึงเป็นสิ่งแรกที่ผู้ใช้เห็นขณะที่รอให้เนื้อหาสร้างอินเทอร์เฟซผู้ใช้
แม้ว่า Application Shell จะโหลดได้เร็ว หากเครือข่ายพร้อมใช้งานและค่อนข้างรวดเร็ว แต่ Service Worker ที่แคช App Shell ล่วงหน้าและเนื้อหาที่เกี่ยวข้องจะทำให้โมเดล Application Shell ได้รับประโยชน์เพิ่มเติมดังนี้
- ประสิทธิภาพที่เชื่อถือได้และสม่ำเสมอสำหรับการเข้าชมซ้ำ ในการเข้าชมแอปที่ไม่ได้ติดตั้ง Service Worker เป็นครั้งแรก มาร์กอัปของแอปพลิเคชันและเนื้อหาที่เกี่ยวข้องจะต้องโหลดจากเครือข่ายก่อน โปรแกรมทำงานของบริการจึงจะใส่ลงในแคชได้ อย่างไรก็ตาม การเข้าชมซ้ำจะดึง Application Shell จากแคช ซึ่งหมายความว่าการโหลดและการแสดงผลจะเกิดขึ้นทันที
- การเข้าถึงฟังก์ชันการทำงานที่เชื่อถือได้ในสถานการณ์ออฟไลน์ บางครั้งการเข้าถึงอินเทอร์เน็ตนั้นขาดหายเป็นช่วงๆ หรือเข้าถึงไม่ได้เลย และ "เราไม่พบเว็บไซต์นั้น" ที่น่ากลัว โดยหน้าจอจะหลุดออกไป โมเดล Application Shell ช่วยแก้ปัญหานี้ด้วยการตอบกลับคำขอการนำทางที่มีมาร์กอัป Application Shell จากแคช แม้ว่าจะมีผู้เข้าชม URL ในเว็บแอปซึ่งไม่เคยเข้าชมมาก่อน แต่ระบบจะแสดง Application Shell จากแคชและอาจป้อนข้อมูลเนื้อหาที่เป็นประโยชน์ได้
กรณีที่ควรใช้ Application Shell Model
Application Shell จะเหมาะสมที่สุดเมื่อคุณมีองค์ประกอบของอินเทอร์เฟซผู้ใช้ทั่วไปที่ไม่เปลี่ยนเส้นทางแต่ละเส้นทาง แต่เป็นเนื้อหา SPA ส่วนใหญ่มีแนวโน้มที่จะใช้โมเดล Application Shell ที่มีประสิทธิภาพอยู่แล้ว
หากข้อมูลนี้ตรงกับโปรเจ็กต์ของคุณและคุณต้องการเพิ่ม Service Worker เพื่อปรับปรุงความเสถียรและประสิทธิภาพ Application Shell ควรมีลักษณะดังนี้
- โหลดเร็ว
- ใช้เนื้อหาแบบคงที่จากอินสแตนซ์
Cache
- มีองค์ประกอบทั่วไปในอินเทอร์เฟซ เช่น ส่วนหัวและแถบด้านข้าง โดยแยกจากเนื้อหาของหน้าเว็บ
- เรียกและแสดงเนื้อหาเฉพาะหน้าเว็บ
- หากเป็นไปได้ คุณสามารถแคชเนื้อหาแบบไดนามิกเพื่อดูแบบออฟไลน์ได้
Application Shell จะโหลดเนื้อหาเฉพาะหน้าเว็บแบบไดนามิกผ่าน API หรือเนื้อหาที่รวมอยู่ใน JavaScript นอกจากนี้ ยังควรอัปเดตตัวเองด้วยหากมาร์กอัปของ Application Shell มีการเปลี่ยนแปลง การอัปเดต Service Worker ควรรับ Application Shell ใหม่และแคชโดยอัตโนมัติ
การสร้าง Application Shell
Application Shell ควรแยกเป็นอิสระจากเนื้อหา แต่ก็ควรระบุฐานสำหรับการใส่เนื้อหาภายใน ตามหลักแล้วควรมีขนาดเล็กที่สุด แต่มีเนื้อหาที่มีความหมายเพียงพอในการดาวน์โหลดครั้งแรกที่ผู้ใช้เข้าใจว่าประสบการณ์โหลดได้อย่างรวดเร็ว
ยอดคงเหลือที่เหมาะสมจะขึ้นอยู่กับแอปของคุณ Application Shell สำหรับแอป Trained To Thrill ของ Jake Archibald มีส่วนหัวที่มีปุ่มรีเฟรชเพื่อดึงเนื้อหาใหม่จาก Flickr
มาร์กอัป Application Shell จะแตกต่างกันไปในแต่ละโปรเจ็กต์ แต่ตัวอย่างหนึ่งของไฟล์ index.html
ที่ระบุต้นแบบของแอปพลิเคชัน
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
Application Shell Example
</title>
<link rel="manifest" href="/manifest.json">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="styles/global.css">
</head>
<body>
<header class="header">
<!-- Application header -->
<h1 class="header__title">Application Shell Example</h1>
</header>
<nav class="nav">
<!-- Navigation items -->
</nav>
<main id="app">
<!-- Where the application content populates -->
</main>
<div class="loader">
<!-- Spinner/content placeholders -->
</div>
<!-- Critical application shell logic -->
<script src="app.js"></script>
<!-- Service worker registration script -->
<script>
if ('serviceWorker' in navigator) {
// Register a service worker after the load event
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js');
});
}
</script>
</body>
</html>
อย่างไรก็ตาม คุณสร้าง Application Shell สำหรับโปรเจ็กต์ของคุณ ไฟล์ดังกล่าวต้องมีลักษณะเฉพาะต่อไปนี้
- HTML ควรมีพื้นที่ที่แยกออกจากกันอย่างชัดเจนสำหรับองค์ประกอบของอินเทอร์เฟซผู้ใช้แต่ละรายการ ในตัวอย่างข้างต้น จะรวมถึงส่วนหัวของแอปพลิเคชัน การนำทาง พื้นที่เนื้อหาหลัก และพื้นที่สำหรับ "ตัวหมุน" ที่กำลังโหลด ที่ปรากฏเฉพาะเมื่อเนื้อหากำลังโหลดเท่านั้น
- JavaScript และ CSS แรกที่โหลดสำหรับ Application Shell ควรมีค่าน้อยที่สุด และเกี่ยวข้องกับฟังก์ชันการทำงานของ Application Shell เท่านั้น ไม่ใช่ตัวเนื้อหา เพื่อให้แอปพลิเคชันแสดงผล Shell โดยเร็วที่สุดและลดการทำงานของเทรดหลักลงจนกว่าเนื้อหาจะปรากฏขึ้น
- สคริปต์ในหน้าที่ลงทะเบียน Service Worker
เมื่อสร้าง Application Shell แล้ว คุณจะสร้าง Service Worker เพื่อแคชทั้ง App Shell และเนื้อหาได้
การแคช Application Shell
Application Shell และเนื้อหาที่จำเป็นคือสิ่งที่โปรแกรมทำงานของบริการควรแคชล่วงหน้าทันทีเมื่อติดตั้ง สมมติว่า Application Shell เหมือนกับตัวอย่างด้านบน มาดูกันว่าเราจะทำให้สำเร็จในตัวอย่าง Workbox พื้นฐานที่ใช้ workbox-build
ได้อย่างไร
// build-sw.js
import {generateSW} from 'workbox-build';
// Where the generated service worker will be written to:
const swDest = './dist/sw.js';
generateSW({
swDest,
globDirectory: './dist',
globPatterns: [
// The necessary CSS and JS for the app shell
'**/*.js',
'**/*.css',
// The app shell itself
'shell.html'
],
// All navigations for URLs not precached will use this HTML
navigateFallback: 'shell.html'
}).then(({count, size}) => {
console.log(`Generated ${swDest}, which precaches ${count} assets totaling ${size} bytes.`);
});
การกำหนดค่านี้ที่จัดเก็บไว้ใน build-sw.js
จะนำเข้า CSS และ JavaScript ของแอป รวมถึงไฟล์มาร์กอัป Application Shell ที่อยู่ใน shell.html
สคริปต์จะทำงานกับโหนดดังนี้
node build-sw.js
ระบบจะเขียน Service Worker ที่สร้างขึ้นไปยัง ./dist/sw.js
และจะบันทึกข้อความต่อไปนี้เมื่อเสร็จสิ้น
Generated ./dist/sw.js, which precaches 5 assets totaling 44375 bytes.
เมื่อโหลดหน้าเว็บ โปรแกรมทำงานของบริการจะแคชมาร์กอัปเชลล์ของแอปพลิเคชันและทรัพยากร Dependency ล่วงหน้าดังนี้
![ภาพหน้าจอของแผงเครือข่ายในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome ที่แสดงรายการเนื้อหาที่ดาวน์โหลดจากเครือข่าย เนื้อหาที่แคชล่วงหน้าโดย Service Worker จะแตกต่างจากเนื้อหาอื่นๆ ที่มีเฟืองทางด้านซ้ายในแถว ไฟล์ JavaScript และ CSS หลายไฟล์ได้รับการแคชล่วงหน้าโดย Service Worker ขณะติดตั้ง](https://developer.chrome.com/static/docs/workbox/app-shell-model/image/a-screenshot-the-network-96ad6896c678b.png?authuser=8&hl=th)
การแคช HTML, CSS และ JavaScript ของ Application Shell ล่วงหน้าสามารถทำได้ในเวิร์กโฟลว์ส่วนใหญ่ รวมถึงโปรเจ็กต์ที่ใช้ Bundler เมื่ออ่านเอกสารประกอบ คุณจะได้ทราบวิธีใช้ Workbox โดยตรงในการตั้งค่า Toolchain เพื่อสร้าง Service Worker ที่เหมาะกับโปรเจ็กต์ของคุณมากที่สุด ไม่ว่าจะเป็น SPA ก็ตาม
บทสรุป
การรวมโมเดล Application Shell กับโปรแกรมทำงานของบริการจะเป็นวิธีที่ยอดเยี่ยมสำหรับการแคชแบบออฟไลน์ โดยเฉพาะอย่างยิ่งหากคุณรวมฟังก์ชันการแคชล่วงหน้าเข้ากับกลยุทธ์แบบเครือข่ายเป็นหลักและกลับไปใช้กลยุทธ์การแคชสำหรับมาร์กอัปหรือการตอบกลับของ API ผลลัพธ์ที่ได้คือประสบการณ์การใช้งานที่รวดเร็วและเชื่อถือได้ซึ่งจะแสดงผลเชลล์แอปพลิเคชันของคุณทันทีเมื่อเข้าชมซ้ำ แม้ในสภาวะออฟไลน์