Mô-đun ES trong trình chạy dịch vụ

Một giải pháp thay thế hiện đại cho importScripts().

Thông tin khái quát

Mô-đun ES đã được các nhà phát triển yêu thích từ lâu. Ngoài một số lợi ích khác, chúng hứa hẹn về một định dạng mô-đun phổ quát, trong đó mã được chia sẻ có thể được phát hành một lần và chạy trong các trình duyệt cũng như trong các môi trường thời gian chạy thay thế như Node.js. Mặc dù tất cả trình duyệt hiện đại đều hỗ trợ một số mô-đun ES, nhưng không phải tất cả trình duyệt đều hỗ trợ mọi nơi có thể chạy mã. Cụ thể, tính năng hỗ trợ nhập các mô-đun ES bên trong trình chạy dịch vụ của trình duyệt mới bắt đầu được cung cấp rộng rãi hơn.

Bài viết này trình bày chi tiết trạng thái hiện tại của chế độ hỗ trợ mô-đun ES trong trình chạy dịch vụ trên các trình duyệt phổ biến, cùng với một số yêu cầu cần tránh và các phương pháp hay nhất để vận chuyển mã trình chạy dịch vụ có khả năng tương thích ngược.

Trường hợp sử dụng

Trường hợp sử dụng lý tưởng cho các mô-đun ES bên trong trình chạy dịch vụ là để tải thư viện hoặc mã cấu hình hiện đại được chia sẻ với các môi trường thời gian chạy khác hỗ trợ mô-đun ES.

Cố gắng chia sẻ mã theo cách này trước các mô-đun ES đòi hỏi việc sử dụng các định dạng mô-đun "phổ biến" cũ như UMD bao gồm mã nguyên mẫu không cần thiết và viết mã thực hiện thay đổi đối với các biến hiển thị chung.

Các tập lệnh được nhập qua các mô-đun ES có thể kích hoạt quy trình cập nhật trình chạy dịch vụ nếu nội dung của các tập lệnh đó thay đổi, khớp với hành vi của importScripts().

Các hạn chế hiện tại

Chỉ các lệnh nhập tĩnh

Bạn có thể nhập mô-đun ES theo một trong 2 cách: tĩnh, sử dụng cú pháp import ... from '...' hoặc động bằng phương thức import(). Bên trong một trình chạy dịch vụ, hiện chỉ hỗ trợ cú pháp tĩnh.

Giới hạn này tương tự như quy định hạn chế tương tự được đặt ra cho việc sử dụng importScripts(). Các lệnh gọi động đến importScripts() không hoạt động bên trong một trình chạy dịch vụ và tất cả các lệnh gọi importScripts() vốn đồng bộ với nhau phải hoàn tất trước khi trình chạy dịch vụ này hoàn tất giai đoạn install. Hạn chế này đảm bảo rằng trình duyệt biết và có thể ngầm lưu vào bộ nhớ đệm tất cả mã JavaScript cần thiết để triển khai trình chạy dịch vụ trong quá trình cài đặt.

Cuối cùng, hạn chế này có thể được gỡ bỏ và có thể được phép nhập mô-đun ES động. Hiện tại, hãy đảm bảo rằng bạn chỉ sử dụng cú pháp tĩnh bên trong một trình chạy dịch vụ.

Còn các worker khác thì sao?

Tính năng hỗ trợ dành cho các mô-đun ES trong trình thực thi "chuyên dụng" (những mô-đun được tạo bằng new Worker('...', {type: 'module'})) phổ biến hơn, đồng thời được hỗ trợ trong Chrome và Edge kể từ phiên bản 80, cũng như các phiên bản gần đây của Safari. Cả tính năng nhập mô-đun ES tĩnh và động đều được hỗ trợ trong worker chuyên dụng.

Chrome và Edge đã hỗ trợ các mô-đun ES trong worker dùng chung kể từ phiên bản 83, nhưng hiện tại chưa có trình duyệt nào khác hỗ trợ.

Không hỗ trợ nhập bản đồ

Tính năng Nhập bản đồ cho phép môi trường thời gian chạy ghi lại thông số mô-đun, chẳng hạn như thêm vào trước URL của CDN ưu tiên nơi có thể tải các mô-đun ES.

Mặc dù phiên bản 89 trở lên của Chrome và Edge hỗ trợ tính năng nhập bản đồ, nhưng bạn hiện không thể sử dụng các trình chạy dịch vụ này với trình chạy dịch vụ.

Hỗ trợ trình duyệt

Chrome và Edge hỗ trợ các mô-đun ES trong trình chạy dịch vụ kể từ phiên bản 91.

Safari đã hỗ trợ thêm trong Bản phát hành Bản dùng thử công nghệ 122 và nhà phát triển sẽ thấy chức năng này được phát hành trong phiên bản Safari ổn định trong tương lai.

Ví dụ về mã

Đây là ví dụ cơ bản về cách sử dụng mô-đun ES dùng chung trong ngữ cảnh window của ứng dụng web, đồng thời đăng ký một trình chạy dịch vụ sử dụng cùng một mô-đun ES:

// Inside config.js:
export const cacheName = 'my-cache';
// Inside your web app:
<script type="module">
  import {cacheName} from './config.js';
  // Do something with cacheName.

  await navigator.serviceWorker.register('es-module-sw.js', {
    type: 'module',
  });
</script>
// Inside es-module-sw.js:
import {cacheName} from './config.js';

self.addEventListener('install', (event) => {
  event.waitUntil((async () => {
    const cache = await caches.open(cacheName);
    // ...
  })());
});

Khả năng tương thích ngược

Ví dụ trên sẽ hiệu quả nếu tất cả các trình duyệt đều hỗ trợ mô-đun ES trong trình chạy dịch vụ, nhưng tại thời điểm viết bài này, thì không đúng như vậy.

Để phù hợp với những trình duyệt không có tính năng hỗ trợ tích hợp sẵn, bạn có thể chạy tập lệnh trình chạy dịch vụ thông qua trình đóng gói tương thích với mô-đun ES để tạo một trình chạy dịch vụ bao gồm tất cả mã mô-đun cùng dòng và sẽ hoạt động trong các trình duyệt cũ. Ngoài ra, nếu các mô-đun mà bạn đang cố gắng nhập đã có sẵn trong gói ở định dạng IIFE hoặc UMD, bạn có thể nhập các mô-đun đó bằng importScripts().

Sau khi có 2 phiên bản trình chạy dịch vụ (một phiên bản sử dụng mô-đun ES và phiên bản còn lại không sử dụng mô-đun), bạn sẽ cần phát hiện trình duyệt hiện tại hỗ trợ những gì và đăng ký tập lệnh trình chạy dịch vụ tương ứng. Các phương pháp hay nhất để phát hiện tính năng hỗ trợ hiện đang thay đổi, nhưng bạn có thể làm theo nội dung thảo luận trong vấn đề GitHub này để biết các đề xuất.

_Ảnh chụp của VladoPaunovic trên Unsplash_