Bộ nhớ KV - Mô-đun tích hợp đầu tiên của web

Trong phần lớn thập kỷ qua, các nhà cung cấp trình duyệt và chuyên gia về hiệu suất web đã nói rằng localStorage chạy chậm và các nhà phát triển web nên ngừng sử dụng.

Công bằng mà nói, những người nói như vậy không sai. localStorage là một API đồng bộ chặn luồng chính và mỗi khi truy cập vào API này, bạn có thể ngăn trang của mình tương tác.

Vấn đề là API localStorage quá đơn giản và phương án thay thế không đồng bộ duy nhất cho localStorageIndexedDB. API này (hãy đối mặt với thực tế) không được biết đến là dễ sử dụng hoặc thân thiện.

Vì vậy, nhà phát triển sẽ phải chọn giữa một tính năng khó sử dụng và một tính năng gây hại cho hiệu suất. Mặc dù các thư viện cung cấp sự đơn giản của API localStorage trong khi thực sự sử dụng các API bộ nhớ không đồng bộ, bao gồm một trong các thư viện đó trong ứng dụng của bạn có chi phí kích thước tệp và có thể làm giảm ngân sách hiệu suất.

Nhưng nếu có thể đạt được hiệu suất của một API lưu trữ không đồng bộ với sự đơn giản của API localStorage mà không phải trả chi phí về kích thước tệp thì sao?

Có thể sẽ sớm có. Chrome đang thử nghiệm một tính năng mới có tên là mô-đun tích hợp. Mô-đun đầu tiên mà chúng tôi dự định phát hành là mô-đun lưu trữ khoá/giá trị không đồng bộ có tên là KV Storage.

Tuy nhiên, trước khi đi vào chi tiết về mô-đun KV Storage, hãy để tôi giải thích ý nghĩa của mô-đun tích hợp sẵn.

Mô-đun tích hợp là gì?

Mô-đun tích hợp cũng giống như mô-đun JavaScript thông thường, ngoại trừ việc bạn không cần tải xuống vì các mô-đun này đi kèm với trình duyệt.

Giống như các API web truyền thống, các mô-đun tích hợp phải trải qua quy trình chuẩn hoá. Mỗi mô-đun sẽ có quy cách riêng yêu cầu xem xét thiết kế và các dấu hiệu tích cực về việc hỗ trợ từ cả nhà phát triển web và các nhà cung cấp trình duyệt khác trước khi có thể xuất xưởng. (Trong Chrome, các mô-đun tích hợp sẽ tuân theo cùng một quy trình khởi chạy mà chúng tôi sử dụng để triển khai và phân phối tất cả API mới.)

Không giống như các API web truyền thống, các mô-đun tích hợp không được hiển thị trên phạm vi toàn cục — các mô-đun này chỉ có sẵn thông qua lệnh nhập.

Việc không hiển thị các mô-đun tích hợp trên toàn cầu có nhiều ưu điểm: các mô-đun này sẽ không thêm bất kỳ hao tổn nào khi khởi động một ngữ cảnh thời gian chạy JavaScript mới (ví dụ: một thẻ, worker hoặc worker dịch vụ mới) và sẽ không tiêu tốn bất kỳ bộ nhớ hoặc CPU nào trừ khi các mô-đun này thực sự được nhập. Hơn nữa, các biến này không có nguy cơ xung đột tên với các biến khác được xác định trong mã của bạn.

Để nhập một mô-đun tích hợp, bạn sử dụng tiền tố std:, theo sau là giá trị nhận dạng của mô-đun tích hợp. Ví dụ: trong các trình duyệt được hỗ trợ, bạn có thể nhập mô-đun KV Storage bằng mã sau (xem phần bên dưới để biết cách sử dụng polyfill KV Storage trong các trình duyệt không được hỗ trợ):

import storage, {StorageArea} from 'std:kv-storage';

Mô-đun Bộ nhớ KV

Mô-đun KV Storage có tính đơn giản tương tự như API localStorage, nhưng hình dạng API của mô-đun này thực sự gần với Map JavaScript. Thay vì getItem(), setItem(), và removeItem(), thì có get(), set(), và delete(). Lớp này cũng có các phương thức giống như bản đồ khác không có trong localStorage, chẳng hạn như keys(), values()entries(). Giống như Map, khoá của lớp này không nhất thiết phải là chuỗi. Đó có thể là bất kỳ loại có thể chuyển đổi tuần tự có cấu trúc nào.

Không giống như Map, tất cả các phương thức của KV Storage đều trả về lời hứa hoặc trình duyệt tuần tự không đồng bộ (vì điểm chính của mô-đun này là không đồng bộ, trái ngược với localStorage). Để xem chi tiết toàn bộ API, bạn có thể tham khảo thông số kỹ thuật.

Như bạn có thể nhận thấy trong ví dụ về mã ở trên, mô-đun KV Storage có một tệp xuất mặc định storage và một tệp xuất có tên StorageArea.

storage là một thực thể của lớp StorageArea có tên 'default'. Đây là lớp mà các nhà phát triển sẽ sử dụng thường xuyên nhất trong mã ứng dụng của họ. Lớp StorageArea được cung cấp cho các trường hợp cần thêm tính năng tách biệt (ví dụ: thư viện của bên thứ ba lưu trữ dữ liệu và muốn tránh xung đột với dữ liệu được lưu trữ thông qua thực thể storage mặc định). Dữ liệu StorageArea được lưu trữ trong cơ sở dữ liệu IndexedDB có tên kv-storage:${name}, trong đó name là tên của thực thể StorageArea.

Dưới đây là ví dụ về cách sử dụng mô-đun KV Storage trong mã:

import storage from 'std:kv-storage';

const main = async () => {
  const oldPreferences = await storage.get('preferences');

  document.querySelector('form').addEventListener('submit', async () => {
    const newPreferences = Object.assign({}, oldPreferences, {
      // Updated preferences go here...
    });

    await storage.set('preferences', newPreferences);
  });
};

main();

Nếu trình duyệt không hỗ trợ mô-đun tích hợp thì sao?

Nếu đã quen với việc sử dụng các mô-đun JavaScript gốc trong trình duyệt, bạn có thể biết rằng (ít nhất là cho đến thời điểm hiện tại) việc nhập bất kỳ nội dung nào khác ngoài URL sẽ tạo ra lỗi. Và std:kv-storage không phải là URL hợp lệ.

Điều này đặt ra câu hỏi: chúng ta có phải đợi đến khi tất cả trình duyệt hỗ trợ mô-đun tích hợp trước khi có thể sử dụng mô-đun đó trong mã của mình không? Rất may, câu trả lời là không!

Bạn thực sự có thể sử dụng các mô-đun tích hợp ngay khi có một trình duyệt hỗ trợ các mô-đun đó nhờ sự trợ giúp của một tính năng khác mà chúng tôi đang thử nghiệm có tên là bản đồ nhập.

Nhập bản đồ

Về cơ bản, Bản đồ nhập là một cơ chế mà qua đó nhà phát triển có thể đặt bí danh cho giá trị nhận dạng nhập vào một hoặc nhiều giá trị nhận dạng thay thế.

Điều này rất hữu ích vì cho phép bạn thay đổi (trong thời gian chạy) cách trình duyệt phân giải một giá trị nhận dạng nhập cụ thể trên toàn bộ ứng dụng.

Trong trường hợp mô-đun tích hợp, điều này cho phép bạn tham chiếu polyfill của mô-đun trong mã xử lý ứng dụng, nhưng trình duyệt hỗ trợ mô-đun tích hợp có thể tải phiên bản đó!

Dưới đây là cách khai báo bản đồ nhập để làm cho tính năng này hoạt động với mô-đun Bộ nhớ KV:

<!-- The import map is inlined into your page -->
<script type="importmap">
{
  "imports": {
    "/path/to/kv-storage-polyfill.mjs": [
      "std:kv-storage",
      "/path/to/kv-storage-polyfill.mjs"
    ]
  }
}
</script>

<!-- Then any module scripts with import statements use the above map -->
<script type="module">
  import storage from '/path/to/kv-storage-polyfill.mjs';

  // Use `storage` ...
</script>

Điểm chính trong mã trên là URL /path/to/kv-storage-polyfill.mjs đang được liên kết đến hai tài nguyên khác nhau: std:kv-storage, sau đó lại là URL ban đầu, /path/to/kv-storage-polyfill.mjs.

Vì vậy, khi gặp một câu lệnh nhập tham chiếu đến URL đó (/path/to/kv-storage-polyfill.mjs), trước tiên, trình duyệt sẽ cố gắng tải std:kv-storage. Nếu không thể, trình duyệt sẽ quay lại tải /path/to/kv-storage-polyfill.mjs.

Xin nhắc lại, điều kỳ diệu ở đây là trình duyệt không cần hỗ trợ bản đồ nhập hoặc các mô-đun tích hợp để kỹ thuật này hoạt động vì URL được truyền đến câu lệnh nhập là URL cho polyfill. Polyfill không thực sự là một giải pháp dự phòng, mà là giải pháp mặc định. Mô-đun tích hợp là một tính năng nâng cao dần!

Còn những trình duyệt không hỗ trợ mô-đun thì sao?

Để sử dụng bản đồ nhập để tải các mô-đun tích hợp theo điều kiện, bạn phải thực sự sử dụng các câu lệnh import, đồng nghĩa với việc bạn phải sử dụng tập lệnh mô-đun, tức là <script type="module">.

Hiện tại, hơn 80% trình duyệt hỗ trợ mô-đun. Đối với những trình duyệt không hỗ trợ, bạn có thể sử dụng công nghệ mô-đun/không có mô-đun để phân phát gói cũ. Xin lưu ý rằng khi tạo bản dựng nomodule, bạn cần đưa vào tất cả các polyfill vì bạn chắc chắn rằng các trình duyệt không hỗ trợ mô-đun chắc chắn sẽ không hỗ trợ các mô-đun tích hợp.

Bản minh hoạ về Bộ nhớ KV

Để minh hoạ việc bạn có thể sử dụng các mô-đun tích hợp sẵn trong khi vẫn hỗ trợ các trình duyệt cũ, tôi đã tạo một bản minh hoạ kết hợp tất cả các kỹ thuật được mô tả ở trên và chạy trong tất cả trình duyệt hiện nay:

  • Các trình duyệt hỗ trợ mô-đun, bản đồ nhập và mô-đun tích hợp sẽ không tải bất kỳ mã nào không cần thiết.
  • Những trình duyệt hỗ trợ mô-đun và bản đồ nhập nhưng không hỗ trợ mô-đun tích hợp sẽ tải tiện ích bổ sung KV Storage (thông qua trình tải mô-đun của trình duyệt).
  • Các trình duyệt hỗ trợ mô-đun nhưng không hỗ trợ bản đồ nhập cũng tải polyfill Bộ nhớ KV (thông qua trình tải mô-đun của trình duyệt).
  • Các trình duyệt không hỗ trợ mô-đun sẽ nhận được polyfill KV Storage trong gói cũ (được tải qua <script nomodule>).

Bản minh hoạ được lưu trữ trên Glitch, vì vậy, bạn có thể xem nguồn của bản minh hoạ. Tôi cũng có nội dung giải thích chi tiết về cách triển khai trong README. Bạn có thể xem nếu muốn biết cách tạo ứng dụng này.

Để thực sự xem mô-đun tích hợp gốc hoạt động, bạn phải tải bản minh hoạ trong Chrome 74 trở lên khi bật cờ tính năng nền tảng web thử nghiệm (chrome://flags/#enable-experimental-web-platform-features).

Bạn có thể xác minh rằng mô-đun tích hợp sẵn đang được tải vì bạn sẽ không thấy tập lệnh polyfill trong bảng điều khiển nguồn trong DevTools; thay vào đó, bạn sẽ thấy phiên bản mô-đun tích hợp sẵn (thông tin thú vị: bạn thực sự có thể kiểm tra mã nguồn của mô-đun hoặc thậm chí đặt điểm ngắt trong đó!):

Nguồn mô-đun KV Storage trong Công cụ của Chrome cho nhà phát triển

Vui lòng gửi ý kiến phản hồi cho chúng tôi

Phần giới thiệu này đã cho bạn thấy những gì có thể làm được với các mô-đun tích hợp. Và hy vọng bạn cũng háo hức như chúng tôi! Chúng tôi rất mong các nhà phát triển dùng thử mô-đun KV Storage (cũng như tất cả các tính năng mới được thảo luận tại đây) và gửi ý kiến phản hồi cho chúng tôi.

Sau đây là các đường liên kết đến GitHub mà bạn có thể gửi ý kiến phản hồi cho chúng tôi về từng tính năng được đề cập trong bài viết này:

Nếu trang web của bạn hiện đang sử dụng localStorage, bạn nên thử chuyển sang API Kho lưu trữ KV để xem API này có đáp ứng tất cả nhu cầu của bạn hay không. Và nếu đăng ký dùng thử phiên bản gốc của KV Storage, bạn có thể triển khai các tính năng này ngay hôm nay. Tất cả người dùng của bạn sẽ được hưởng lợi từ hiệu suất bộ nhớ tốt hơn và người dùng Chrome 74 trở lên sẽ không phải trả thêm chi phí tải xuống.