WebStorageのお作法「◯◯Storage.clear()は使わない」
Webサイトにリッチな機能を持たせる際にとても強い味方になってくれるWebStorage。
昨今、webサイトやwebアプリケーションが大きく発達していく中で、UX(ユーザー体験)向上の為に様々な技術や機能が盛り込まれています。
その中で、ユーザーの行った操作のデータを保持しておく必要があるケースも非常に増えています。
『ユーザーの行った操作のデータ』などと言うと「トラッキングだ」といったような感覚を受けるかもしれませんが、もっと単純な部分で
例えば
- ECサイトでカートに追加した品物
- SNS等で最後にログインしてから新着があったか
- UI、レイアウトの切り替え
といったようなもの。
こういった機能が無いと逆に不便だと感じるものですよね?
「便利な機能」を実現する為には操作のデータを保持しなければならないケースも多々あります。
3つ目のものはこの画像のようなものなどを指します。
数年前からちょくちょく見かけるもので、「シングルレイアウトとグリッドレイアウト」のようにUI、レイアウトを切り替えられるサイトなどがありますが、せっかく切り替えたのにページ移動の度にリフレッシュされては使用感が非常に悪いものになってしまいますね?こういったケースでも「操作のデータを保持」しておく必要があります。
これらのように、データを保持する際、今まではcookieでやっていたことをWebStorageで行うサイトが増えています。
それらの理由として、制作作側の利点が多い為です。
例えば、
- WebStorageはcookieに比べ、はるかに大容量のデータを扱うことができる
- WebStorageは実装が非常にシンプル
- 容量内であれば保存数に制限が無い(※cookieにはドメインに対して保存できる最大個数がある)
また、WebStorageは似たような機能のindexedDBに比べてもはるかにシンプルにフロントエンドでデータベースを設計・構築できる。 (※indexedDBの方が複雑なことができるが実装も複雑になる)
中でもlocalStorage
を代替として利用する方が多いと感じます。
けれど忘れてはならないのはlocalStorageのデータは大容量かつ永続的であるということ。
sessionStorageならばブラウザのタブを閉じるだけで削除されますが、localStorageは実装者がデータを削除するプログラムを用意しない限り、永遠に保持され続けられます。
しかもユーザー側からすれば、cookieとWebStorageどちらを使っているかは分からない。
一般的なユーザーがDeveloper toolsを開くことなどありません。
ブラウザによっては「ブラウザの履歴とcookie削除」をしてもlocalStorageのデータは保持されるものも少なくない。
しかし、ほとんどのサイトではユーザーが任意にlocalStorageを削除できるインターフェースを用意していない。
ならばlocalStorageに保存されたデータはどうなるのだろう?
多くのサイトでlocalStorageを使うようになれば
ユーザーのデバイス(のストレージ)には消すことのできないジャンクデータがどんどん蓄積されていってしまう。
それなのに、localStorageを使用して良いかユーザーに確認する「confirm」も用意していない。
これはユーザーフレンドリーな実装だろうか?
WebStorageを使うのが自分だけとは考えないこと
WebStorageの保存領域はドメインに対して共通です。
クライアント様のサイトにコンテンツを追加したり、メインテナンスするのは自分だけとは言い切れないはずです。
にも関わらず、無作為にlocalStorageを使用したり、そのKey/Valueの設定を安易に行ってしまうと、他の製作者がコンテンツ追加した際などにバグを引き起こします。
逆もしかりで、すでにlocalStorageが使用されているサイトに対して、新たにlocalStorageを使ったコンテンツを追加する際には注意しましょう。
localStorageは単純なKey/Value方式です。
不適切な実装では、その操作で消してはならないデータを上書きしてしまったり削除してしまったり、といったことが起こりやすいのです。
WebStorageを使う時の作法
1.Keyにプレフィックスを使う
自社(自分)用の一意なプレフィックスを用意して、例えば「プレフィックス+番号」といったようなKeyにしておく。
localStorage.setItem('myPrefix_1', val ); localStorage.setItem('myPrefix_2', val ); localStorage.setItem('myPrefix_3', val );
このような感じにデータを扱うと、例え他のランダムなkeyがStorageに紛れても、自社の扱っているデータのみを抽出するのが容易になります。
もちろん、サイト内でコンテンツを扱う全ての方がそれぞれ一意なプレフィックスを用いれば、それぞれのデータが干渉し合うこともありません。
2.削除用インターフェースを用意する
これまでの製作で僕もいくつかのlocalStorageを用いたアプリケーションやプラグインをサイトに組み込んできました。
例えばこちら
※麻布テーラー様website My Menuアプリ(https://www.azabutailor.com)
リンク先で実際の使用感も試していただけます。
このように、簡単な操作でlocalStorageに保存したデータを削除できるインターフェースを実装しています。
(※加えて、ユーザーが「能動的に」お気に入りに追加しない限り、localStorageを使用しません)
動画右1/3側にデベロッパーツールを表示させていますが、操作と連動してデータの追加/削除が行われているのが見て取れるかと。
削除用インターフェースは可能な限りシンプルかつ直感的な操作で行えるものにすべきと考えます。
説明文がいちいち必要にならないレベルに。
特にモバイルでの操作を考え、何度もタップが必要なものは控えるべきでしょう。また、フリック操作に対応させたりすると尚良いと考えます。
※このアプリではkeyに複数のプレフィックスを用いています。
登録したデータ毎にカテゴリー分けをする為に複数用いましたが、削除用の処理が複雑になるので慣れるまでは単一のプレフィックスで行うのがおすすめかもしれません。
3.localStorage.clear()は安易に使わない
ただし、削除時にlocalStorage.clear()
は絶対に使わないようにしましょう。
なぜなら、1の箇所でも触れたように、自分以外の製作者が同ドメイン上のコンテンツでlocalStorageを使用したコンテンツを追加していた際、消してはならないデータまで削除してしまいます。
もし、先ほど紹介したMyMenuアプリのように、ユーザーが「お気に入り」として保存しているデータがあった場合は…?
データの復旧もできない為、著しくサイトのUXを損ねます。
自分が作ったコンテンツのkeyには特定の規則性を持たせるなり、まとめて削除する際にも処理しやすいよう工夫しましょう。
// Ex. localStorageのkeyに「prefix_」と連番を用いる function listDelete(){ // 引数でプレフィックスを渡せるようにするのも良いと思います for(let i = 0; i < something.length; i++){ let keyname = 'prefix_'+(i+1); localStorage.removeItem( keyname ); } } function deleteItem(){ const target = this.getAttribute('data-key'); localStorage.removeItem( target ) } // データをまとめて削除する為のボタン const deleteBtn = document.getElementById('delete-btn'); deleteBtn.addEventListener('click', listDelete); // データを一つだけ削除するボタン const deleteBtn_single = document.getElementById('delete-single'); deleteBtn_single.addEventListener('click', deleteItem);
前述のMyMenuアプリで「全件削除」を行った際も、記事のデータのみをforループで削除する方式を取っている為、他のデータが紛れてもそれらを削除はしません。
(※それ以外のデータはif分岐+continueで処理を飛ばすようにしています。)
4.容量が大きいからといって無闇に使いすぎない
WebStorageは同期的です。
ページロードのタイミングで保存されているデータを読み込みますが、例えばその際何Mものデータを保存していたとすれば ページで読み込むのファイルのデータ量+WebStorageのデータ量がダウンロードされる為 ページ表示速度を著しく遅める要因にもなりかねます。
大容量を扱えるからといって、過度に容量を使いすぎないよう気を付けましょう。
まとめ
WebStorageは非常に便利で様々な場面で役立ってくれます。
その分、使いたくなる場面も多いでしょう。
それだけに扱う際にはちょっと気を付けて
- Keyにプレフィックスを使う
- 削除用インターフェースを用意する
- localStorage.clear()は安易に使わない
- 容量が大きいからといって無闇に使いすぎない
の4つのポイントを意識して実装してみてください。
きっと、このほんのちょっとの気遣いで、ユーザーにとっても心地よく、制作側にとってもメンテナンス性と拡張性の高い心地よいサイトやアプリケーションになることでしょう。
Comments
自分が管理するアプリケーションのWEBストレージに一意なキー名を振る簡単な方法の例。
const storageKey = 'applicationName:' + location.pathname;
キーにlocationのパス名も加える。
プレフィックスに何を選ぶか、の基本的な考え方としてはそういう感じでいいと思います。
ただ、location.pathnameは場合によっては非常に長くなるケースもあります。(Ex.URLに日本語などマルチバイト文字を使っているケース)
そういったケースではWebStorageに保存される1件あたりのデータが大きくなる為、ページ表示速度に悪影響を与えることも想定されます。
おそらくアプリケーションの動作に重要なデータはkeyよりもvalueであり、そこに様々な情報を格納するかと思います。
なので可能な限りkeyはデータ量を極力使わない、シンプルなプレフィックスになるように構成するのが個人的にはおすすめかなと考えています。