MochiuWiki : SUSE, EC, PCB
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
JavaScriptの基礎 - Web Storageのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
JavaScriptの基礎 - Web Storage
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == Web Storage APIは、Webブラウザがキー・バリューペア形式のデータをクライアント側に保存するための仕組みである。<br> WHATWG HTML Web Storage仕様に基づいて実装されており、全ての主要なWebブラウザでサポートされている。<br> <br> Web Storageには、<u>localStorage</u> と <u>sessionStorage</u> の2つのオブジェクトが存在する。<br> <u>localStorage</u> はWebブラウザを閉じても永続的にデータを保存し、<u>sessionStorage</u> はタブを閉じるとデータが削除される。<br> <br> <u>Web Storage APIが保存できるデータは文字列のみである。</u><br> オブジェクトや配列を保存する場合は、<code>JSON.stringify()</code> で文字列に変換してから保存し、取得時に <code>JSON.parse()</code> で復元する必要がある。<br> <br> 他のストレージ手段との位置付けとして、Cookieはサーバとの通信に付随する小容量のストレージ (最大4[KB]) であり、IndexedDBは大容量・複雑なデータを扱うための非同期APIである。<br> Web Storageはこれら2つの中間に位置する手段であり、シンプルなキー・バリュー形式のデータを5〜10[MB]程度まで保存する用途に適している。<br> <br><br> == Web Storageの基本 == ==== localStorage と sessionStorageの違い ==== 下表に、<u>localStorage</u> と <u>sessionStorage</u> の主な違いを示す。<br> <br> <center> {| class="wikitable" |+ localStorage と sessionStorage の比較 ! 項目 !! localStorage !! sessionStorage |- | ライフサイクル || 明示的に削除するまで永続 || タブ・ウィンドウを閉じると削除 |- | スコープ || 同じオリジンの全てのタブ・ウィンドウ || 各タブ・ウィンドウで独立 |- | 容量 || 約5〜10[MB] || 約5〜10[MB] |- | ページリロード || 保持される || 保持される |- | 主な用途 || ユーザ設定、テーマ設定、ログイン状態 || フォーム入力の一時保存、ページ間の状態管理 |} </center> <br> <u>sessionStorage</u> は、タブを閉じると削除される点を除いてほぼ同じAPIを持つ。<br> ページのリロードや、Webブラウザの[戻る] / [進む]操作の後もデータは保持される。<br> <br><br> == データの保存と取得 == Web Storage APIのメソッドは、<u>localStorage</u> と <u>sessionStorage</u> のどちらでも共通して使用できる。<br> 以下の説明では <u>localStorage</u> を例に示す。<br> <br> ==== setItem / getItem ==== <code>setItem(key, value)</code> は、指定したキーとバリューのペアを保存する。<br> <br> キーが既に存在する場合はバリューが上書きされる。<br> キーとバリューはどちらも文字列として保存される。<br> <br> <code>getItem(key)</code> は、指定したキーに対応するバリューを返す。<br> キーが存在しない場合は <u>null</u> を返す。<br> <br> <syntaxhighlight lang="javascript"> // データの保存 localStorage.setItem("username", "Alice"); localStorage.setItem("theme", "dark"); // データの取得 const username = localStorage.getItem("username"); console.log(username); // "Alice" // 存在しないキーの取得 const missing = localStorage.getItem("nonExistentKey"); console.log(missing); // null </syntaxhighlight> <br> ストレージの容量を超えた場合、<code>setItem()</code> は 例外 <code>QuotaExceededError</code> (DOMException) を発生させる。<br> エラーハンドリングを行う場合は、<code>try...catch</code> を使用する。<br> <br> <syntaxhighlight lang="javascript"> function saveWithQuotaCheck(key, value) { try { localStorage.setItem(key, value); } catch (e) { if (e.name === "QuotaExceededError") { console.error("ストレージ容量が超過しました"); } } } </syntaxhighlight> <br> ==== removeItem / clear ==== <code>removeItem(key)</code> は、指定したキーとそのバリューをストレージから削除する。<br> 指定したキーが存在しない場合は何も起こらない。<br> <br> <code>clear()</code> は、ストレージ内の全てのキーを削除する。<br> <br> <syntaxhighlight lang="javascript"> // 特定のキーを削除 localStorage.removeItem("theme"); // 全データを削除 localStorage.clear(); </syntaxhighlight> <br> ==== key / length ==== <code>length</code> は読み取り専用プロパティで、ストレージに保存されているデータ項目の数を返す。<br> <br> <code>key(index)</code> は、指定したインデックス (0始まり) に対応するキー名を返す。<br> インデックスが範囲外の場合は、<code>null</code> を返す。<br> <br> <code>key()</code> と <code>length</code> を組み合わせることにより、ストレージ内の全データをイテレーションできる。<br> <br> <syntaxhighlight lang="javascript"> // ストレージ内の全てのキーをイテレーション for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); const value = localStorage.getItem(key); console.log(`${key}: ${value}`); } </syntaxhighlight> <br><br> == JSON変換 == ==== 文字列のみ保存可能な理由 ==== Web Storage APIの仕様上、キーとバリューはどちらも文字列型として保存される。<br> 数値、真偽値、オブジェクト、配列等を直接保存しようとすると、自動的に文字列へ変換される。<br> <br> 例えば、数値 <u>42</u> を保存すると文字列 <u>"42"</u> として保存されるため、取得後に数値として扱う場合は型変換が必要になる。<br> オブジェクトを直接保存すると <code>"[object Object]"</code> という文字列に変換され、元のデータを復元できなくなる。<br> <br> このため、文字列以外のデータを保存する場合は <code>JSON.stringify()</code> と <code>JSON.parse()</code> を使用する必要がある。<br> <br> ==== オブジェクトと配列の保存 ==== オブジェクトや配列を保存する場合は、<code>JSON.stringify()</code> でJSON文字列に変換してから保存する。<br> 取得時は <code>JSON.parse()</code> で元のデータ型に復元する。<br> <br> <syntaxhighlight lang="javascript"> // オブジェクトの保存 const userSettings = { theme: "dark", fontSize: 14, language: "ja", }; localStorage.setItem("settings", JSON.stringify(userSettings)); // オブジェクトの取得 const savedSettings = JSON.parse(localStorage.getItem("settings")); console.log(savedSettings.theme); // "dark" // 配列の保存 const bookmarks = ["page1", "page2", "page3"]; localStorage.setItem("bookmarks", JSON.stringify(bookmarks)); // 配列の取得 const savedBookmarks = JSON.parse(localStorage.getItem("bookmarks")); console.log(savedBookmarks[0]); // "page1" </syntaxhighlight> <br> ==== 型情報の注意点 ==== <code>JSON.stringify()</code> による変換では、一部のデータ型に関する情報が失われる点に注意が必要である。<br> <br> 下表に示す型は JSON変換で失われる または データが変化する。<br> <br> <center> {| class="wikitable" |+ JSON変換で失われる、またはデータが変化する型 ! 型 !! 説明 |- | <u>undefined</u> (オブジェクトのプロパティ値) || オブジェクトのプロパティ値が <u>undefined</u> の場合、そのプロパティはJSONに含まれない。 |- | 関数 (Function) || 関数はJSONに変換されず、プロパティごと除外される。 |- | シンボル (Symbol) || シンボルはJSONに変換されず、プロパティごと除外される。 |- | <code>Date</code> オブジェクト || ISO 8601形式の文字列に変換される。<br><code>JSON.parse()</code> 後は <code>Date</code> オブジェクトではなく文字列のままになる。 |- | <u>undefined</u> (配列の要素) || 配列内の <u>undefined</u> 要素は <u>null</u> に変換される。 |} </center> <br> <code>Date</code> オブジェクトを復元する場合は、<code>JSON.parse()</code> の第2引数にリバイバー関数を使用することで対応できる。<br> <br> <syntaxhighlight lang="javascript"> // Dateオブジェクトを含むデータの保存 const data = { name: "イベント", createdAt: new Date(), }; localStorage.setItem("event", JSON.stringify(data)); // リバイバー関数でDateを復元 function dateReviver(key, value) { if (typeof value === "string") { const datePattern = /^\d{4}-\d{2}-\d{2}T/; if (datePattern.test(value)) { return new Date(value); } } return value; } const savedData = JSON.parse(localStorage.getItem("event"), dateReviver); console.log(savedData.createdAt instanceof Date); // true </syntaxhighlight> <br><br> == storageイベント == ==== 他タブとの同期 ==== <code>storage</code> イベントは、同じオリジンを共有する別のタブ・ウィンドウで <u>localStorage</u> に変更が加えられた場合に発生する。<br> <br> <u>変更を行ったタブ・ウィンドウ自身ではイベントは発生しないことに注意が必要である。</u><br> <br> <u>sessionStorage</u> の変更は他のタブと共有されないため、<code>storage</code> イベントは発生しない。<br> <br> 下表に、<code>StorageEvent</code> オブジェクトのプロパティを示す。<br> <br> <center> {| class="wikitable" |+ StorageEventオブジェクトのプロパティ ! プロパティ !! 説明 |- | <code>key</code> || 変更されたキー名<br><code>clear()</code> が呼び出された場合は <u>null</u> になる。 |- | <code>oldValue</code> || 変更前の値<br>新規追加の場合は <u>null</u> になる。 |- | <code>newValue</code> || 変更後の値<br>削除の場合は <u>null</u> になる。 |- | <code>url</code> || ストレージ変更を引き起こしたドキュメントのURL |- | <code>storageArea</code> || 変更が加えられた <code>Storage</code> オブジェクト<br>(<u>localStorage</u> または <u>sessionStorage</u>) |} </center> <br> <syntaxhighlight lang="javascript"> // 他のタブからのlocalStorage変更を検知する window.addEventListener("storage", (event) => { console.log("変更されたキー:", event.key); console.log("前の値:", event.oldValue); console.log("新しい値:", event.newValue); console.log("変更元URL:", event.url); if (event.key === "theme") { // テーマが変更されたときの処理 applyTheme(event.newValue); } }); </syntaxhighlight> <br> この仕組みを利用することにより、複数タブ間でユーザ設定やログイン状態等を同期させることができる。<br> <br><br> == 他のストレージ手段との比較 == ==== Cookie / IndexedDB / Web Storage の比較テーブル ==== 主なクライアント側のストレージ手段の比較を以下に示す。<br> <br> <center> {| class="wikitable" |+ クライアントサイドストレージ比較 ! 項目 !! Web Storage (localStorage / sessionStorage) !! Cookie !! IndexedDB |- | 容量 || 5〜10[MB] || 4[KB] || 10[GB]以上 |- | データ型 || 文字列のみ || 文字列のみ || オブジェクト・Blob等多様 |- | API型 || 同期 || 同期 || 非同期 |- | サーバへの自動送信 || しない || 全てのHTTPリクエストで自動送信 || しない |- | インデックス・クエリ || 不可 || 不可 || 可能 |- | JavaScript以外のアクセス || 不可 || サーバ側からもアクセス可能 || 不可 |- | 有効期限設定 || 手動削除が必要 || Expires / Max-Age属性で設定可能 || 手動削除が必要 |- | HttpOnlyによるJSアクセス防止 || 不可 || 可能 || 不可 |- | 学習難度 || 低い || 低〜中 || 高い |- | 主な用途 || 設定・状態の簡易保存 || 認証・セッション管理 || 大容量データ・複雑なクエリ |} </center> <br> ==== Tauriアプリでの永続化手段 ==== Tauriアプリケーションでは、WebViewの内部で動作するWeb Storageの他に、ネイティブ側のファイルシステムやデータベースを利用した永続化手段が提供されている。<br> <br> <center> {| class="wikitable" |+ Tauriアプリにおけるストレージ手段の比較 ! 項目 !! Web Storage !! tauri-plugin-store !! tauri-plugin-sql |- | ストレージ方式 || WebView内部 (文字列) || ファイルシステム (JSON) || データベース (SQL) |- | 容量制限 || 3〜5[MB] || 制限なし || 制限なし |- | API型 || 同期 || 非同期 || 非同期 |- | Rustからのアクセス || 不可 || 可能 || 可能 |- | データ型 || 文字列のみ || 多様 (JSON対応) || 多様 (SQL型) |- | 主な用途 || 一時的なUI状態 || アプリ設定・ユーザデータ || リレーショナルデータ |} </center> <br> <u>tauri-plugin-store</u> は、アプリ設定やユーザデータをファイルシステム上のJSONファイルに永続化するためのプラグインである。<br> Web Storageと比較して容量制限がなく、Rust側からもアクセスできる点が特徴である。<br> <br> <syntaxhighlight lang="javascript"> import { Store } from "@tauri-apps/plugin-store"; const store = new Store(".settings.json"); // データの保存 await store.set("apiKey", "secret-key-value"); // データの取得 const apiKey = await store.get("apiKey"); console.log(apiKey); // "secret-key-value" </syntaxhighlight> <br> アプリ設定や機密性のないユーザデータの永続化には、<u>tauri-plugin-store</u> が適している。<br> Web Storageは一時的なUI状態の保持やRust側からのアクセスが不要な軽量なデータの保存に向いている。<br> <br><br> == セキュリティ上の注意事項 == <code>localStorage</code> と <code>sessionStorage</code> はJavaScriptから完全にアクセス可能であるため、<br> XSS (クロスサイトスクリプティング) 攻撃によって悪意あるスクリプトが格納データを読み取る可能性がある。<br> <br> HTTP-only Cookieとは異なり、Web StorageにはJavaScriptベースの攻撃に対する組み込み保護機能がない。<br> <br> 以下の情報はWeb Storageに格納してはならない。<br> <br> * 認証トークン (JWT、セッションID) * APIキーやシークレット * パスワード * 個人識別情報 (PII) * 支払い情報 <br> 認証トークンはWeb Storageではなく、HTTP-only Cookieで管理することを推奨する。<br> <br> セキュリティを向上させるために推奨される対策を以下に示す。<br> <br> * HTTP-only Cookieの使用 *: セッション認証トークンの保管にはHTTP-only Cookieを使用する。 *: JavaScriptからアクセスできないためXSSによる漏洩を防げる。 *: <br> * CSP (コンテンツセキュリティポリシー) の設定 *: 厳密なCSPを設定することで、不正なスクリプトの実行を防止する。 *: <br> * ログアウト時のストレージクリア *: ユーザがログアウトした時に <code>localStorage.clear()</code> を呼び出し、残存データを削除する。 *: <br> * HTTPSの使用 *: 通信の暗号化により、中間者攻撃によるデータ盗取を防止する。 *: <br> * サーバ側での入力検証・出力エスケープ *: XSSの根本的な原因となるスクリプトインジェクションをサーバ側で防止する。 <br><br> == 関連情報 == * [https://html.spec.whatwg.org/multipage/webstorage.html WHATWG HTML Living Standard - Web Storage] * [https://developer.mozilla.org/ja/docs/Web/API/Web_Storage_API MDN Web Docs - Web Storage API] * [https://developer.mozilla.org/ja/docs/Web/API/Window/localStorage MDN Web Docs - Window.localStorage] * [https://developer.mozilla.org/ja/docs/Web/API/Window/sessionStorage MDN Web Docs - Window.sessionStorage] * [https://developer.mozilla.org/ja/docs/Web/API/StorageEvent MDN Web Docs - StorageEvent] * [https://v2.tauri.app/plugin/store/ Tauri - tauri-plugin-store] <br><br> {{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux |image=/resources/assets/MochiuLogo_Single_Blue.png }} __FORCETOC__ [[カテゴリ:Web]]
JavaScriptの基礎 - Web Storage
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse