When I deploy, it succeeds without any error. When I run the fly logs, I can’t see any error. What could be causing that difference and causing the CSS not to load correctly?
+1 to everything @Stephen said. Following from that, I noticed in the browser’s network monitor that /stylesheets/styles.css and the images have an HTTP response header “last-modified: Tue, 01 Jan 1980 00:00:01 GMT”, which is quite likely to cause caching issues.
I’m not sure why the last modified time has that value. Wikipedia says it’s the epoch of FAT filesystems and the ZIP format…
You can open a shell using fly ssh console and run ls -l /path/to/stylesheets to view the timestamps of the files in deployment (I predict they’ll be 1 Jan 1980), then try to backtrack from there to find where those timestamps are coming from (local filesystem? build process?).
There are ugly workarounds (e.g. fudge the timestamps during the build process), but I’d try to find the root cause first.
This is great for debugging (and confirms that the problem is due to caching), but I wouldn’t consider this a “solution” (or even a “workaround”) because your users can’t be expected to do a hard refresh every time you modify the files.
I can reproduce the issue both with your code and with Fly’s Helloruby app*. I’m confident the “1 Jan 1980” timestamp is due to the builder image heroku/buildpacks:20. Apparently it overwrites timestamps for reproducibility (discussion; that discussion is about the timestamps in the image metadata, but I assume it also applies to the file modification timestamps).
If you want to stick with the Heroku builder (which Fly picks by default), I’m not sure how you can fix this properly. As an ugly workaround, you can change the file modification times by running find . -exec touch {} + at early startup. Example config.ru:
# frozen_string_literal: true
# config.ru
require './app'
# HACK: set all file modification timestamps to the current time
# (builder "heroku/buildpacks:20" sets them to 1 Jan 1980, which causes caching issues)
# WARNING: if multiple workers are started, this will run multiple times...
system "find . -exec touch {} +"
run Sinatra::Application
I’m surprised that there are no online complaints about caching issues with Heroku due to these timestamps. Maybe the Heroku platform has some magic to deal with this; it would be interesting if somebody can test this. @kurt (I see you’ve read this thread): if Heroku is doing something different from Fly, you might want to look into it (especially given that “flyctl launch” automatically chooses “heroku/buildpacks:20” as the builder, and that this happens with Fly’s Helloruby application).
*To reproduce the issue with Fly’s Helloruby app, I created a file “public/stylesheets/styles.css” and confirmed that the response headers for https://<app>.fly.dev/stylesheets/styles.css included “last-modified: Tue, 01 Jan 1980 00:00:01 GMT”.