Video là một thành phần khó quản lý; việc phát trực tuyến tốn nhiều băng thông và việc lưu vào bộ nhớ đệm không đơn giản. Những vấn đề này càng trở nên nghiêm trọng hơn khi video phát lặp lại, chẳng hạn như trong màn hình ki-ốt. Ví dụ: nếu một công ty có hàng trăm thiết bị phát 30 video lặp lại cả ngày, mỗi ngày, thì mạng của công ty đó có thể nhanh chóng bị quá tải. Bằng cách phân phát video từ bộ nhớ đệm thay vì phát trực tuyến, bạn chỉ phải trả phí tải xuống một lần, giúp các lần phát tiếp theo diễn ra nhanh hơn và có thể phát khi không có mạng. Để làm việc này, bạn có thể tận dụng khả năng lưu trữ của trình duyệt, trong đó API Bộ nhớ đệm và IndexedDB là phù hợp nhất để lưu trữ tệp video. Mặc dù cả hai đều là lựa chọn tốt, nhưng chúng ta sẽ tập trung vào Cache Storage API vì API này tích hợp với thư viện trình chạy dịch vụ phổ biến Workbox.
Lưu video vào bộ nhớ đệm từ một worker dịch vụ
Vì việc tải xuống và lưu vào bộ nhớ đệm các tài sản lớn như video có thể là một tác vụ tốn nhiều thời gian và bộ xử lý, nên bạn cần thực hiện tác vụ này ở chế độ nền bên ngoài luồng chính. Worker dịch vụ đặc biệt hữu ích khi giảm tải các tác vụ lưu vào bộ nhớ đệm. Chúng đóng vai trò là một proxy giữa trang và mạng, cho phép proxy này chặn các yêu cầu và áp dụng thêm logic cho phản hồi mạng, ví dụ: chiến lược lưu vào bộ nhớ đệm.
Có nhiều chiến lược lưu vào bộ nhớ đệm và mỗi chiến lược được thiết kế để hỗ trợ trong các trường hợp sử dụng khác nhau. Ví dụ: để phân phát một tệp từ bộ nhớ đệm nếu có hoặc quay lại mạng nếu không, bạn có thể viết mã sau.
self.addEventListener('fetch', function (event) { event.respondWith( caches.match(event.request).then(function (response) { return response || fetch(event.request); }), ); });
Việc quản lý hoạt động này cho các loại tài sản hoặc URL khác nhau đòi hỏi các chiến lược lưu vào bộ nhớ đệm khác nhau có thể là một quy trình lặp đi lặp lại và dễ xảy ra lỗi. Workbox cung cấp một bộ công cụ, bao gồm các trình trợ giúp định tuyến và chiến lược lưu vào bộ nhớ đệm, cho phép bạn viết mã trình chạy dịch vụ theo cách khai báo và có thể sử dụng lại nhiều hơn.
Chiến lược trước đây được gọi là cache first (ưu tiên bộ nhớ đệm). Để viết cùng một nội dung bằng Workbox, bạn sẽ thêm những nội dung sau:
registerRoute( ({ request }) => request.destination === 'video', new CacheFirst() );
Workbox cung cấp các công thức tương tự cho các chiến lược lưu vào bộ nhớ đệm khác và các tác vụ trình chạy dịch vụ phổ biến, bao gồm cả việc tích hợp với các công cụ xây dựng như Webpack và Rollup.
Sau khi thiết lập Workbox, bạn cần chọn thời điểm lưu video vào bộ nhớ đệm. Có hai cách để thực hiện việc này: tải ngay khi tải trang hoặc tải chậm khi video được yêu cầu.
Phương pháp tiếp cận chủ động
Lưu trước vào bộ nhớ đệm là một kỹ thuật lưu các tệp vào bộ nhớ đệm trong quá trình cài đặt trình chạy dịch vụ, giúp các tệp này có sẵn ngay khi trình chạy dịch vụ hoạt động. Workbox có thể tự động thiết lập tính năng lưu trước vào bộ nhớ đệm cho các tệp mà Workbox có thể truy cập trong quá trình tạo.
Bạn có thể sử dụng đoạn mã Workbox sau đây trong trình chạy dịch vụ để lưu trước các tệp vào bộ nhớ đệm:
import { addPlugins, precacheAndRoute } from 'workbox-precaching'; import { RangeRequestsPlugin } from 'workbox-range-requests'; addPlugins([new RangeRequestsPlugin()]); precacheAndRoute(self.__WB_MANIFEST);
import(s) – Tải các liên kết bắt buộc từ các mô-đun Workbox tương ứng. Vì các worker dịch vụ hiện chưa hỗ trợ ESModules một cách phổ biến, nên worker dịch vụ dựa trên Workbox của bạn sẽ cần được truyền qua một trình đóng gói để hoạt động trong quá trình sản xuất.RangeRequestsPlugin– Cho phép một yêu cầu có tiêu đềRangeđược thực hiện bằng một phản hồi được lưu vào bộ nhớ đệm. Điều này là cần thiết vì trình duyệt thường dùng tiêu đềRangecho nội dung nghe nhìn.addPlugins– Cho phép bạn thêm các trình bổ trợ Workbox vào mọi yêu cầu Workbox.precacheAndRoute– Thêm các mục vào danh sách lưu trước vào bộ nhớ đệm và tạo một tuyến đường để xử lý các yêu cầu tìm nạp tương ứng.__WB_MANIFEST– Phần giữ chỗ mà Workbox CLI (hoặc các trình bổ trợ công cụ tạo) thay thế bằng tệp kê khai lưu vào bộ nhớ đệm trước.
Truyền trình chạy dịch vụ của bạn vào Workbox CLI hoặc công cụ tạo mà bạn chọn và định cấu hình cách tạo bộ nhớ đệm trước; một tệp workbox-config.js, chẳng hạn như tệp sau,sẽ cho CLI biết cách hiển thị trình chạy dịch vụ của bạn:
module.exports = { globDirectory: '.', globPatterns: ['**/*.{html,mp4}'], maximumFileSizeToCacheInBytes: 5000000, swSrc: 'sw.js', swDest: 'sw.js', };
globDirectory– Thư mục gốc để bắt đầu tìm kiếm các tệp lưu vào bộ nhớ đệm trướcglobPatterns– Các mẫu tệp ("glob") cần được lưu vào bộ nhớ đệm trước.maximumFileSizeToCacheInBytes– Giới hạn trên về kích thước mà một tệp có thể có để được lưu vào bộ nhớ đệm trước, tính bằng byte.swSrc– Vị trí của tệp sẽ được dùng để tạo trình chạy dịch vụ.swDest– Đích đến của trình chạy dịch vụ được tạo (có thể giống với tệp nguồn, nhưng hãy đảm bảo cóself.__WB_MANIFESTcho mỗi lần chạy).
Khi quy trình tạo chạy, một phiên bản mới của service worker sẽ được tạo và self.__WB_MANIFEST sẽ được thay thế bằng một danh sách các tệp, mỗi tệp có một hàm băm để biểu thị bản sửa đổi của tệp:
precacheAndRoute([ { revision: '524ac4b453c83f76eb9caeec11854ca5', url: 'ny.mp4', }, ]);
Mỗi khi quá trình tạo bản dựng chạy, danh sách này sẽ được ghi lại bằng nhóm tệp khớp hiện tại và hàm băm sửa đổi hiện tại của các tệp đó. Điều này đảm bảo rằng bất cứ khi nào một tệp được thêm, xoá hoặc thay đổi, trình chạy dịch vụ sẽ cập nhật bộ nhớ đệm trong lần cài đặt tiếp theo.
Phương pháp Lazy
Khi không có sẵn tất cả video tại thời điểm tạo hoặc chỉ muốn lưu video vào bộ nhớ đệm khi cần, bạn nên sử dụng phương pháp trì hoãn. Phương pháp này yêu cầu tách riêng việc lưu vào bộ nhớ đệm và phân phát; vì chỉ có nội dung một phần được tìm nạp từ mạng trong quá trình phát video, nên việc lưu các tệp vào bộ nhớ đệm khi chúng được truyền phát sẽ không hoạt động.
Lưu tệp vào bộ nhớ đệm
Bạn có thể tạo bộ nhớ đệm bằng cách sử dụng Cache.open(), sau đó thêm tệp vào bộ nhớ đệm bằng cách sử dụng Cache.add() hoặc Cache.addAll(). Nếu ứng dụng của bạn nhận được danh sách video ở định dạng JSON để lưu vào bộ nhớ đệm, thì bạn có thể thêm các video đó vào bộ nhớ đệm video như sau:
// Open video cache const cache = await caches.open('video-cache'); // Fetch list of videos const videos = await (await fetch('/video-list.json')).json(); // Add videos to cache await cache.addAll(videos);
Ưu điểm của phương pháp này là bạn có thể kiểm soát bước lưu vào bộ nhớ đệm một cách độc lập với vòng đời của trình chạy dịch vụ, ngay cả từ các trình chạy web khác. Nhược điểm là phần quản lý bộ nhớ do nhà phát triển đảm nhiệm: bạn cần tự viết thuật toán để theo dõi các thay đổi của tệp, theo dõi các tệp hiện được lưu vào bộ nhớ đệm trong trình duyệt và quản lý các bản cập nhật tệp để đảm bảo chỉ những tệp đã thay đổi mới được cập nhật.
Phân phát tệp video được lưu vào bộ nhớ đệm
Sau đó, bạn có thể sử dụng chiến lược lưu vào bộ nhớ đệm thời gian chạy của worker dịch vụ, chẳng hạn như ưu tiên bộ nhớ đệm để phân phát các tệp video đã lưu vào bộ nhớ đệm trước đó:
import { registerRoute } from 'workbox-routing'; import { CacheFirst } from 'workbox-strategies'; import { CacheableResponsePlugin } from 'workbox-cacheable-response'; import { RangeRequestsPlugin } from 'workbox-range-requests'; registerRoute( ({ request }) => request.destination === 'video', new CacheFirst({ cacheName: 'video-cache', plugins: [ new CacheableResponsePlugin({ statuses: [200], }), new RangeRequestsPlugin(), ], }), );
import(s) – Tải các liên kết bắt buộc từ các mô-đun workbox tương ứng.registerRoute– Định tuyến các yêu cầu đến các hàm (chiến lược lưu vào bộ nhớ đệm và các trình bổ trợ) cung cấp phản hồi.CacheFirst– Chiến lược lưu vào bộ nhớ đệm đáp ứng yêu cầu từ bộ nhớ đệm (nếu có), nếu không thì tìm nạp yêu cầu đó từ mạng và cập nhật bộ nhớ đệm.CacheableResponsePlugin– Dùng để cho biết những tiêu đề cần có để phản hồi có thể lưu vào bộ nhớ đệm. Hãy nhớ chỉ thêm 200 trạng thái cho các tuyến đường lưu video vào bộ nhớ đệm để tránh các phản hồi nội dung một phần (206) được lưu vào bộ nhớ đệm khi video được phát trực tuyến.RangeRequestsPlugin– Trình bổ trợ cho phép một yêu cầu có tiêu đềRangeđược thực hiện bằng một phản hồi được lưu vào bộ nhớ đệm. Điều này là cần thiết vì trình duyệt thường dùng tiêu đềRangecho nội dung nghe nhìn.
Tối ưu hoá quá trình tải video là một việc quan trọng đối với những ứng dụng phát trực tuyến nhiều nội dung. Bằng cách tận dụng Cache Storage API và Workbox của trình duyệt, bạn có thể quản lý nhiệm vụ khó khăn này, tiết kiệm băng thông cho người dùng, giảm tải cho máy chủ, đạt được tốc độ phát video nhanh hơn và cho phép video chạy ngay cả khi không có mạng.