บทนำ
การที่แอปพลิเคชันบนเว็บเป็นสิ่งที่สามารถเข้าถึงแบบออฟไลน์ได้มีความสำคัญมากขึ้นเรื่อยๆ ได้ เบราว์เซอร์ทุกตัวสามารถแคชหน้าเว็บและทรัพยากรไว้เป็นเวลานานได้หากได้รับคำสั่งให้ดำเนินการ แต่เบราว์เซอร์สามารถนำรายการแต่ละรายการออกจากแคชได้ทุกเมื่อเพื่อเพิ่มพื้นที่ให้กับรายการอื่นๆ HTML5 แก้ปัญหาบางอย่างที่ทำให้เกิดความไม่สะดวกเมื่อออฟไลน์ด้วยอินเทอร์เฟซ ApplicationCache การใช้อินเทอร์เฟซแคชจะช่วยให้แอปพลิเคชันของคุณมีข้อดี 3 ข้อดังนี้
- การท่องเว็บแบบออฟไลน์ - ผู้ใช้ไปยังส่วนต่างๆ ของเว็บไซต์ได้แม้จะออฟไลน์อยู่
- ความเร็ว - ทรัพยากรมาจากดิสก์โดยตรงโดยไม่ต้องผ่านเครือข่าย
- ความยืดหยุ่น - หากเว็บไซต์หยุดทำงานเพื่อ "การบำรุงรักษา" (เช่น มีคนทำให้ทุกอย่างเสียหายโดยไม่ตั้งใจ) ผู้ใช้จะได้รับประสบการณ์การใช้งานแบบออฟไลน์
แคชของแอปพลิเคชัน (หรือ AppCache) ช่วยให้นักพัฒนาซอฟต์แวร์สามารถระบุไฟล์ที่เบราว์เซอร์ควรแคช และทำให้สามารถใช้ได้สำหรับผู้ใช้ออฟไลน์ แอปของคุณจะโหลดและทำงานได้อย่างถูกต้องแม้ว่าผู้ใช้จะกดปุ่มรีเฟรชในขณะออฟไลน์
ไฟล์ Manifest ของแคช
ไฟล์ Manifest ของแคชคือไฟล์ข้อความธรรมดาที่แสดงรายการทรัพยากรที่เบราว์เซอร์ควรแคชไว้สําหรับการเข้าถึงแบบออฟไลน์
การอ้างอิงไฟล์ Manifest
หากต้องการเปิดใช้แคชแอปพลิเคชันสำหรับแอป ให้ใส่แอตทริบิวต์ไฟล์ Manifest ในแท็ก html
ของเอกสาร ดังนี้
<html manifest="example.appcache">
...
</html>
คุณควรใส่แอตทริบิวต์ manifest
ในทุกหน้าของเว็บแอปพลิเคชันที่คุณต้องการแคช เบราว์เซอร์จะไม่แคชหน้าเว็บหากไม่มีแอตทริบิวต์ manifest
(เว้นแต่จะระบุไว้อย่างชัดเจนในไฟล์ Manifest เอง) ซึ่งหมายความว่าหน้าเว็บใดก็ตามที่ผู้ใช้ไปยังหน้านั้นซึ่งมี manifest
จะเพิ่มลงในแคชแอปพลิเคชันโดยปริยาย
คุณจึงไม่จำเป็นต้องระบุทุกหน้าในไฟล์ Manifest หากหน้าเว็บชี้ไปยังไฟล์ Manifest จะไม่มีวิธีป้องกันไม่ให้แคชหน้านี้
คุณดู URL ที่แคชของแอปพลิเคชันควบคุมได้โดยไปที่ about://://appcache-internals/ ใน Chrome คุณจะล้างแคชและดูรายการต่างๆ ได้จากที่นี่ มีเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ที่คล้ายกันใน Firefox
แอตทริบิวต์ manifest
สามารถชี้ไปยัง URL ที่สมบูรณ์หรือเส้นทางแบบสัมพัทธ์ได้ แต่ URL ที่สมบูรณ์ต้องอยู่ภายใต้ต้นทางเดียวกับเว็บแอปพลิเคชัน
ไฟล์ Manifest อาจมีนามสกุลไฟล์ใดก็ได้ แต่ต้องแสดงด้วยประเภท MIME ที่ถูกต้อง (ดูด้านล่าง)
<html manifest="http://www.example.com/example.mf">
...
</html>
ไฟล์ Manifest ต้องแสดงด้วยประเภท MIME text/cache-manifest
คุณอาจต้องเพิ่มประเภทไฟล์ที่กำหนดเองลงในการกำหนดค่าเว็บเซิร์ฟเวอร์หรือ .htaccess
เช่น หากต้องการแสดงประเภท mime นี้ใน Apache ให้เพิ่มบรรทัดนี้ลงในไฟล์การกําหนดค่า
AddType text/cache-manifest .appcache
หรือในไฟล์ app.yaml ใน Google App Engine ให้ทำดังนี้
- url: /mystaticdir/(.*\.appcache)
static_files: mystaticdir/\1
mime_type: text/cache-manifest
upload: mystaticdir/(.*\.appcache)
ข้อกำหนดนี้ถูกยกเลิกจากข้อกำหนดเฉพาะไปเมื่อสักพักแล้ว และ Chrome, Safari และ Firefox เวอร์ชันล่าสุดไม่กำหนดให้ต้องใช้อีกต่อไป แต่คุณจะต้องมี mime-type เพื่อให้ทำงานในเบราว์เซอร์รุ่นเก่าและ IE11 ได้
โครงสร้างของไฟล์ Manifest
ไฟล์ Manifest เป็นไฟล์แยกต่างหากที่คุณลิงก์ผ่านแอตทริบิวต์ Manifest ในองค์ประกอบ HTML ไฟล์ Manifest ง่ายๆ จะมีลักษณะดังนี้
CACHE MANIFEST
index.html
stylesheet.css
images/logo.png
scripts/main.js
http://cdn.example.com/scripts/main.js
ตัวอย่างนี้จะแคชไฟล์ 4 ไฟล์ในหน้าเว็บที่ระบุไฟล์ Manifest นี้
สิ่งที่ควรทราบมีดังนี้
- สตริง
CACHE MANIFEST
คือบรรทัดแรกและจำเป็นต้องระบุ - ไฟล์อาจมาจากโดเมนอื่น
- เบราว์เซอร์บางรุ่นจะจำกัดปริมาณโควต้าพื้นที่เก็บข้อมูลที่ใช้ได้กับแอปของคุณ เช่น ใน Chrome แอปแคชจะใช้พื้นที่เก็บข้อมูลชั่วคราวในพูลที่แชร์ซึ่ง API ออฟไลน์อื่นๆ สามารถแชร์ได้ หากคุณเขียนแอปสำหรับ Chrome เว็บสโตร์ การใช้
unlimitedStorage
จะยกเลิกข้อจำกัดดังกล่าว - หากไฟล์ Manifest แสดงผล 404 หรือ 410 แคชจะถูกลบ
- หากการดาวน์โหลดไฟล์ Manifest หรือทรัพยากรที่ระบุในไฟล์นั้นไม่สำเร็จ กระบวนการอัปเดตแคชทั้งหมดก็จะไม่สำเร็จ เบราว์เซอร์จะใช้แคชแอปพลิเคชันเดิมต่อไปในกรณีที่ดำเนินการไม่สำเร็จ
มาดูตัวอย่างที่ซับซ้อนขึ้นกัน
CACHE MANIFEST
# 2010-06-18:v2
# Explicitly cached 'master entries'.
CACHE:
/favicon.ico
index.html
stylesheet.css
images/logo.png
scripts/main.js
# Resources that require the user to be online.
NETWORK:
*
# static.html will be served if main.py is inaccessible
# offline.jpg will be served in place of all images in images/large/
# offline.html will be served in place of all other .html files
FALLBACK:
/main.py /static.html
images/large/ images/offline.jpg
บรรทัดที่ขึ้นต้นด้วย "#" คือบรรทัดความคิดเห็น แต่อาจใช้เพื่อวัตถุประสงค์อื่นได้ด้วย แคชของแอปพลิเคชันจะอัปเดตก็ต่อเมื่อไฟล์ Manifest ของแอปพลิเคชันมีการเปลี่ยนแปลงเท่านั้น เช่น หากคุณแก้ไขทรัพยากรรูปภาพหรือเปลี่ยนฟังก์ชัน JavaScript ระบบจะไม่แคชการเปลี่ยนแปลงเหล่านั้นซ้ำ คุณต้องแก้ไขไฟล์ Manifest เองเพื่อแจ้งให้เบราว์เซอร์รีเฟรชไฟล์ที่แคชไว้
หลีกเลี่ยงการใช้การประทับเวลาที่มีการอัปเดตอย่างต่อเนื่องหรือสตริงแบบสุ่มเพื่อบังคับให้อัปเดตทุกครั้ง ระบบจะตรวจสอบไฟล์ Manifest 2 ครั้งในระหว่างการอัปเดต โดยตรวจสอบครั้งแรกที่เริ่มต้น และตรวจสอบอีกครั้งหลังจากอัปเดตไฟล์ที่แคชไว้ทั้งหมดแล้ว หากไฟล์ Manifest มีการเปลี่ยนแปลงระหว่างการอัปเดต เป็นไปได้ว่าเบราว์เซอร์จะดึงข้อมูลไฟล์บางไฟล์จากเวอร์ชันหนึ่ง และไฟล์อื่นๆ จากอีกเวอร์ชันหนึ่ง ดังนั้นจึงไม่ใช้แคชและพยายามอีกครั้งในภายหลัง
แม้ว่าการอัปเดตแคช เบราว์เซอร์จะไม่ใช้ไฟล์เหล่านั้นจนกว่าจะมีการรีเฟรชหน้า เนื่องจากการอัปเดตจะเกิดขึ้นหลังจากที่หน้าเว็บโหลดจากแคชเวอร์ชันปัจจุบัน
ไฟล์ Manifest สามารถมีส่วนที่แตกต่างกัน 3 ส่วน ได้แก่ CACHE
, NETWORK
และ FALLBACK
CACHE:
- นี่คือส่วนเริ่มต้นสำหรับรายการ ระบบจะแคชไฟล์ที่อยู่ในส่วนส่วนหัวนี้ (หรือหลัง
CACHE MANIFEST
) อย่างชัดแจ้งหลังจากดาวน์โหลดเป็นครั้งแรกNETWORK:
- ไฟล์ที่แสดงในส่วนนี้อาจมาจากเครือข่ายหากไม่ได้อยู่ในแคช ไม่เช่นนั้นระบบจะไม่ใช้เครือข่าย แม้ว่าผู้ใช้จะออนไลน์อยู่ก็ตาม คุณสามารถเพิ่ม URL ที่ต้องการลงในรายการที่อนุญาตที่นี่ หรือเพียงแค่ "" ซึ่งจะอนุญาต URL ทั้งหมดก็ได้ เว็บไซต์ส่วนใหญ่ต้องใช้ ""
FALLBACK:
- ส่วนที่ไม่บังคับซึ่งระบุหน้าสำรองในกรณีที่เข้าถึงทรัพยากรไม่ได้ URI แรกคือทรัพยากร ส่วนที่สองเป็นรายการสำรองที่จะใช้หากคำขอเครือข่ายล้มเหลวหรือเกิดข้อผิดพลาด URI ทั้ง 2 รายการต้องมาจากแหล่งที่มาเดียวกันกับไฟล์ Manifest คุณสามารถบันทึก URL ที่เฉพาะเจาะจง รวมถึงคํานําหน้า URL ได้ด้วย "images/large/" จะบันทึกความล้มเหลวจาก URL เช่น "images/large/whatever/img.jpg"
ไฟล์ Manifest ต่อไปนี้จะกำหนดหน้า "ที่รับทั้งหมด" (offline.html) ซึ่งจะแสดงเมื่อผู้ใช้พยายามเข้าถึงรูทของเว็บไซต์ขณะออฟไลน์ และยังประกาศว่าทรัพยากรอื่นๆ ทั้งหมด (เช่น ทรัพยากรในเว็บไซต์ระยะไกล) ต้องมีการเชื่อมต่ออินเทอร์เน็ต
CACHE MANIFEST
# 2010-06-18:v3
# Explicitly cached entries
index.html
css/style.css
# offline.html will be displayed if the user is offline
FALLBACK:
/ /offline.html
# All other resources (e.g. sites) require the user to be online.
NETWORK:
*
# Additional resources to cache
CACHE:
images/logo1.png
images/logo2.png
images/logo3.png
การอัปเดตแคช
เมื่อแอปพลิเคชันออฟไลน์แล้ว แอปพลิเคชันนั้นจะยังคงแคชไว้จนกว่าจะเกิดเหตุการณ์ใดเหตุการณ์หนึ่งต่อไปนี้
- ผู้ใช้ล้างพื้นที่เก็บข้อมูลของเบราว์เซอร์สำหรับเว็บไซต์ของคุณ
- มีการแก้ไขไฟล์ Manifest หมายเหตุ: การอัปเดตไฟล์ที่แสดงในไฟล์ Manifest ไม่ได้หมายความว่าเบราว์เซอร์จะแคชทรัพยากรนั้นอีกครั้ง ต้องแก้ไขไฟล์ Manifest เอง
สถานะแคช
ออบเจ็กต์ window.applicationCache
คือสิทธิ์เข้าถึงแบบเป็นโปรแกรมสำหรับแคชแอปของเบราว์เซอร์
พร็อพเพอร์ตี้ status
มีประโยชน์ในการตรวจสอบสถานะปัจจุบันของแคช
var appCache = window.applicationCache;
switch (appCache.status) {
case appCache.UNCACHED: // UNCACHED == 0
return 'UNCACHED';
break;
case appCache.IDLE: // IDLE == 1
return 'IDLE';
break;
case appCache.CHECKING: // CHECKING == 2
return 'CHECKING';
break;
case appCache.DOWNLOADING: // DOWNLOADING == 3
return 'DOWNLOADING';
break;
case appCache.UPDATEREADY: // UPDATEREADY == 4
return 'UPDATEREADY';
break;
case appCache.OBSOLETE: // OBSOLETE == 5
return 'OBSOLETE';
break;
default:
return 'UKNOWN CACHE STATUS';
break;
};
หากต้องการตรวจสอบการอัปเดตไฟล์ Manifest แบบเป็นโปรแกรม ให้เรียกใช้ applicationCache.update()
ก่อน
ซึ่งจะพยายามอัปเดตแคชของผู้ใช้ (ซึ่งกำหนดให้ไฟล์ Manifest ต้องเปลี่ยนแปลง)
สุดท้าย เมื่อ applicationCache.status
อยู่ในสถานะ UPDATEREADY
การเรียกใช้ applicationCache.swapCache()
จะแทนที่แคชเก่าด้วยแคชใหม่
var appCache = window.applicationCache;
appCache.update(); // Attempt to update the user's cache.
...
if (appCache.status == window.applicationCache.UPDATEREADY) {
appCache.swapCache(); // The fetch was successful, swap in the new cache.
}
ข่าวดีคือคุณทําการอัปเดตนี้ได้โดยอัตโนมัติ หากต้องการอัปเดตผู้ใช้เป็นเว็บไซต์เวอร์ชันล่าสุด ให้ตั้งค่า Listener เพื่อตรวจสอบเหตุการณ์ updateready
เมื่อโหลดหน้าเว็บ โดยทำดังนี้
// Check if a new cache is available on page load.
window.addEventListener('load', function(e) {
window.applicationCache.addEventListener('updateready', function(e) {
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
// Browser downloaded a new app cache.
if (confirm('A new version of this site is available. Load it?')) {
window.location.reload();
}
} else {
// Manifest didn't changed. Nothing new to server.
}
}, false);
}, false);
เหตุการณ์ AppCache
ดังที่คุณคาดไว้ ระบบจะแสดงเหตุการณ์เพิ่มเติมเพื่อตรวจสอบสถานะของแคช เบราว์เซอร์จะเริ่มการทำงานของเหตุการณ์สำหรับสิ่งต่างๆ เช่น ความคืบหน้าในการดาวน์โหลด การอัปเดตแคชของแอป และสภาวะข้อผิดพลาด ข้อมูลโค้ดต่อไปนี้จะตั้งค่าตัวรับเหตุการณ์สําหรับเหตุการณ์แคชแต่ละประเภท
function handleCacheEvent(e) {
//...
}
function handleCacheError(e) {
alert('Error: Cache failed to update!');
};
// Fired after the first cache of the manifest.
appCache.addEventListener('cached', handleCacheEvent, false);
// Checking for an update. Always the first event fired in the sequence.
appCache.addEventListener('checking', handleCacheEvent, false);
// An update was found. The browser is fetching resources.
appCache.addEventListener('downloading', handleCacheEvent, false);
// The manifest returns 404 or 410, the download failed,
// or the manifest changed while the download was in progress.
appCache.addEventListener('error', handleCacheError, false);
// Fired after the first download of the manifest.
appCache.addEventListener('noupdate', handleCacheEvent, false);
// Fired if the manifest file returns a 404 or 410.
// This results in the application cache being deleted.
appCache.addEventListener('obsolete', handleCacheEvent, false);
// Fired for each resource listed in the manifest as it is being fetched.
appCache.addEventListener('progress', handleCacheEvent, false);
// Fired when the manifest resources have been newly redownloaded.
appCache.addEventListener('updateready', handleCacheEvent, false);
หากไฟล์ Manifest หรือทรัพยากรที่ระบุในไม่สามารถดาวน์โหลดได้ การอัปเดตทั้งหมดจะล้มเหลว เบราว์เซอร์จะใช้แคชแอปพลิเคชันเดิมต่อไปในกรณีที่เกิดข้อผิดพลาดดังกล่าว
ข้อมูลอ้างอิง
- ข้อกำหนดของ API ApplicationCache
- แคชของแอปพลิเคชันคือแบบ Douchebag ซึ่งครอบคลุมข้อผิดพลาดและปัญหาเกี่ยวกับ AppCache