jvinhit//lab

Search posts

Type to search across journal entries.

navigate open esc close

Build Chrome Extensions · Part 7 — Storage

chrome.storage in depth: local vs sync vs session, quotas and item limits, the onChanged event for reactive UIs, storage as the single source of truth, and migrating data shapes between versions. With an interactive storage explorer.

Vì service worker không trạng thái và mọi ngữ cảnh cô lập, chrome.storagebộ não chung của extension. Nó là nơi duy nhất mọi phần đọc và ghi được, và nền tảng của UI phản ứng, đa-ngữ-cảnh.

Đặt key, xem thanh hạn mức, và thấy onChanged kích hoạt bên dưới:


1. Vì sao không dùng localStorage?

localStorage của web là đồng bộkhông có trong service worker (không window). chrome.storagebất đồng bộ, truy cập được từ mọi ngữ cảnh kể cả worker, và phát sự kiện thay đổi. Luôn dùng chrome.storage.

await chrome.storage.local.set({ theme: "dark" });
const { theme } = await chrome.storage.local.get("theme");
const all = await chrome.storage.local.get(null); // everything
await chrome.storage.local.remove("theme");
await chrome.storage.local.clear();

Cần quyền "storage" trong manifest.


2. Ba khu vực

AreaSizeScopeXóa khiDùng cho
local~10 MBmáy nàygỡ càiđa số dữ liệu, cache
sync~100 KB (8 KB/item)theo user qua thiết bịon uninstallcài đặt nhỏ
session~10 MBchỉ bộ nhớđóng trình duyệttoken, state tạm

sync tự roam cài đặt tới nơi user đăng nhập — nhưng nó bé và giới hạn tốc độ, nên chỉ để cài đặt nhỏ. session là nhà đúng cho bí mật bạn không muốn ghi xuống đĩa. Đổi khu vực trong explorer để so hạn mức.


3. onChanged — xương sống phản ứng

Đây là tính năng làm storage mạnh mẽ. Bất kỳ lần ghi nào cũng kích onChangedmọi ngữ cảnh đang lắng nghe:

chrome.storage.onChanged.addListener((changes, area) => {
  if (area === "local" && changes.theme) {
    applyTheme(changes.theme.newValue); // oldValue also available
  }
});

Thay vì phát tin nhắn thủ công để giữ popup, content script và options page đồng bộ, ghi một lần vào storage và để mọi người phản ứng. Đây là mẫu state xuyên-ngữ-cảnh sạch nhất.


4. Storage làm nguồn sự thật duy nhất

Kết hợp các bài đến giờ:

  • Popup là view: đọc khi mở, ghi khi đổi.
  • Worker không trạng thái: đọc từ storage đầu handler.
  • Content script phản ứng onChanged để cập nhật trang trực tiếp.

Storage là trung tâm bền; mọi thứ khác phù du và dựng lại được từ nó.


5. Hạn mức và tránh lỗi MAX_WRITE

sync giới hạn ~1.800 lần ghi/giờ và 120 lần ghi/phút. Đừng ghi mỗi phím gõ — debounce:

let pending;
function saveDebounced(value) {
  clearTimeout(pending);
  pending = setTimeout(() => chrome.storage.sync.set({ draft: value }), 500);
}

Gộp nhiều key vào một lời gọi set({ a, b, c }) thay vì ba lời gọi riêng. Xem thanh hạn mức chuyển hổ phách rồi đỏ trong explorer.


6. Mặc định và di trú

Đặt mặc định một lần khi cài, và đọc kèm fallback để key thiếu không bao giờ làm crash:

// onInstalled
chrome.runtime.onInstalled.addListener(({ reason }) => {
  if (reason === "install") {
    chrome.storage.local.set({ version: 2, settings: { theme: "dark" } });
  }
  if (reason === "update") migrate();
});

// reading with a default
const { settings = { theme: "dark" } } = await chrome.storage.local.get("settings");

Khi đổi cấu trúc dữ liệu giữa các phiên bản, chạy di trú ở nhánh update — đọc cấu trúc cũ, chuyển đổi, ghi cấu trúc mới, tăng version đã lưu.


7. Một wrapper có kiểu nhỏ

Tập trung truy cập để không rải string key thô khắp nơi:

interface Settings { theme: "dark" | "light"; count: number; }
const DEFAULTS: Settings = { theme: "dark", count: 0 };

export async function getSettings(): Promise<Settings> {
  const stored = await chrome.storage.local.get(DEFAULTS);
  return stored as Settings;
}
export function setSettings(patch: Partial<Settings>) {
  return chrome.storage.local.set(patch);
}

Một module sở hữu key, mặc định, và kiểu — mọi ngữ cảnh import nó.


8. Bài tập

1. Bạn cần một token xác thực không bao giờ ghi xuống đĩa và biến mất khi đóng trình duyệt. Khu vực nào?

Lời giải

chrome.storage.session — trong bộ nhớ, xóa khi đóng trình duyệt.

2. Options page lưu blob JSON 30 KB vào sync và bị lỗi QUOTA_BYTES_PER_ITEM. Vì sao, và sửa thế nào?

Lời giải

sync giới hạn mỗi item ~8 KB. Lưu dữ liệu lớn trong local (chỉ cài đặt nhỏ trong sync).

3. Đổi cài đặt ở options page nên restyle ngay content script đang mở. Làm sao mà không messaging?

Lời giải

Content script lắng nghe chrome.storage.onChanged và phản ứng theo giá trị mới.

Nâng cao:trong explorer, chuyển sang sync, thêm một giá trị lớn, và xem thanh hạn mức tiến tới giới hạn 100 KB nhỏ nhanh hơn local nhiều.


Điểm chính

  • Dùng chrome.storage, không bao giờ localStorage — bất đồng bộ và worker truy cập được.
  • local cho đa số dữ liệu, sync cho cài đặt roaming nhỏ, session cho bí mật.
  • onChanged giữ mọi ngữ cảnh đồng bộ — ưu tiên hơn phát thủ công.
  • Storage là nguồn sự thật duy nhất; mọi thứ khác dựng lại từ nó.
  • Debounce lần ghi và di trú cấu trúc giữa phiên bản.

Tiếp theo

Phần 8 — Bề mặt UI: popup, options page, side panel, và action API (chữ badge, icon, tiêu đề) — chọn đúng bề mặt và nối chúng với storage.