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.storage là bộ 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ộ và không có trong service worker (không window). chrome.storage là bấ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
| Area | Size | Scope | Xóa khi | Dùng cho |
|---|---|---|---|---|
local | ~10 MB | máy này | gỡ cài | đa số dữ liệu, cache |
sync | ~100 KB (8 KB/item) | theo user qua thiết bị | on uninstall | cài đặt nhỏ |
session | ~10 MB | chỉ bộ nhớ | đóng trình duyệt | token, 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 onChanged ở mọ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. localcho đa số dữ liệu,synccho cài đặt roaming nhỏ,sessioncho bí mật.onChangedgiữ 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.