Our company uses sessionStorage all over the place. These are basically all globals. I guess each git repo should have it’s own namespace, but, we really should just have one monorepo in the first place.
We had some bug that called for going deep down a rabbit hole. For some reason a
sessionStorage.apitoken was undefined/null. Sidenote: at a previous very large company, there was an errily similar issue, instead of sessionStorage it was a cookie. In personal projects and even new, isolated projects, you can simply read and write to sessionStorage and document.cookie directly without repercussions. Sure document.cookie api is so rough that any sane developer would use a wrapper library (like js/cookie) but they might also just write their own/copy paste something from somewhere, so they aren’t directly reading the raw
document.cookie or directly assigning to it
document.cookie = 'foo...'.
These storage bits are ‘super global’ in the sense that they are global across multiple page loads. Normal globals are difficult, but not quite as difficult as data stored client side. They tend to get written to+read from more often.
At least having a wrapper would be a good start. This was an interesting read: How do I deal with global variables in existing legacy code (or, what’s better, global hell or pattern hell)?
It seems like a registry would be a good idea.
One idea I just got was having a tiny node module/git repo, which holds typescript defs for these globals. All the sessionStorage keys that anyone could used would be enumerated (in some way) in the typescript definitions. If you want to introduce a new global, you need to make a tiny pr to this typescript def.
This provides a central location for managing globals. The tiny typescript def repo should probably also include wrapper libraries for these.
I think before you can read/write any globals you’ll need to create an “instance” of the registry by passing in your name, so the registry knows who you are, to make things easier to debug/track down who should change their code. It could be useful to actually create a new instance of the registry, to keep things 100% isolated, but the whole point here is to help manage globals. Maybe it should include some utilities/methods which allow you to read/write from your own “private” namespace, but it feels like a bit of a “v2” at this point. (or maybe just before stamping it as “v1” if it were an open source library)
I think, jsCookie is the best library for managing cookies: https://github.com/js-cookie/js-cookie
But, we also need a wrapper for sessionStorage+localStorage. Feels like it should be asynchronous, but hard to say.. I think some projects may have no issues with storage limits for session/localStorage.
I think, you need a mechanism to “listen” to new values, based on my experience at a previous company. (Like, for your “preferred store” location for a retail company).
I think the “global manager” library should probably be the only code that is allowed to read/write from client side storage (cookies/sessionStorage/localStorage). Crucially, review of this code will have to consider how previous client side data would be migrated when changes to the keys/storage format might change. I’m not sure what the exported functions of this library would be exactly, but the smaller the better, I think. It might be useful to consider how the code would handle going over cookie storage limits. Of course, reviewers would also need to think about client side storage limits. This might be where httpOnly cookies need to come into consideration, I’m not sure exactly how they might contribute to cookie storage limit. In some way this “global manager” repo needs to have checks for possibly exceeding storage limit, and all key/value pairs (esp. cookies) would need to include some definition of how many bytes will be stored in that key.
Options for this check:
-Easiest would be a normal runtime check, would also be the most accurate, but worst performance. The runtime checks could be made to run only if
NODE_ENV!=='production', either only in development, or only in testing.
-Compile time check would be best performance, but I’m not sure how that would be implemented. Might require some special tooling.
Theoretically a compile time check could be as accurate as the runtime check when it counts. If there’s an error with exceeding the storage limit, then some how a flag would be set.. I suppose in the url.. this flag would cause the runtime checking code to be loaded in the future for X days until there are no more storage errors… In addition, when an error occurs, the current state of the storage mechanism could be cached, if writing to storage fails, the whole state is cached, so we know the state before+after the storage exception.
Some cookie defs could include code for itself if deleted… along with some indication that it is recoverable… and possibly other values that are needed to recover it (although that seems like bit overboard, probably time to fix the problem upstream).
- On second thought, if cookie/sessionStorage/localStorage value is recoverable, it might be better to just consider it a cached value. In this sense, the “global storage manager” could have code that lets the cache be cleared if the storage limit is being hit (or simply uses a different storage mechanism – i.e. switch a key/value from being stored as a cookie to being stored in sessionStorage (which has a higher storage limit).
Pardon the fact that this is not well written at this point. There’s just a lot of complexity and ideas and only so much time in the day.