Deno 1.16 localStorage ハンズオン
Deno 1.16にてlocalStorage APIの更新が入りました。
上記記事でも書いていますが、--location
オプションがなくてもエラーなくlocalStorageを使用できるようになりました。
従来通り--location
をつけることでバケットのキーを直接指定できますが、この指定がない場合はメインモジュール(エントリーポイント)のパスがキーとして使われます。
本記事では1.16のリリースノートに沿って、これを試してみます。
基本の読み書き
以下のようなファイルを用意します。
console.log(localStorage.getItem("file"));
localStorage.setItem("file", Deno.mainModule);
Deno 1.15.xまではこれをそのまま実行するとエラーになっていました。
❯ deno --version
deno 1.15.3 (release, aarch64-apple-darwin)
v8 9.5.172.19
typescript 4.4.2
❯ deno run one.js
error: Uncaught ReferenceError: Access to "location", run again with --location <href>.
console.log(localStorage.getItem("file"));
^
at get (deno:ext/web/12_location.js:381:17)
at createStorage (deno:ext/webstorage/01_webstorage.js:94:28)
at localStorage (deno:ext/webstorage/01_webstorage.js:179:24)
at file:///Users/kawarimidoll/one.js:1:13
Deno 1.16.x以降はエラーなく実行できるようになっています。
※ Deno.mainModule
へのアクセスには--allow-read
権限が必要です
❯ deno --version
deno 1.16.1 (release, aarch64-apple-darwin)
v8 9.7.106.2
typescript 4.4.2
❯ deno run --allow-read one.js
null
❯ deno run --allow-read one.js
file:///Users/kawarimidoll/one.js
初回の実行ではストレージに何も保存されていないため、null
が表示されています。
その後Deno.mainModule
を保存しているので、2回目の実行ではそれが表示されています。
同ディレクトリの別ファイル
続いて同ディレクトリに同内容のファイルを用意します。
❯ cp ./one.js ./two.js
console.log(localStorage.getItem("file"));
localStorage.setItem("file", Deno.mainModule);
one.js
とtwo.js
で内容は同じですが、メインモジュール(エントリーポイントの絶対パス)が異なるため、参照するlocalStorageのバケットキーが異なります。
したがって、two.js
とone.js
の保存先は別であり、互いに関係しません。
❯ deno run --allow-read two.js
null
❯ deno run --allow-read two.js
file:///Users/kawarimidoll/two.js
two.js
からはone.js
で保存した内容が見えないことがわかります。
importしたファイル
前述のtwo.js
をインポートしてそのまま実行するthree.js
を作ってみました。 これはどうなるでしょうか。
import "./two.js";
localStorageのバケットのキーはあくまでメインモジュールに依存し、localStorage
APIを使用しているファイルではありません。 したがって、three.js
とtwo.js
の保存先も、やはり別になります。
❯ deno run --allow-read three.js
null
❯ deno run --allow-read three.js
file:///Users/kawarimidoll/three.js
もしこれがlocalStorage
APIを使用しているファイル(ここでいうとtwo.js
)に依存してしまうとどうなるでしょうか。例えばlocalStorage
をラップしたAPIを提供するモジュールがあった場合、そのモジュールを使用しているプログラム同士でバケットが共有されてしまうことになります。
これは望ましい挙動ではないので、エントリーポイントで区別されるというのは理にかなっていますね。
--config
オプションの使用
--config
オプションで設定ファイルを指定してdeno run
すると、その設定ファイルの絶対パスがバケットのキーとして使用されます。
ファイルは中身がなくても構いません(存在していないとエラーになります)。
{}
絶対パスがキーとして使われるということは、同じ設定ファイルを使っていれば、別々のプログラムでもバケットが共有されるということです。
以下のように、one.js
で保存した内容をtwo.js
から、逆にtwo.js
で保存した内容をone.js
から読めるようになります。
❯ deno run --allow-read --config=deno.jsonc one.js
null
❯ deno run --allow-read --config=deno.jsonc one.js
file:///Users/kawarimidoll/one.js
❯ deno run --allow-read --config=deno.jsonc two.js
file:///Users/kawarimidoll/one.js
❯ deno run --allow-read --config=deno.jsonc one.js
file:///Users/kawarimidoll/two.js
同一プロジェクト内のプログラムであれば、同じ設定ファイル・localStorage
バケットを共有したい可能性は高そうなので、この挙動は適切だと思います。
また、ここで初回のone.js
の実行でnull
が出力されていることからわかるように、先程のオプションを付けない実行で保存した内容は見えていません。
先程はone.js
のパスがキーになっていて、今回はdeno.jsonc
のパスがキーになっており、別々のバケットを見ているためです。
--location
オプションの使用
前のバージョンからあった方法です。--location
に渡したURLのオリジンがバケットのパスとして使われます。
--config
オプションの場合と同じく、別ファイル同士でバケットを共有していることがわかると思います。
❯ deno run --allow-read --location=http://example.com one.js
null
❯ deno run --allow-read --location=http://example.com one.js
file:///Users/kawarimidoll/one.js
❯ deno run --allow-read --location=http://example.com/page/1 two.js
file:///Users/kawarimidoll/one.js
❯ deno run --allow-read --location='http://example.com?query=ABC' one.js
file:///Users/kawarimidoll/two.js
❯ deno run --allow-read --location=http://example.com:80 two.js
file:///Users/kawarimidoll/one.js
オリジン部分がキーとして使われるので、上記のようにパスやクエリが入っていても同じバケットを共有します。
また、ポート80はHTTPのデフォルトポートなので、同一オリジンとなります。
以下は異なるオリジンなので、別バケットとなります。
❯ deno run --allow-read --location=https://example.com one.js
null
❯ deno run --allow-read --location=http://www.example.com one.js
null
❯ deno run --allow-read --location=http://example.com:8080 one.js
null
おわりに
以上、Deno 1.16から--location
不要になったlocalStorage
APIの簡単な説明でした。
オプションが不要になっただけで、けっこうカジュアルに使えるようになったのではないでしょうか。
基本的にはファイルごとに別々のlocalStorage
を使える、という理解で良いと思います。
なお、バケットのキーが暗黙で設定されるようになったというだけで、location.href
などの使用には--location
オプションが必要なのでご注意ください。
Discussion