Rebuilding ActiveStorage: First Impressions

Why?

ActiveStorage’s JS library is just fine…why rebuild it?

You’re not wrong. It works.

I enjoy rebuilding things, it also really helps me understand how these libraries work under the hood and helps me troubleshoot with others.

Initial Impressions

Shared Code

ActiveStorage’s JS package seems to reuse a lot of Rails-UJS functions but gets none of the benefits of sharing code. Even better, ActiveStorage could share with the package I created, mrujs .

Examples:

toArray is actually interesting because the ActiveStorage version polyfills to newer versions of creating arrays. This could be adopted into mrujs and shared.

Old ways of doing things

This line stuck out to me, rather than making an AJAX request, it creates a button on a form if it can’t find one and then manually clicks the element.

https://github.com/rails/rails/blob/099289b6360ac82d1e0fa0a5592ac10cfc05e6e0/activestorage/app/javascript/activestorage/ujs.js#L63-L77

In light of WebComponents, testing tag names feels weird…We can also grab submitters off of the “submit” event and both Turbo / mrujs ship with the polyfill for Safari.

mrujs submit polyfill

Turbo submit polyfill

MD5 Hashing

ActiveStorage uses the SparkMD5 library for MD5 hashing. I don’t know enough about the library to know if MD5 is necessary or if we could use SHA-x hashing or similar. SparkMD5 is roughly 2.5kb and ActiveStorage is ~5kb overall, which means MD5 hashing accounts for roughly half the library.

SparkMD5 bundle size

Where SparkMD5 is used

XmlHttpRequests

XmlHttpRequest example

Not surprised, but ActiveStorage uses XmlHttpRequests rather than the newer Fetch API for AJAX. This could be updated to use the FetchResponse and FetchRequest helpers exported by mrujs.

Closing Thoughts

At least it’s not CoffeeScript! It should be much easier to port to TypeScript and integrate with mrujs since its much more modern. There may be some incompatibilities around XmlHttpRequest and Fetch, but we shall have to see. Everything else looks fairly usable.