Hướng dẫn cho người mới bắt đầu sử dụng bộ nhớ đệm của ứng dụng

Giới thiệu

Các ứng dụng dựa trên web có thể truy cập ngoại tuyến ngày càng trở nên quan trọng. Có, tất cả các trình duyệt đều có thể lưu các trang và tài nguyên vào bộ nhớ đệm trong thời gian dài nếu được yêu cầu. Tuy nhiên, trình duyệt có thể đưa từng mục riêng lẻ ra khỏi bộ nhớ đệm bất cứ lúc nào để có chỗ cho những nội dung khác. HTML5 giải quyết một số phiền toái khi không có kết nối mạng với giao diện ApplicationCache. Việc sử dụng giao diện bộ nhớ đệm mang lại ba lợi ích cho ứng dụng của bạn:

  1. Duyệt web ngoại tuyến - người dùng có thể điều hướng toàn bộ trang web của bạn khi họ ngoại tuyến
  2. Tốc độ - tài nguyên lấy trực tiếp từ ổ đĩa, không cần kết nối với mạng.
  3. Khả năng phục hồi - nếu trang web của bạn phải ngừng hoạt động để "bảo trì" (chẳng hạn như ai đó vô tình làm hỏng mọi thứ), thì người dùng của bạn sẽ có được trải nghiệm ngoại tuyến

Bộ nhớ đệm của ứng dụng (hay AppCache) cho phép nhà phát triển chỉ định tệp nào mà trình duyệt nên lưu vào bộ nhớ đệm và cung cấp cho người dùng ngoại tuyến. Ứng dụng của bạn sẽ tải và hoạt động chính xác, ngay cả khi người dùng nhấn nút làm mới khi không có kết nối mạng.

Tệp kê khai bộ nhớ đệm

Tệp kê khai bộ nhớ đệm là một tệp văn bản đơn giản liệt kê các tài nguyên mà trình duyệt cần lưu vào bộ nhớ đệm để truy cập khi không có mạng.

Tham chiếu tệp kê khai

Để bật bộ nhớ đệm của ứng dụng cho một ứng dụng, hãy thêm thuộc tính tệp kê khai vào thẻ html của tài liệu:

<html manifest="example.appcache">
  ...
</html>

Thuộc tính manifest phải được đưa vào mọi trang của ứng dụng web mà bạn muốn lưu vào bộ nhớ đệm. Trình duyệt không lưu một trang vào bộ nhớ đệm nếu trang đó không chứa thuộc tính manifest (trừ phi trang đó được liệt kê rõ ràng trong chính tệp kê khai. Tức là mọi trang mà người dùng chuyển đến có chứa manifest đều sẽ ngầm được thêm vào bộ nhớ đệm của ứng dụng. Do đó, bạn không cần phải liệt kê mọi trang trong tệp kê khai. Nếu một trang trỏ đến một tệp kê khai, thì không có cách nào để ngăn việc lưu trang này vào bộ nhớ đệm.

Bạn có thể xem các URL do bộ nhớ đệm của ứng dụng kiểm soát bằng cách truy cập about://appcache-internals/ trong Chrome. Tại đây, bạn có thể xoá bộ nhớ đệm và xem các mục. Có các công cụ tương tự cho nhà phát triển trong Firefox.

Thuộc tính manifest có thể trỏ đến một URL tuyệt đối hoặc đường dẫn tương đối, nhưng URL tuyệt đối phải có cùng nguồn gốc với ứng dụng web. Tệp kê khai có thể có đuôi tệp bất kỳ, nhưng cần được phân phát với đúng loại mime (xem bên dưới).

<html manifest="http://www.example.com/example.mf">
  ...
</html>

Tệp kê khai phải được phân phát bằng loại MIME text/cache-manifest. Bạn có thể phải thêm loại tệp tuỳ chỉnh vào máy chủ web hoặc cấu hình .htaccess.

Ví dụ: để phân phát loại MIME này trong Apache, hãy thêm dòng sau vào tệp cấu hình của bạn:

AddType text/cache-manifest .appcache

Hoặc trong tệp app.yaml của bạn trong Google App Engine:

- url: /mystaticdir/(.*\.appcache)
  static_files: mystaticdir/\1
  mime_type: text/cache-manifest
  upload: mystaticdir/(.*\.appcache)

Yêu cầu này đã bị loại bỏ so với thông số kỹ thuật cách đây một thời gian và không còn được yêu cầu bởi các phiên bản mới nhất của Chrome, Safari và Firefox, nhưng bạn sẽ cần loại mime để hoạt động trong trình duyệt cũ và IE11.

Cấu trúc của tệp kê khai

Tệp kê khai là một tệp riêng biệt mà bạn liên kết đến thông qua thuộc tính tệp kê khai trên phần tử html. Một tệp kê khai đơn giản sẽ có dạng như sau:

CACHE MANIFEST
index.html
stylesheet.css
images/logo.png
scripts/main.js
http://cdn.example.com/scripts/main.js

Ví dụ này sẽ lưu vào bộ nhớ đệm 4 tệp trên trang chỉ định tệp kê khai này.

Có một vài điều cần lưu ý:

  • Chuỗi CACHE MANIFEST là dòng đầu tiên và bắt buộc phải có.
  • Tệp có thể đến từ một miền khác
  • Một số trình duyệt đặt ra hạn chế về dung lượng hạn mức bộ nhớ dành cho ứng dụng của bạn. Ví dụ: Trong Chrome, AppCache sử dụng bộ nhớ dùng chung TEMPORARY mà các API ngoại tuyến khác có thể chia sẻ. Nếu bạn đang viết một ứng dụng cho Cửa hàng Chrome trực tuyến thì việc sử dụng unlimitedStorage sẽ loại bỏ hạn chế đó.
  • Nếu chính tệp kê khai trả về 404 hoặc 410, thì bộ nhớ đệm sẽ bị xoá.
  • Nếu tệp kê khai hoặc tài nguyên được chỉ định trong tệp đó không tải xuống được, thì toàn bộ quá trình cập nhật bộ nhớ đệm sẽ không thành công. Trình duyệt sẽ tiếp tục sử dụng bộ nhớ đệm cũ của ứng dụng trong trường hợp không thành công.

Hãy xem một ví dụ phức tạp hơn:

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

Các dòng bắt đầu bằng '#' là các dòng nhận xét nhưng cũng có thể phục vụ một mục đích khác. Bộ nhớ đệm của ứng dụng chỉ được cập nhật khi tệp kê khai của ứng dụng đó thay đổi. Ví dụ: nếu bạn chỉnh sửa tài nguyên hình ảnh hoặc thay đổi hàm JavaScript, những thay đổi đó sẽ không được lưu lại vào bộ nhớ đệm. Bạn phải sửa đổi chính tệp kê khai để thông báo cho trình duyệt làm mới các tệp được lưu vào bộ nhớ đệm.

Tránh sử dụng dấu thời gian liên tục cập nhật hoặc chuỗi ngẫu nhiên để buộc cập nhật mỗi lần cập nhật. Tệp kê khai được kiểm tra hai lần trong quá trình cập nhật, một lần khi bắt đầu và một lần sau khi tất cả các tệp lưu trong bộ nhớ đệm đã được cập nhật. Nếu tệp kê khai đã thay đổi trong quá trình cập nhật, thì có thể trình duyệt đã tìm nạp một số tệp từ một phiên bản và các tệp khác từ phiên bản khác. Do đó, trình duyệt sẽ không áp dụng bộ nhớ đệm và thử lại sau.

Mặc dù bộ nhớ đệm sẽ cập nhật, nhưng trình duyệt sẽ không sử dụng các tệp đó cho đến khi trang được làm mới, vì quá trình cập nhật diễn ra sau khi trang được tải từ phiên bản hiện tại của bộ nhớ đệm.

Tệp kê khai có thể có ba phần riêng biệt: CACHE, NETWORKFALLBACK.

CACHE:
Đây là phần mặc định cho các mục nhập. Các tệp liệt kê trong tiêu đề này (hoặc ngay sau CACHE MANIFEST) sẽ được lưu vào bộ nhớ đệm một cách rõ ràng sau khi tải xuống lần đầu. NETWORK:
Các tệp liệt kê trong phần này có thể đến từ mạng nếu chúng không có trong bộ nhớ đệm, nếu không thì mạng sẽ không được dùng, ngay cả khi người dùng đang kết nối mạng. Bạn có thể đưa các URL cụ thể vào danh sách cho phép tại đây, hoặc đơn giản là "", để cho phép tất cả URL. Hầu hết các trang web đều cần có "". FALLBACK:
Một phần không bắt buộc chỉ định các trang dự phòng nếu không thể truy cập tài nguyên. URI đầu tiên là tài nguyên, URI thứ hai là phương án dự phòng được dùng nếu yêu cầu mạng không thành công hoặc gặp lỗi. Cả hai URI phải có cùng nguồn gốc với tệp kê khai. Bạn có thể lấy các URL cụ thể cũng như lấy tiền tố URL. "images/large/" sẽ ghi lại lỗi từ URL như "images/large/whatever/img.jpg".

Tệp kê khai sau đây xác định trang "catch-all" (Offline.html) sẽ hiển thị khi người dùng cố gắng truy cập vào thư mục gốc của trang web trong khi không có kết nối mạng. Tệp kê khai cũng khai báo rằng tất cả các tài nguyên khác (ví dụ: những tài nguyên trên một trang web từ xa) đều cần có kết nối Internet.

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

Cập nhật bộ nhớ đệm

Khi ứng dụng ngoại tuyến, ứng dụng vẫn được lưu vào bộ nhớ đệm cho đến khi một trong các trường hợp sau xảy ra:

  1. Người dùng xoá bộ nhớ dữ liệu của trình duyệt trên trang web của bạn.
  2. Tệp kê khai đã được sửa đổi. Lưu ý: việc cập nhật một tệp liệt kê trong tệp kê khai không có nghĩa là trình duyệt sẽ lưu tài nguyên đó vào bộ nhớ đệm lại. Tệp kê khai phải được thay đổi.

Trạng thái bộ nhớ đệm

Đối tượng window.applicationCache là quyền truy cập có lập trình vào bộ nhớ đệm ứng dụng của trình duyệt. Thuộc tính status rất hữu ích cho việc kiểm tra trạng thái hiện tại của bộ nhớ đệm:

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;
};

Để kiểm tra các bản cập nhật cho tệp kê khai bằng phương thức lập trình, trước tiên, hãy gọi applicationCache.update(). Hệ thống sẽ tìm cách cập nhật bộ nhớ đệm của người dùng (yêu cầu phải thay đổi tệp kê khai). Cuối cùng, khi applicationCache.status đang ở trạng thái UPDATEREADY, việc gọi applicationCache.swapCache() sẽ hoán đổi bộ nhớ đệm cũ lấy bộ nhớ đệm mới.

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.
}

Tin vui là bạn có thể tự động hoá việc này. Để cập nhật người dùng lên phiên bản mới nhất của trang web, hãy thiết lập trình nghe để theo dõi sự kiện updateready khi tải trang:

// 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);

Sự kiện trong AppCache

Như bạn có thể mong đợi, các sự kiện bổ sung sẽ hiển thị để theo dõi trạng thái của bộ nhớ đệm. Trình duyệt sẽ kích hoạt các sự kiện như tiến trình tải xuống, cập nhật bộ nhớ đệm của ứng dụng và tình trạng lỗi. Đoạn mã sau đây thiết lập trình nghe sự kiện cho từng loại sự kiện bộ nhớ đệm:

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);

Nếu tệp kê khai hoặc tài nguyên được chỉ định trong tệp đó không tải xuống được, thì toàn bộ bản cập nhật sẽ không thành công. Trình duyệt sẽ tiếp tục sử dụng bộ nhớ đệm của ứng dụng cũ trong trường hợp xảy ra lỗi.

Tài liệu tham khảo