ฟีเจอร์ทางสถาปัตยกรรมทั่วไปของเว็บแอปพลิเคชันแบบหน้าเดียว (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 ล่วงหน้าดังนี้
การแคช HTML, CSS และ JavaScript ของ Application Shell ล่วงหน้าสามารถทำได้ในเวิร์กโฟลว์ส่วนใหญ่ รวมถึงโปรเจ็กต์ที่ใช้ Bundler เมื่ออ่านเอกสารประกอบ คุณจะได้ทราบวิธีใช้ Workbox โดยตรงในการตั้งค่า Toolchain เพื่อสร้าง Service Worker ที่เหมาะกับโปรเจ็กต์ของคุณมากที่สุด ไม่ว่าจะเป็น SPA ก็ตาม
บทสรุป
การรวมโมเดล Application Shell กับโปรแกรมทำงานของบริการจะเป็นวิธีที่ยอดเยี่ยมสำหรับการแคชแบบออฟไลน์ โดยเฉพาะอย่างยิ่งหากคุณรวมฟังก์ชันการแคชล่วงหน้าเข้ากับกลยุทธ์แบบเครือข่ายเป็นหลักและกลับไปใช้กลยุทธ์การแคชสำหรับมาร์กอัปหรือการตอบกลับของ API ผลลัพธ์ที่ได้คือประสบการณ์การใช้งานที่รวดเร็วและเชื่อถือได้ซึ่งจะแสดงผลเชลล์แอปพลิเคชันของคุณทันทีเมื่อเข้าชมซ้ำ แม้ในสภาวะออฟไลน์