分手吧 LocalStorage,我愛上了 RemoteStorage!

2024年2月6日 20点热度 0人点赞

大傢好,很高興又見面了,我是"高級前端進階",由我帶著大傢一起關註前端前沿、深入前端底層技術,大傢一起進步,也歡迎大傢關註、點贊、收藏、轉發!

1. 什麼是 RemoteStorage

RmoteStorage is a simple library that combines the localStorage API with a remote server to persist data across browsers and devices.

在 localStorage 中存儲數據很有用,但當數據需要在多個設備或瀏覽器之間共享時,這並不是一個好的解決方案。

例如,假設想向所有註冊產品的新用戶顯示歡迎模式,如果使用 localStorage 來跟蹤用戶是否已經看到此模式,則用戶每次切換設備或瀏覽器時都會重復展示該模式。

這就是 RemoteStorage 的用武之地,其使用與 localStorage 相同的 API,remoteStorage 允許開發者輕松地動態讀寫數據,同時跨瀏覽器和設備維護狀態,以提供更好的用戶體驗。

總結起來看,RemoteStorage 有以下優秀特性:

  • ✨ 簡單的 API(與 localStorage 相同)
  • 適用於所有 Javascript 框架
  • 輕量級(縮小到 1 kB)
  • 開源服務器和客戶端(MIT 許可證)
  • 免費托管社區服務器

目前 RmoteStorage 在 Github 通過 MIT 協議開源,是一個值得關註的前端開源項目。

2.RemoteStorage 的三要素

用戶 ID

RemoteStorage 使用用戶 ID 來識別用戶,用戶 ID 是唯一標識用戶的字符串。 它可以是您想要的任何內容,但建議使用不可迭代的 UUID 以防止用戶猜測其他用戶 ID 並訪問其數據。

用戶 ID 在創建 RemoteStorage 的新實例時設置:

const remoteStorage = new RemoteStorage({
  userId: '123e4567-e89b-12d3-a456-426614174000'
})

如果不提供用戶 ID,remoteStorage 將生成一個隨機 UUID,每次用戶訪問站點時該 UUID 都會發生變化。 這對於測試很有用,但違背了遠程存儲的目的,因為數據不會跨設備或瀏覽器持久保存。

實例 ID

RemoteStorage 使用實例 ID 來標識發出請求的應用程序實例, 實例 ID 是唯一標識應用程序實例的字符串。 通常,需要對來自同一應用程序實例的所有請求使用相同的實例 ID。

實例 ID 在創建 RemoteStorage 的新實例時設置:

const remoteStorage = new RemoteStorage({
  userId: '123e4567-e89b-12d3-a456-426614174000',
  instanceId: 'my-cool-app'
})

服務器

RemoteStorage 在
https://api.remote.storage 上提供免費的托管社區服務器(如果未提供 serverAddress,則為默認行為)。 此托管服務器不應用於生產應用程序,但它非常適合測試和原型設計。

要使用不同的服務器,隻需在創建 RemoteStorage 的新實例時傳遞 serverAddress 選項即可:

const remoteStorage = new RemoteStorage({
  serverAddress: 'https://api.remote.storage',
  userId: '123e4567-e89b-12d3-a456-426614174000',
  instanceId: 'my-cool-app'
})

自托管服務器的唯一前提是運行 Docker 和 Docker Compose 的系統。

使用 Docker 和 docker-compose 可以在幾分鐘內啟動服務器,該鏡像附帶在端口 6379 上運行的 Redis 服務器以及在端口 4000 上運行的應用程序服務器。

首先,隻需運行以下命令:

git clone [email protected]:FrigadeHQ/remote-storage.git
cd remote-storage/apps/remote-storage-server
cp .env.example .env
docker-compose build
docker-compose up

此時服務器會在端口 4000 上運行,可以通過獲取和設置一個值來測試:

curl -i -X PUT \
   -H "x-remote-storage-instance-id:my-instance-id" \
   -H "x-remote-storage-user-id:user-123" \
   -d \
'{"foo":"bar"}' \
 'http://localhost:4000/entities/some-key'

下面是具體的返回值:

curl -i -X GET \
   -H "x-remote-storage-instance-id:my-instance-id" \
   -H "x-remote-storage-user-id:user-123" \
 'http://localhost:4000/entities/some-key'
HTTP/1.1 200 OK
{"foo":"bar"}

3. 如何使用 RemoteStorage

首先需要安裝依賴:

npm install remote-storage

接著,可以導入庫並像 localStorage 一樣使用:

import {RemoteStorage} from 'remote-storage'
const remoteStorage = new RemoteStorage({userId: "my-user-id"})
const hasSeenNewFeature = await remoteStorage.getItem('hasSeenNewFeature')
if (!hasSeenNewFeature) {
  await remoteStorage.setItem('hasSeenNewFeature', true)
  // Highlight your new and exciting feature!
}

4.RemoteStorage 的三個疑問

應該在遠程存儲中存儲哪些數據

RemoteStorage 隻能用於非敏感數據,建議將其用於用戶首選項、設置和其他非敏感數據等。 由於公共 API 的性質,它不太適合存儲密碼或 PII 等敏感數據。

import {RemoteStorage} from 'remote-storage'
const remoteStorage = new RemoteStorage({userId: "my-user-id"})
// 註意:不建議保存敏感數據
const hasPassword = await remoteStorage.getItem('password')
if (!hasPassword) {
  await remoteStorage.setItem('password', true)
  // Highlight your new and exciting feature!
}

遠程存儲與本地存儲有何不同

localStorage 是一個瀏覽器 API,允許在瀏覽器中存儲數據。 數據本地存儲在用戶設備上,不會在設備或瀏覽器之間共享。 RemoteStorage 是一個將 localStorage API 與遠程服務器相結合的庫,可跨瀏覽器和設備保存數據。

// 隻存在在本地
const person = {name: "Alex"};
localStorage.setItem("user", person);
console.log(localStorage.getItem("user"));
// "[object Object]"; not useful!
localStorage.setItem("user", JSON.stringify(person));
console.log(JSON.parse(localStorage.getItem("user")));
// {name: "Alex"}

難道任何人都不能猜測用戶 ID 並訪問其他人的數據嗎

可以使用由包(例如 uuid)生成的秘密唯一 UUID 作為用戶 ID,以保護對遠程存儲的調用。 不建議使用連續的數字 ID 或用戶的電子郵件地址,因為這樣可以輕松猜測其他用戶 ID 並訪問他們的數據。

import {v1 as uuidv1 , v3, v5, v4 as uuidv4} from 'uuid';
uuidv4(); // ⇨ '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
uuidv1(); // ⇨ '2c5ea4c0-4067-11e9-8bad-9b1deb4d3b7d'
// 輸入配置
const v1options = {
  node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
  clockseq: 0x1234,
  msecs: new Date('2011-11-01').getTime(),
  nsecs: 5678,
};
uuidv1(v1options); // ⇨ '710b962e-041c-11e1-9234-0123456789ab'

或者,可以圍繞 RemoteStorage 創建一個簡單的包裝器 / 代理 API,該 API 使用您自己的身份驗證方法來驗證用戶的身份,然後再允許訪問數據。 然後,可以選擇一個不公開的安全且秘密的實例 ID,以確保隻有應用程序可以訪問數據。

參考資料

https://github.com/FrigadeHQ/remote-storage

https://github.com/FrigadeHQ/remote-storage/blob/main/apps/remote-storage-server/README.md

https://github.com/FrigadeHQ/remote-storage

https://remote.storage/

https://developer.mozilla.org/en-US/docs/Web/API/Storage/setItem

https://github.com/uuidjs/uuid

https://www.freecodecamp.org/news/how-to-store-objects-or-arrays-in-browser-local-storage/

https://www.codeproject.com/Articles/5329553/Use-Remote-Storage-a-Community-Derived-FOSS-Offlin

https://gamedevjs.com/articles/using-local-storage-for-high-scores-and-game-progress/