How I work with static assets in React apps

Most people when working with tools like webpack tend to add loaders like image-loader combined with optimizers to store the raw high quality assets in their repo and let the bundles optimize them at build time.

However once your app starts to grow this becomes way slower, and ask you this, why optimize your assets on every build/deploy when you can do it once and forget about it?

This is why, what I usually do is to optimize them only one time.

If I have an SVG instead of using a Babel loader to convert it to a React component on build-time I use transform.tools to do it once and store it as a React component.

If I have an image I pass it through TinyPNG and get it with a huge size reduction, I also try to don't user images bigger than needed or I use srcset to load the specific size I need based on the user screen.

Then, after I have everything ready I let Rails serve the assets using their asset pipeline, Rails will automatically add a hash to make the URL unique and help improve the cache.

Send hashed URLs to React

Since Rails hash the URLs automatically for me I can’t just use /assets/logo.png because that is not the real URLs.

What I do to be able to reference the correct URL client-side is to pass them from Rails to React. The key here is that static assets are exactly that, static, you can always know which assets you will need because they don’t change dynamically as assets whose URL you store in a DB.

To pass them from Rails to React I create script tag with the type application/json and and ID (usually initial-props), similar to this one:

<script type="application/json" id="initial-props">
  {
    "assets": {
      "logo": "<%= asset_path("images/logo.png") %>"
    }
  }
</script>

Then, before rendering the React application I read this JSON, store in an AssetContext I create and when I need a URL I use a custom Hook useAsset to ask for the asset name (e.g. useAsset("logo”)) and this returns me the asset URL.