Ngừng Sử Dụng localStorage Mọi Lúc – Lựa Chọn Tốt Hơn Là Gì?
⚠️ Cảnh báo:
localStorageKHÔNG phải là nơi an toàn để lưu trữ dữ liệu nhạy cảm. Tuy nhiên, nó vẫn được sử dụng phổ biến. Hãy cùng tìm hiểu cách khắc phục điều này bằng cách lựa chọn những phương án lưu trữ tốt hơn.
😰 Vấn Đề: localStorage Giống Như Một Thùng Rác Kỹ Thuật Số
localStorage rất hấp dẫn: nó nhanh chóng, có thể truy cập toàn cầu và không cần thiết lập. Nhưng nó có một số thiếu sót nghiêm trọng:
- ❌ Không mã hóa: Dữ liệu được lưu trữ dưới dạng văn bản thuần túy.
- ❌ Dễ bị tấn công XSS: Các tập lệnh độc hại có thể truy cập vào nó.
- ❌ Đồng bộ: Chặn luồng chính, làm chậm ứng dụng của bạn.
- ❌ Không có thời hạn: Dữ liệu tồn tại vô thời hạn trừ khi được xóa thủ công.
- ❌ Kém cho dữ liệu có cấu trúc: Nó chỉ là các cặp khóa-giá trị.
🧠 Các Lựa Chọn Thông Minh Hơn So Với localStorage
Dưới đây là hướng dẫn nhanh về các tùy chọn lưu trữ tốt hơn dựa trên trường hợp sử dụng của bạn:
| Trường Hợp Sử Dụng | Lựa Chọn Tốt Hơn |
|---|---|
| Dữ liệu phiên tạm thời | sessionStorage |
| Mã thông báo xác thực | HttpOnly Cookies |
| Dữ liệu phức tạp hoặc lớn | IndexedDB hoặc Dexie.js |
| Hỗ trợ ngoại tuyến và tài sản | Cache API + Service Workers |
| Cơ sở dữ liệu trình duyệt quan hệ | SQLite với WebAssembly (ví dụ: sql.js) |
Hãy cùng tìm hiểu từng tùy chọn với các ví dụ cụ thể.
🧪 1. sessionStorage: Lý Tưởng Để Lưu Trữ Dữ Liệu Riêng Tab
sessionStorage lưu trữ dữ liệu chỉ trong thời gian phiên của tab trình duyệt. Khi tab đóng, dữ liệu sẽ biến mất.
// Lưu sở thích giao diện
sessionStorage.setItem("theme", "dark");
// Lấy lại nó
console.log(sessionStorage.getItem("theme")); // "dark"
Ưu điểm:
- ✅ Cách ly với tab hiện tại (không có sự can thiệp giữa các tab).
- ✅ API đơn giản, tương tự như
localStorage.
Nhược điểm:
- ❌ Dữ liệu sẽ bị xóa khi tab đóng.
Trường hợp sử dụng: Lưu trữ trạng thái giao diện tạm thời, như đầu vào biểu mẫu hoặc các cài đặt riêng của tab.
📦 2. IndexedDB (hoặc Dexie.js): Tương Thích, Bất Đồng Bộ và Có Cấu Trúc
IndexedDB là một cơ sở dữ liệu NoSQL mạnh mẽ, bất đồng bộ trong trình duyệt, hoàn hảo cho các tập dữ liệu phức tạp hoặc lớn. Để có API đơn giản hơn, hãy sử dụng Dexie.js, một lớp bọc xung quanh IndexedDB.
🔹 Ví Dụ Với Dexie.js
import Dexie from "dexie";
// Khởi tạo cơ sở dữ liệu
const db = new Dexie("MyAppDB");
db.version(1).stores({
users: "++id, name, age" // ID tự động tăng, các trường được lập chỉ mục
});
// Thêm một người dùng
await db.users.add({ name: "Menula", age: 12 });
// Truy vấn người dùng
const youngUsers = await db.users.where("age").below(18).toArray();
console.log(youngUsers); // [{ id: 1, name: "Menula", age: 12 }]
Ưu điểm:
- ✅ Bất đồng bộ, không chặn.
- ✅ Hỗ trợ các truy vấn phức tạp và tập dữ liệu lớn (trên 100MB).
- ✅ Dữ liệu có cấu trúc với lập chỉ mục.
Nhược điểm:
- ❌ Độ khó học cao hơn so với
localStorage.
Trường hợp sử dụng: Lưu trữ hồ sơ người dùng, trạng thái ứng dụng hoặc tập dữ liệu lớn.
🔐 3. HttpOnly Cookies: Xác Thực An Toàn
Không bao giờ lưu trữ mã thông báo xác thực trong localStorage! Tại sao? Bởi vì bất kỳ JavaScript độc hại nào cũng có thể đọc nó:
// Tập lệnh tấn công
console.log(localStorage.getItem("auth_token")); // 😱 Đánh cắp mã thông báo của bạn!
Thay vào đó, hãy sử dụng HttpOnly Cookies, mà không thể truy cập bởi JavaScript.
Ví Dụ (Máy Chủ):
Set-Cookie: token=abc123; HttpOnly; Secure; SameSite=Strict; Max-Age=3600
Ưu điểm:
- ✅ Không thể thấy bởi JavaScript, giảm thiểu rủi ro XSS.
- ✅ Tự động được gửi cùng với các yêu cầu HTTP.
- ✅ Có thể cấu hình thời gian hết hạn.
Nhược điểm:
- ❌ Giới hạn 4KB cho mỗi cookie.
- ❌ Cần thiết lập phía máy chủ.
Trường hợp sử dụng: Lưu trữ an toàn các mã thông báo xác thực hoặc ID phiên.
🚀 4. Cache API: Hỗ Trợ Ngoại Tuyến & Hiệu Suất
Cache API, kết hợp với Service Workers, là lý tưởng để lưu trữ tài sản hoặc dữ liệu cho các ứng dụng ưu tiên ngoại tuyến hoặc Progressive Web Apps (PWAs).
// Đăng ký Service Worker
navigator.serviceWorker.register("/sw.js");
// Lưu trữ tài sản
caches.open("app-cache").then(cache => {
cache.addAll(["/styles.css", "/script.js"]);
});
Ưu điểm:
- ✅ Kích hoạt chức năng ngoại tuyến.
- ✅ Lấy tài sản nhanh chóng.
- ✅ Tuyệt vời cho PWAs.
Nhược điểm:
- ❌ Cần thiết lập Service Worker.
- ❌ Phức tạp cho dữ liệu động.
Trường hợp sử dụng: Lưu trữ hình ảnh, kịch bản, hoặc phản hồi API để truy cập ngoại tuyến.
🧩 5. SQLite Trong Trình Duyệt: Sức Mạnh Thực Sự Của SQL
Với sql.js, bạn có thể chạy một cơ sở dữ liệu SQLite đầy đủ trong trình duyệt bằng WebAssembly.
import initSqlJs from "sql.js";
// Khởi tạo SQLite
const SQL = await initSqlJs();
const db = new SQL.Database();
// Tạo và điền một bảng
db.run("CREATE TABLE test (col1, col2);");
db.run("INSERT INTO test VALUES (?, ?);", [1, "hello"]);
// Truy vấn dữ liệu
const results = db.exec("SELECT * FROM test");
console.log(results); // [{ col1: 1, col2: "hello" }]
Ưu điểm:
- ✅ Có khả năng SQL đầy đủ.
- ✅ Tuyệt vời cho dữ liệu quan hệ.
- ✅ Khả năng lưu trữ lớn.
Nhược điểm:
- ❌ Cần thiết lập WebAssembly.
- ❌ Chi phí cho các trường hợp sử dụng đơn giản.
Trường hợp sử dụng: Các ứng dụng phức tạp cần dữ liệu quan hệ, như bảng điều khiển hoặc CRM.
✅ Khi Nào localStorage Thực Sự OK?
localStorage không xấu—nó chỉ bị lạm dụng. Nó vẫn ổn để:
- Sở Thích Giao Diện: Ví dụ, lưu giữ lựa chọn giao diện của người dùng (
"dark"hoặc"light"). - Chuyển Đổi Tính Năng: Ví dụ, bật/tắt các tính năng thử nghiệm.
- Siêu Dữ Liệu Không Nhạy Cảm: Ví dụ, cài đặt ứng dụng công khai.
// Sử dụng an toàn `localStorage`
localStorage.setItem("theme", "dark");
localStorage.setItem("feature:beta", "true");
🎯 So Sánh Các Tùy Chọn Lưu Trữ
| Tính Năng | localStorage |
sessionStorage |
IndexedDB |
HttpOnly Cookies |
Cache API |
|---|---|---|---|---|---|
| Liên Tục | ✅ | ❌ | ✅ | ✅ | ✅ |
| An Toàn | ❌ | ❌ | ✅ | ✅ | ✅ |
| Dữ Liệu Có Cấu Trúc | ❌ | ❌ | ✅ | ❌ | ❌ |
| Dung Lượng | ~5MB | ~5MB | 100MB+ | <4KB | Không giới hạn |
| Bất Đồng Bộ | ❌ | ❌ | ✅ | ✅ | ✅ |
🔍 Tóm Tắt Hình Ảnh
Ghi chú: Lấy cảm hứng từ Blog LogRocket.
👋 Suy Nghĩ Cuối Cùng
Ngừng mặc định sử dụng localStorage cho mọi thứ. Thay vào đó, hãy chọn công cụ phù hợp dựa trên:
- 📌 An Ninh: Ưu tiên
HttpOnly Cookiescho xác thực. - 📌 Độ Phức Tạp Dữ Liệu: Sử dụng
IndexedDBhoặc SQLite cho dữ liệu có cấu trúc. - 📌 Hiệu Suất: Tận dụng
Cache APIcho tài sản ngoại tuyến.
Hãy cùng xây dựng ứng dụng web an toàn, nhanh chóng và thông minh hơn! 🚀
💬 Giải Pháp Lưu Trữ Yêu Thích Của Bạn Là Gì?
Bạn có yêu thích IndexedDB? Tin tưởng vào HttpOnly Cookies? Hay bạn đã tìm thấy một cách sử dụng cho sql.js? Hãy chia sẻ công cụ và mẹo yêu thích của bạn trong phần bình luận bên dưới! 👇
❤️ Hỗ Trợ Bài Viết Này
Nếu bạn thấy bài viết này hữu ích, hãy để lại một ❤️, 🦄, hoặc 📝 trên Dev.to để tiếp tục chia sẻ kiến thức!