Rails 7, React & Esbuild - Static assets not served in production

Viewed 39

I have created a simple new Rails 7 project from scratch with Esbuild and React to get to know these, and they indeed feel like a step up from Webpack, except I can't manage to have my static files (ie image) served in production.

I have an Esbuild config file:

// esbuild.config.js

const path = require('path');

require("esbuild").build({
  entryPoints: ["application.jsx"],
  bundle: true,
  outdir: path.join(process.cwd(), "app/assets/builds"),
  absWorkingDir: path.join(process.cwd(), "app/javascript"),
  publicPath: "assets",
  sourcemap: true,
  watch: process.argv.includes('--watch'),
  plugins: [],
  loader: {
    '.js': 'jsx',
    '.jpg': 'file',
    '.png': 'file',
    '.MOV': 'file'
  },
}).catch(() => process.exit(1));

I store my images in the app/javascript/images/ folder, and import and use them in a React component like that (for example):

import MyImage from "./images/myimage.jpg"
import styled from "styled-components";
//...

const SomeStyledComponent = styled.div`
    background-image: url(${MyImage});    
`

In development, everything works fine, Esbuild copies the images in the app/assets/builds/ folder, fingerprints them, and prepends all the images url with the publicPath property of my Esbuild config. The above image for example then has the relative url assets/myimage-FINGERPRINT.jpg which is served correctly in development.

Then things get complicated in production (production here being just a Docker container built for production - I don't add the Dockerfile to keep things simple as I don't think it would help, but happy to provide it of course).

In my production.rb I have added the following:

config.public_file_server.enabled = true

(which will be replaced by an environment variable later)

The assets precompiling succeeds, and my images are in the app/public/assets/ folder, fingerprinted once more by Sprockets this time (from what I understand), but now I get 404. I have tried changing Esbuild publicPath and have tried to get the images directly in my browser, but whatever I try (assets, public, public/assets), nothing work and I am running out of ideas.

I have temporary fix which is to change the loader for images to dataurl, but that does not feel like a good practice, as my compiled javascript is going to explode.

Thank you for your help!

0 Answers
Related