{"componentChunkName":"component---src-templates-blog-post-js","path":"/you-will-stop-using-localstorage/","webpackCompilationHash":"da658d138a5c02dfedf3","result":{"data":{"site":{"siteMetadata":{"title":"八王子わんにゃんクラブ","author":"technology unit of JOHAQ.COM.","siteUrl":"https://svc-802-wannyan-club.johaq.com","keywords":["八王子わんにゃんクラブ"],"disqusShortname":"johaq-com"}},"markdownRemark":{"id":"86fe2fee-e055-58f6-aea2-b2bc6d1b1b83","excerpt":"When LocalStorage first appeared as part of HTML5 specification, web developers were excited because it exposed a simple way to save and retrieve data in and…","timeToRead":3,"html":"<p>When <a href=\"https://html.spec.whatwg.org/multipage/webstorage.html#the-localstorage-attribute\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">LocalStorage</a> first appeared as part of HTML5 specification, web developers were excited because it exposed a simple way to save and retrieve data in and from the user’s browser.</p>\n<p>In this post, we will have a look at a new WICG proposal that aims to be a more performant alternative to LocalStorage.</p>\n<blockquote>\n<p>This blog post talks about a <em>potential</em> future web platform feature called “KV Storage” (short for “Key-Value Storage”). This is currently a <strong>proposal</strong> made by the Web Incubator Community Group and it should <strong>not</strong> be used in production environments.</p>\n</blockquote>\n<h2 id=\"the-localstorage-interface\"><a href=\"#the-localstorage-interface\" aria-label=\"the localstorage interface permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The LocalStorage Interface</h2>\n<p>The LocalStorage interface allows the developer to store data in the browser in the form of key-value pairs, where both the key and the value are strings. The data is persisted across browser sessions and its scope is limited to the origin where the script that accesses LocalStorage resides.</p>\n<h3 id=\"api\"><a href=\"#api\" aria-label=\"api permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>API</h3>\n<h4 id=\"saving-data\"><a href=\"#saving-data\" aria-label=\"saving data permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Saving Data</h4>\n<p>To save data to LocalStorage, simply call the <code>setItem(key, value)</code> method exposed by the <code>window.localStorage</code> object:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-javascript line-numbers\"><code class=\"language-javascript\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token string\">'localStorage'</span> <span class=\"token keyword\">in</span> window<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  localStorage<span class=\"token punctuation\">.</span><span class=\"token function\">setItem</span><span class=\"token punctuation\">(</span><span class=\"token string\">'theme'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'dark'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div>\n<p>If the data you are going to save is not a string, you have to serialize it before saving it:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-javascript line-numbers\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> serializedData <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span>myData<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nlocalStorage<span class=\"token punctuation\">.</span><span class=\"token function\">setItem</span><span class=\"token punctuation\">(</span><span class=\"token string\">'data'</span><span class=\"token punctuation\">,</span> serializedData<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span></span></pre></div>\n<h4 id=\"retrieving-data\"><a href=\"#retrieving-data\" aria-label=\"retrieving data permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Retrieving Data</h4>\n<p>To retrieve data, call the <code>getItem(key)</code> method exposed by <code>window.localStorage</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-javascript line-numbers\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> savedTheme<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token string\">'localStorage'</span> <span class=\"token keyword\">in</span> window<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  savedTheme <span class=\"token operator\">=</span> localStorage<span class=\"token punctuation\">.</span><span class=\"token function\">getItem</span><span class=\"token punctuation\">(</span><span class=\"token string\">'theme'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>Following the previous code snippet, <code>savedTheme</code> should hold the value <code>\"dark\"</code>.</p>\n<p>Again, if the value you stored was not originally a string, you have to deserialize it:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-javascript line-numbers\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> serializedData <span class=\"token operator\">=</span> localStorage<span class=\"token punctuation\">.</span><span class=\"token function\">getItem</span><span class=\"token punctuation\">(</span><span class=\"token string\">'data'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> myData <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span>serializedData<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span></span></pre></div>\n<h3 id=\"cons-of-localstorage\"><a href=\"#cons-of-localstorage\" aria-label=\"cons of localstorage permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Cons of LocalStorage</h3>\n<p>As we have seen, the LocalStorage API is very simple, but a few non-negligible drawbacks are present:</p>\n<ul>\n<li>Only strings can be saved; to handle with non-string data, we have to manually perform serialization and deserialization</li>\n<li><code>getItem</code> and <code>setItem</code> are synchronous: calling them blocks the main thread, and this potentially prevents the page from being interactive</li>\n</ul>\n<p>The only asynchronous alternative to LocalStorage currently available is IndexedDB, which is definitely not known for its ease of use.</p>\n<h2 id=\"the-kv-storage-proposal\"><a href=\"#the-kv-storage-proposal\" aria-label=\"the kv storage proposal permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The KV Storage Proposal</h2>\n<p>Key-Value Storage is a <a href=\"https://wicg.github.io/kv-storage/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">proposal</a> made by the Web Incubator Community Group (WICG) that aims to address the drawbacks of LocalStorage we have just mentioned. The specification mandates that it gets implemented by browser vendors as a built-in module and that it uses <a href=\"https://www.w3.org/TR/IndexedDB/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">IndexedDB</a> as its backing store.</p>\n<p>Let’s see an example usage of the KV Storage API, as provided by the specification:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-javascript line-numbers\"><code class=\"language-javascript\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> storage <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'std:kv-storage'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">await</span> storage<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mycat'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Tom'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  console<span class=\"token punctuation\">.</span><span class=\"token function\">assert</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">await</span> storage<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mycat'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> <span class=\"token string\">'Tom'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">for</span> <span class=\"token keyword\">await</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>key<span class=\"token punctuation\">,</span> value<span class=\"token punctuation\">]</span> <span class=\"token keyword\">of</span> storage<span class=\"token punctuation\">.</span><span class=\"token function\">entries</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">,</span> value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">await</span> storage<span class=\"token punctuation\">.</span><span class=\"token function\">delete</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mycat'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  console<span class=\"token punctuation\">.</span><span class=\"token function\">assert</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">await</span> storage<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mycat'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> <span class=\"token keyword\">undefined</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>As we can see, <code>set</code> and <code>get</code> APIs are the equivalent for LocalStorage’s <code>setItem</code> and <code>getItem</code>, but they are <em>asynchronous</em>. This means that the main JS thread is not blocked while the data is being fetched or persisted <span role=\"img\" aria-labelledby=\"smiling face with open mouth & smiling eyes\">😄</span></p>\n<h3 id=\"try-kv-storage-today\"><a href=\"#try-kv-storage-today\" aria-label=\"try kv storage today permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Try KV Storage Today</h3>\n<p>If you are curious to experiment today with KV Storage, you have two possibilities:</p>\n<ul>\n<li>Use this <a href=\"https://github.com/GoogleChromeLabs/kv-storage-polyfill\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">KV Storage polyfill</a></li>\n<li>Install Chrome 74+ and enable this feature for specific web domains by registering interest in the <a href=\"https://developers.chrome.com/origintrials/#/trials/active\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">KV Storage origin trial</a></li>\n</ul>\n<p>As you guess, the only web engine currently supporting KV Storage is Chromium from version 74. All web browsers based on Chromium v74+ (such as Google Chrome, Opera and Edge Dev) inherits this feature.</p>","fields":{"slug":"/you-will-stop-using-localstorage/"},"frontmatter":{"title":"You Will Stop Using LocalStorage","date":"April 25, 2019","published_time":"2019-04-25","description":"Goodbye LocalStorage, welcome Key-Value Storage!","tags":["javascript","js","storage","localstorage","local storage","kv storage","key-value storage","key-value","key","value","kv","google","chrome","wicg"],"cover":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQCAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABofzmoVIi/wD/xAAbEAABBAMAAAAAAAAAAAAAAAABAAIREgMhQv/aAAgBAQABBQLt8p7NkQMhsjZf/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGhAAAgIDAAAAAAAAAAAAAAAAAAERMSEyYf/aAAgBAQAGPwKFgUX0tidsRsf/xAAcEAADAAIDAQAAAAAAAAAAAAAAARExYUFRobH/2gAIAQEAAT8hxVGYIkLoLI25tdzktLoWX4YvpbP/2gAMAwEAAgADAAAAELwv/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oACAEDAQE/EEx//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGhABAQADAQEAAAAAAAAAAAAAAREAITFhQf/aAAgBAQABPxDaT8CPcbgpqiHsO9xtn4Vjo0Gg1lhIFXm8UNCcVJlbpEZuTb7n/9k=","aspectRatio":2.3333333333333335,"src":"/static/0f78175f44d00cc5c51d2fefa969f5f9/acf46/cover.jpg","srcSet":"/static/0f78175f44d00cc5c51d2fefa969f5f9/74a6a/cover.jpg 350w,\n/static/0f78175f44d00cc5c51d2fefa969f5f9/047db/cover.jpg 700w,\n/static/0f78175f44d00cc5c51d2fefa969f5f9/acf46/cover.jpg 1400w,\n/static/0f78175f44d00cc5c51d2fefa969f5f9/dcb90/cover.jpg 1600w","srcWebp":"/static/0f78175f44d00cc5c51d2fefa969f5f9/e6b98/cover.webp","srcSetWebp":"/static/0f78175f44d00cc5c51d2fefa969f5f9/e5785/cover.webp 350w,\n/static/0f78175f44d00cc5c51d2fefa969f5f9/1b440/cover.webp 700w,\n/static/0f78175f44d00cc5c51d2fefa969f5f9/e6b98/cover.webp 1400w,\n/static/0f78175f44d00cc5c51d2fefa969f5f9/702cd/cover.webp 1600w","sizes":"(max-width: 1400px) 100vw, 1400px","presentationWidth":1400,"originalImg":"/static/0f78175f44d00cc5c51d2fefa969f5f9/dcb90/cover.jpg"}}}}}},"pageContext":{"isCreatedByStatefulCreatePages":false,"slug":"/you-will-stop-using-localstorage/","previous":{"fields":{"slug":"/conditional-rendering-in-react/"},"frontmatter":{"title":"Conditional Rendering In React"}},"next":{"fields":{"slug":"/2019-08-22-gridsome/"},"frontmatter":{"title":"Introduction to Gridsome"}}}}}