The emergence of Web Storage in HTML5 is mainly to make up for the use of cookies as local Storage. Cookies store a very small amount of data, and the data is automatically carried to the request header, but the server may not care about the data, resulting in a waste of bandwidth.

Web Storage provides two Storage objects: localStorage and sessionStorage.

The data stored in sessionStorage is only available for the current session and will be automatically invalid after the session ends. In addition, the data is only available for the current window. New Windows in the same source cannot access the data stored in other Windows based on sessionStorage. Because of these features, sessionStorage is used in fewer scenarios.

LocalStorage can be permanently stored, and the same source of data can be shared in multiple Windows. It looks great, but localStorage has a downside. Most browsers have a 5M size limit. But this is not enough to become a barrier to the use of localStorage, to know that cookies are only 4K in size, more than a thousand times, stealing joy.

Basic use of localStorage

There are so many articles on the Internet about this topic that it’s a little old-fashioned to talk about it now. I don’t want to do more here, but if you don’t know, you can look here.

There are two things to note. In setItem, the size limit may be reached and it is best to add error capture 1:

try {  
  localStorage.setItem(key, value);
} catch(e) {
  if (isQuotaExceeded(e)) {
    // Storage full, maybe notify user or do some clean-up
  }
}

function isQuotaExceeded(e) {  
  var quotaExceeded = false;
  if (e) {
    if (e.code) {
      switch (e.code) {
        case 22:
          quotaExceeded = true;
          break;
        case 1014:
          // Firefox
          if (e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
            quotaExceeded = true;
          }
          break;
      }
    } else if (e.number === -2147024882) {
      // Internet Explorer 8
      quotaExceeded = true;
    }
  }
  return quotaExceeded;
}
Copy the code

In addition, when the storage capacity is nearly full, the performance of getItem deteriorates sharply 2.

Let’s look at some imaginative uses of localStorage.

Cache static files

You can’t help but wonder why localStorage is used when the HTTP protocol already supports caching files (the HTTP Guide to Web Caching). In order to be programmable, the popular point is to hold the fate in their own hands.

The HTTP cache can be cleared or disabled by the user’s browser, or set to expire or not cached by the Web server. To the front-end engineer, this is more like a black box, and it’s hard to decide whether a file should be cached or accessed remotely.

There are two ways to use localStorage to control file caching:

  1. Use Loader to load static files
  2. Inline static files with the help of the server side

In both cases, cache expiration policies are usually set in advance, usually controlled by version numbers, as discussed below. Otherwise, the new version of the file online, the user client or the old version, which is a big trouble, and this kind of problem, but also bad debugging bad recurrence.

Use Loader to load static files

Because requests are made dynamically, they can be intercepted and processed. The general process is as follows:

  1. Check whether the requested file URL is cached to localStorage

    1. If not, go to step 2
    2. If yes, check whether the file is expired or the version number matches
      1. Expired or do not match, go to step 2
      2. File contents are valid. Step 4
  2. Requesting remote files
  3. Caches the latest file contents
  4. Execution file contents

There is an open source library for this approach: basket.js.

Inline static files with the help of the server side

This approach goes a step further by inlining all the files that need to be placed in localStorage into HTML for the first response, and rendering a piece of code that loads the file from localStorage for each subsequent response as long as the version of the file has not changed. The advantage of this is that it can effectively reduce the number of requests, even for the first time.

The version number does not match (the version number can be recorded in the Cookie, the first access does not have the version number), and the server responds:

<script> function script2ls(id) { var script = document.getElementById(id); if (script) { localStorage[id] = script.innerHTML; } } </script> <script id="jquery.js">... jquery source code... </script> <script>script2ls('jquery.js')</script>Copy the code

The version number matches, and the server responds:

<script>  
function ls2script(id) {  
  var script = document.createElement('script');
  script.text = localStorage[id];
  document.head.appendChild(script);
}
</script>

<script>ls2script('jquery.js')</script>  
Copy the code

However, using localStorage to cache files carries XSS risks, and the damage can be permanent 3.

Homologous window communication

You might ask again, isn’t there postMessage? Yes, postMessage can be used to communicate between Windows or iframes, but only if you get the handle object to open a new window or iframe:

var popup = window.open(... popup details...) ; popup.postMessage("hello there!" , "http://example.com");Copy the code

So opening a new window in a new window doesn’t seem like a good way to send messages.

You might also ask, why communicate between Windows? Good question. Any technology without a scenario is a rogue. Applications such as components shared by multiple Windows and high requirements for real-time data synchronization will be the application scenarios of this technology. For example, the number of unread messages on the notification center, two Windows, window A updated to 8, cut to window B is still 9, which causes inconsistent experience, this example may still feel insignificant; Another example is the shopping cart. There are two product Windows. Window A is added to the shopping cart, and window B is cut to add to the shopping cart. This could of course be updated by connecting each window to the background, but it would be expensive for users to have more than a dozen Windows open.

With homologous window communication, we can have only one window to establish a connection with the background, receive updates, broadcast to other Windows can be. Having said that, how does the implementation work?

In fact, the principle is also simple, every time there is any change in localStorage will trigger a storage event, all Windows are listening to this event, once there is a window to update localStorage, other Windows will receive notification, according to the key in the event does not care about the change filter out. The principle is simple, but implementing a complete broadcast mechanism is a bit more complicated. You need to:

  • Manage unique ids for each window
  • Preventing message duplication
  • Prevent messages from being sent to unconcerned Windows
  • Window heartbeat keep alive
  • Main window election
  • .

Don’t worry, there are already good open source implementations: DIY/Intercom.js, Tejacques/Crosstab

other

Serves as the storage medium of the front-end DB

You may want to save more complex data structures than key-value pairs.

Flexible access to JSON-formatted data: Typicode /lowdb

SQL to manipulate data CURD: agershun/ alASQL

Forms persist automatically

When filling out a form, the browser crashes or misoperations cause the content to be lost, and the user’s heart should be broken at the moment. Misoperations can also be added with a beforeUnload event to alert the user before closing the browser or jumping out of the current page. It seems to be expensive to save changes to localStorage in real time. Luckily, there is also an open source implementation: Simsalabim/Sisyphus

conclusion

File caching now has a better solution, that’s right, to the Service Worker’s CacheStorage.

However, being aware of some imaginative ideas can help broaden your approach to problem solving.

Enjoy the open source ❤ ️

1: Always catch LocalStorage security and quota exceeded errors 2: Measuring LocalStorage Performance 3: Use SRI to enhance localStorage code security