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

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

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

Vấn đề là API localStorage rất đơn giản và không đồng bộ duy nhất thay thế cho localStorageIndexedDB, nhưng (hãy đối mặt với vấn đề này) không được biết đến về khả năng dễ sử dụng hoặc API chào đón.

Vì vậy, các nhà phát triển phải lựa chọn giữa yếu tố khó sử dụng và yếu tố không tốt cho hiệu suất. Và mặc dù các thư viện mang lại sự đơn giản của API localStorage trong khi thực tế sử dụng các API lưu trữ không đồng bộ nâng cao, bao gồm cả 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ể ăn vào ngân sách hiệu suất.

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

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

Nhưng trước khi đi vào chi tiết về mô-đun Bộ nhớ KV, hãy để tôi giải thích ý nghĩa của các mô-đun tích hợp.

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

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

Giống như 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 cần phải trải qua quy trình đánh giá thiết kế và nhận được dấu hiệu hỗ trợ tích cực của 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ể vận chuyển. (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à gửi tất cả các API mới.)

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

Việc không hiển thị mô-đun tích hợp trên toàn cục có nhiều ưu điểm: chúng sẽ không làm tăng thêm bất kỳ hao tổn nào để khởi động ngữ cảnh thời gian chạy JavaScript mới (ví dụ: thẻ, trình thực thi hoặc trình chạy dịch vụ mới) và sẽ không tốn bất kỳ bộ nhớ hoặc CPU nào trừ phi chúng thực sự được nhập. Hơn nữa, chúng không có nguy cơ xung đột khi đặt tên với các biến khá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 Bộ nhớ KV với mã sau (xem bên dưới để biết cách sử dụng polyfill Bộ nhớ KV 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 Bộ nhớ KV 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 JavaScript Map hơn. Thay vì getItem(), setItem()removeItem(), nó có get(), set()delete(). Lớp này cũng có các phương thức giống như bản đồ khác không có cho localStorage, chẳng hạn như keys(), values(), entries() và như Map, khoá của lớp này không nhất thiết phải là chuỗi. Chúng có thể là kiểu nối tiếp có cấu trúc bất kỳ.

Không giống như Map, tất cả phương thức Bộ nhớ KV đều trả về promise hoặc trình lặp 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 API đầy đủ, bạn có thể tham khảo quy cách.

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

storage là một thực thể của lớp StorageArea có tên là 'default' và đây là thực thể mà nhà phát triển sử dụng thường xuyên nhất trong mã xử lý ứng dụng của họ. Lớp StorageArea được cung cấp trong các trường hợp cần tách biệt thêm (ví dụ: thư viện 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 với tên là kv-storage:${name}, trong đó tên là tên của thực thể StorageArea.

Dưới đây là ví dụ về cách sử dụng mô-đun Bộ nhớ KV trong mã của bạn:

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 dùng mô-đun JavaScript gốc trong trình duyệt, thì có lẽ bạn đã biết rằng (ít nhất là cho đến bây giờ) việc nhập bất kỳ nội dung nào không phải là URL sẽ tạo ra lỗi. Và std:kv-storage không phải là URL hợp lệ.

Vấn đề được đặt ra là: chúng ta có phải đợi cho đến khi tất cả các trình duyệt hỗ trợ mô-đun tích hợp rồi mới có thể sử dụng mô-đun đó trong mã hay không? Rất may là 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 một trình duyệt hỗ trợ các mô-đun đó nhờ vào sự trợ giúp của một tính năng khác mà chúng tôi đang thử nghiệm với tên là nhập bản đồ.

Nhập bản đồ

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

Đây là cách hiệu quả vì nó cung cấp cho bạn cách 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.

Đối với mô-đun tích hợp, điều này cho phép bạn tham chiếu một 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 bạn sẽ khai báo bản đồ nhập để việc 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 ánh xạ tới hai tài nguyên khác nhau: std:kv-storage và sau đó là URL gốc /path/to/kv-storage-polyfill.mjs một lần nữa.

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ố tải std:kv-storage, và nếu không thể tải, thì trình duyệt sẽ quay lại tải /path/to/kv-storage-polyfill.mjs.

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

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

Để dùng bản đồ nhập nhằm tải có điều kiện các mô-đun tích hợp, bạn phải sử dụng thực sự các câu lệnh import, tức là 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, và đối với các trình duyệt không hỗ trợ mô-đun này, bạn có thể sử dụng kỹ thuật mô-đun/không mô-đun để phân phát một gói cũ. Xin lưu ý rằng khi tạo bản dựng nomodule, bạn sẽ cần phải thêm tất cả polyfill vì bạn biết chắc rằng những trình duyệt không hỗ trợ mô-đun tích hợp sẽ chắc chắn không hỗ trợ mô-đun tích hợp.

Bản minh hoạ 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ũ hơn, tôi đã tổng hợp một bản minh hoạ kết hợp tất cả kỹ thuật được mô tả ở trên và chạy trong tất cả các trình duyệt hiện nay:

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

Bản minh hoạ được lưu trữ trên Glitch nên 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 tệp README. Hãy xem thử nếu bạn muốn tìm hiểu thêm về cách sản phẩm của công cụ này.

Để thực sự xem mô-đun tích hợp gốc đang 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 đ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 Công cụ cho nhà phát triển; thay vào đó, bạn sẽ thấy phiên bản mô-đun tích hợp (thực tế: bạn thực sự có thể kiểm tra mã nguồn của mô-đun hoặc thậm chí đặt các điểm ngắt vào đó!):

Nguồn mô-đun Bộ nhớ KV 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 sẽ giúp bạn hình dung được những việc có thể có với các mô-đun tích hợp. Và hy vọng là bạn thấy hào hứng! Chúng tôi thực sự muốn các nhà phát triển dùng thử mô-đun Bộ nhớ KV (cũng như tất cả các tính năng mới được thảo luận ở đây) và cho chúng tôi biết ý kiến phản hồi.

Sau đây là các đường liên kết trên GitHub để bạn 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 đang sử dụng localStorage, bạn nên thử chuyển sang KV Storage API để xem API đó có đáp ứng mọi nhu cầu của bạn hay không. Nếu đăng ký bản dùng thử theo nguyên gốc Bộ nhớ KV, bạn thực sự 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.