Rails 6 to 7 upgrade with esbuild/sprockets - webfonts not found in development

Hi Im almost at the goal line with my upgrade. Im have been dealing with dynamic reload on js/css changes and it is causing some issues.

As part of the upgrade i have gone with jsbundling (esbuild )and cssbundling (bootstrap).

I think that a part of my issue is that I don’t fully understand what esbuild/sprockets start and stop.

In order to get hot reloading to work i found that i had to run assets:clobber as i had issues with rails reading the digest versions of application.js and stylesheet.css from public/assets. After having cleaned out public/assets dynamic reloading seems to work. I don’t fully understand why.

The issue is now that i get following errors in my chrome console:

GET http://localhost:3000/webfonts/fa-solid-900.woff2 404 (Not Found)
application-4dcb73f3da433d833f26d81dbcf900551080dd96edea864ecb90f8100963eae5.css:1          GET http://localhost:3000/webfonts/fa-solid-900.woff 404 (Not Found)
application-4dcb73f3da433d833f26d81dbcf900551080dd96edea864ecb90f8100963eae5.css:1          GET http://localhost:3000/webfonts/fa-solid-900.ttf net::ERR_ABORTED 404 (Not Found)

and in rails log (only one of them is shown here):

web_1  | 18:53:02 web.1  | I, [2022-09-26T18:53:02.849005 #40]  INFO -- : Started GET "/webfonts/fa-solid-900.ttf" for 172.25.0.1 at 2022-09-26 18:53:02 +0000
web_1  | 18:53:02 web.1  | I, [2022-09-26T18:53:02.849949 #40]  INFO -- : Cannot render console from 172.25.0.1! Allowed networks: 127.0.0.0/127.255.255.255, ::1
web_1  | 18:53:02 web.1  | F, [2022-09-26T18:53:02.857123 #40] FATAL -- :   
web_1  | 18:53:02 web.1  | ActionController::RoutingError (No route matches [GET] "/webfonts/fa-solid-900.ttf"):

This is fairly obvious as I just cleared out public/assets

Now if i run assets:precompile then public/assets is rebuild and after an application restart I still get the error:

web_1  | 19:06:46 web.1  | I, [2022-09-26T19:06:46.913294 #40]  INFO -- : Started GET "/webfonts/fa-solid-900.ttf" for 172.25.0.1 at 2022-09-26 19:06:46 +0000
web_1  | 19:06:46 web.1  | I, [2022-09-26T19:06:46.914006 #40]  INFO -- : Cannot render console from 172.25.0.1! Allowed networks: 127.0.0.0/127.255.255.255, ::1
web_1  | 19:06:46 web.1  | F, [2022-09-26T19:06:46.922051 #40] FATAL -- :   
web_1  | 19:06:46 web.1  | ActionController::RoutingError (No route matches [GET] "/webfonts/fa-solid-900.ttf"):

and just to really set my self back to square zero hot reloading is not working. The assets/builds gest a application.js (with sourcemap) but development now uses the public/assets digest version. Thus I run run assets:clobber once more, but the is very circular.

Does anyone have any idea how to get me out of this bind?

Thanks Jens

My esbuild.config:

// yarn build
// yarn build --watch
// yarn build --reload

const esbuild = require("esbuild")
const path = require("path")
const rails = require("esbuild-rails")

const clients = []
const entryPoints = [
    "application.js"
]

const watchDirectories = [
    "./app/assets/builds/**/*.css", // Wait for cssbundling changes
    "./app/javascript/**/*",
    "./app/views/**/*"
]

const config = {
    absWorkingDir: path.join(process.cwd(), "app/javascript"),
    bundle: true,
    entryPoints: entryPoints,
    outdir: path.join(process.cwd(), "app/assets/builds"),
    plugins: [rails()],
    sourcemap: process.env.RAILS_ENV != "production"
}

async function buildAndReload() {
    const chokidar = require("chokidar")
    const http = require("http")

    http.createServer((req, res) => {
        return clients.push(
            res.writeHead(200, {
                "Content-Type": "text/event-stream",
                "Cache-Control": "no-cache",
                "Access-Control-Allow-Origin": "*",
                "Connection": "keep-alive"
            })
        )
    }).listen(8082)

    let result = await esbuild.build({
        ...config,
        incremental: true,
        banner: {
            js: '(() => new EventSource("http://localhost:8082").onmessage = () => location.reload())();'
        }
    })

    chokidar.watch(watchDirectories).on('all', (event, path) => {
        if (path.includes("javascript")) {
            result.rebuild()
        }

        clients.forEach((res) => res.write("data: update\n\n"))
        clients.length = 0
    })
}

if (process.argv.includes("--reload")) {
    buildAndReload()

} else {
    const watch = process.argv.includes("--watch") && {
        onRebuild(error) {
            if (error) console.error("[watch] build failed", error)
            else console.log("[watch] build finished")
        }
    }
    esbuild.build({
        ...config,
        watch: watch,
        minify: process.env.RAILS_ENV == "production"
    }).catch(() => process.exit(1))
}

and for my development environment i have:

  # Debug mode disables concatenation and preprocessing of assets.
  # This option may cause significant delays in view rendering with a large
  # number of complex assets.
  config.assets.debug = false

  #To get assets to work in dev
  config.assets.compile = true

  # Suppress logger output for asset requests.
  config.assets.quiet = true