indexedDB
PWA

IndexedDBの利用例としてMicrosoft To-Doを読み解く

最近趣味でIndexedDBを利用したオフライン完結型のアプリケーションを書いている。
他サイトのIndexedDBの利用例でMicrosoft To-Doで一番ちゃんと使われてた気がするので利用例としてスキーマを読み解く。

IndexedDBの確認方法

以前から使われているLocalStorageと比べて
- (ブラウザに依るが)単純に容量がでかい
- indexを貼れる
- Objectをそのまま格納出来る
あたりがメリットになる。
このあたりは別の記事を見るとよい

Chromeで中身を確認するには、DeveloperToolsのApplicationタブ、StorageのIndexedDBを見ればよい。
各テーブルのデータを確認出来る。

スクリーンショット 2018-04-06 11.29.27.png

Microsoft To-Do

Microsoftが開発しているToDo管理アプリケーション。
タスクを複数格納出来るlistがある一般的なTodo管理アプリケーションで、オフラインで動作する。

スクリーンショット 2018-04-06 14.33.58.png

https://todo.microsoft.com/

Table

2018/4/6現在は以下の6テーブル
- settings
- steps
- tasks
- members
- lists
- sync

基本的にすべてのテーブルは1つのユニークキーを持っていて、キーに対してObjectを持っている様子。

settings

{
  id: "l-5oo86"
  key: "onboarding_detail_tooltip_dismissed"
  local_id:"l-5oo86"
  remote_id: undefined
  value: true
}
  • いわゆるkey,valueな感じのオブジェクトが保存されている。primaryKeyはkeyが設定されている。
  • remote_idはtasksを見る限りサーバーサイドで持っているidが振られる様子だが、settingsに関してはremote_idが振られているレコードはないのでクライアントでのみ保存している可能性が高い

tasks

{
  ChangeKey: "XAI/lv8jBkOPt79WuS0NSwAAnP2j=="
  committed_day: undefined
  completed: false
  completed_at: undefined
  created_at: {date_time: "2017-05-04T18:22:51.500", time_zone: "UTC"}
  due_date: undefined
  id: "AQMkADAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgBGAAADVFc0lFz6P0m-xARjTHHhrAcAXAI-lv8jBkOPt79WuS0NSwAAAJzsHc4AAABcAj_W-yMGQ4_3v1a5LQ1LAAAAnOwloAAAA=="
  is_ignored: undefined
  is_reminder_on: false
  list_id: "AQMkADAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgAuAAADVFc0lFz6P0m-xARjTHHhrAEAXAI-lv8jBkOPt79WuS0NSwAAAJzsHc4AAA="
  local_id: "AQMkADAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgBGAAADVFc0lFz6P0m-xARjTHHhrAcAXAI-lv8jBkOPt79WuS0NSwAAAJzsHc4AAABcAj_W-yMGQ4_3v1a5LQ1LAAAAnOwloAAAA=="
  note: ""
  note_updated_at: undefined
  position: 1493922090000
  postponed_day: undefined
  recurrence: undefined
  reminder: undefined
  remote_id: "AQMkADAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgBGAAADVFc0lFz6P0m-xARjTHHhrAcAXAI-lv8jBkOPt79WuS0NSwAAAJzsHc4AAABcAj_W-yMGQ4_3v1a5LQ1LAAAAnOwloAAAA=="
  remote_list_id: "AQMkADAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgAuAAADVFc0lFz6P0m-xARjTHHhrAEAXAI-lv8jBkOPt79WuS0NSwAAAJzsHc4AAA="
  source: undefined
  title: "タスクネーム"
  today_position: undefined
}
  • primaryKeyはidになっている。
  • remote_id, remote_list_idがおそらくサーバー側でのpkey。
  • list_idはlistsのレコードに対する外部キー
  • ChangeKeyを見てサーバーサイドのデータと動機を取っているように見える。

lists

{
  background: "mountains"
  id: "inbox"
  is_owner: true
  is_shared_folder: false
  local_id: "inbox"
  members: []
  position: 1493835505000
  remote_id: "AQMkADAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgAuAAADVFc0lFz6P0m-xARjTHHhrAEAXAI-lv8jBkOPt79WuS0NSwAAAgESAAA"
  sharing_sync_status: "Synced"
  show_completed: false
  sort_asc: true
  sort_type: 1
  theme: "blue"
  title: "タスク"
}

sync

{
  id : "sync-key"
  queue : [
    {
      data : 
        committed_day : {date_time: "2018-04-06", time_zone: "Asia/Tokyo"} 
        id : "l-5hkdu"
        list_id : "inbox"
        local_id : "l-5hkdu"
        position : 1492520890000
        postponed_day : null
        remote_id : undefined
        remote_list_id : "AQMkAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgAuAAADVFc0lFz6P0m-xARjTHHhrAEAXAI-lv8jBkOPt79WuS0NSwAAAgESAAAA"
        title : "aaaa"
        today_position : 1522984086542
      type : "CREATE_TASK"
    }
  ]
  length : 1
}
  • sync-keyという1レコードのみ
  • queueが合って、typeとdataがセットになったデータが入ってる。fluxのアクション的なノリ
  • オンラインになると実行される

steps, members

この2つのテーブルに保存されているデータを見たことがない
membersはタスクの共有用なんだろうなとは思ったけど、UI上で共有する方法が分からない

おわり

  • Firebase使ってアプリ書くとオンライン・オフライン対応してくれてキューとか意識しなくてよかったので、自前でやる時の参考になりそうだった。
  • indexがkeyにしか振られてないので、まだlocalStorageの延長線上の使い方だなーという印象
  • remote_idなどクライアントとサーバーをまたいだデータやりとりはWebエンジニアとしてはあまりやらないので、デスクトップやスマートフォン上での設計は学ぶ必要性が強くなっているように感じた。(ReactNativeとかPWAの文脈として)