0

I have followed the default Rails tutorial on the Fly.io website : https://fly.io/docs/rails/getting-started/

It works well but when you reload the page, the css "blink" : https://rails-demo.fly.dev/fly/index

When I open the web console, JS and CSS resources are not loaded into memory or disk.. maybe the issue came from here

enter image description here

Here is my production.rb

require "active_support/core_ext/integer/time"

Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.

  # Code is not reloaded between requests.
  config.cache_classes = true

  # Eager load code on boot. This eager loads most of Rails and
  # your application in memory, allowing both threaded web servers
  # and those relying on copy on write to perform better.
  # Rake tasks automatically ignore this option for performance.
  config.eager_load = true

  # Full error reports are disabled and caching is turned on.
  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true

  # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
  # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
  # config.require_master_key = true

  # Disable serving static files from the `/public` folder by default since
  # Apache or NGINX already handles this.
  config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?

  config.public_file_server.headers = {
    'Cache-Control' => 'public, max-age=15552000',
    'Expires' => 1.year.from_now.to_formatted_s(:rfc822)
  }

  # Compress CSS using a preprocessor.
  # config.assets.css_compressor = :sass

  # Do not fallback to assets pipeline if a precompiled asset is missed.
  config.assets.compile = false

  # Enable serving of images, stylesheets, and JavaScripts from an asset server.
  # config.asset_host = "http://assets.example.com"

  # Specifies the header that your server uses for sending files.
  # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache
  # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX

  # Store uploaded files on the local file system (see config/storage.yml for options).
  config.active_storage.service = :local

  # Mount Action Cable outside main process or domain.
  # config.action_cable.mount_path = nil
  # config.action_cable.url = "wss://example.com/cable"
  # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ]

  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
  # config.force_ssl = true

  # Include generic and useful information about system operation, but avoid logging too much
  # information to avoid inadvertent exposure of personally identifiable information (PII).
  config.log_level = :info

  # Prepend all log lines with the following tags.
  config.log_tags = [ :request_id ]

  # Use a different cache store in production.
  # config.cache_store = :mem_cache_store

  # Use a real queuing backend for Active Job (and separate queues per environment).
  # config.active_job.queue_adapter     = :resque
  # config.active_job.queue_name_prefix = "list_production"

  config.action_mailer.perform_caching = false

  # Ignore bad email addresses and do not raise email delivery errors.
  # Set this to true and configure the email server for immediate delivery to raise delivery errors.
  # config.action_mailer.raise_delivery_errors = false

  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
  # the I18n.default_locale when a translation cannot be found).
  config.i18n.fallbacks = true

  # Don't log any deprecations.
  config.active_support.report_deprecations = false

  # Use default logging formatter so that PID and timestamp are not suppressed.
  config.log_formatter = ::Logger::Formatter.new

  # Use a different logger for distributed setups.
  # require "syslog/logger"
  # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name")

  if ENV["RAILS_LOG_TO_STDOUT"].present?
    logger           = ActiveSupport::Logger.new(STDOUT)
    logger.formatter = config.log_formatter
    config.logger    = ActiveSupport::TaggedLogging.new(logger)
  end

  # Do not dump schema after migrations.
  config.active_record.dump_schema_after_migration = false
end
Louis Bertin
  • 552
  • 2
  • 12
  • If you reload the page, all assets are reloaded. They can be cached or not, but they are reloaded. Why do you expect them not to blink ? Do you use anything that would prevent it ? Turbo makes your pages not blink when you transition from a page to another. But the reload button of the browser should incur a small blink. – Maxence Jul 16 '23 at 21:29
  • I'm sure something's wrong: take a look at almost the same application on Render: https://mysite-1d77.onrender.com/ There's no blinking and when you open the inspector: all assets are in the cache. – Louis Bertin Jul 16 '23 at 21:32
  • Yep on render your assets are cached. But they still blink on reload (also there is just the title on render). The blink still happen when your assets are cached, it is the browser repainting your page. Regarding the cached status of your static assets it is just a header set by the rails app. I have checked my latest app and have nothing fancy in my `config/environments/production.rb` except `config.action_controller.perform_caching = true` and it is all cached by the browser until 2037. – Maxence Jul 16 '23 at 21:48
  • If you want to set manually for how long your static assets are cached by the browser you can check this stackoverflow thread: https://stackoverflow.com/questions/52684004/cache-warnings-from-chrome-audit-on-rails-5-precompiled-assets – Maxence Jul 16 '23 at 21:49
  • On Fly.dev you can go to your browser network tab and click on an asset, you will see the cache control is like that : `cache-control: public, max-age=0, must-revalidate` and on render it is : `cf-cache-status: DYNAMIC` which iI am not familiar with but seems to be a Cloudflare tag. => cloudflare has added a cache-policy by themselves to your static assets. Just check stackoverflow thread mentionned above and add some cache-policy by yourself to your static assets headers... – Maxence Jul 16 '23 at 21:56
  • I have added my `production.rb` to the post. As you can see, I have added the cache lines, but I have still the same issue. Here is a demo app with Laravel and Tailwind : https://mirthful-oasis-93ciaezwqe.ploi.site/hello and it works as expected. I only have the issue on Fly.io – Louis Bertin Jul 16 '23 at 22:52
  • 1
    Do you have an environment variable `RAILS_SERVE_STATIC_FILES` to enable your app to serve your static assets ? Otherwise you can change `config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?` to `config.public_file_server.enabled = true`Also It seems ploi.site and render.com use a CDN (Cloudlfare) so this is transparent to you. Does Fly uses Nginx ? is Nginx setup to serve static files with a cache-policy ? I will stop here and let other users who may know Fly.io to reply to you if they have more info.. – Maxence Jul 16 '23 at 23:12
  • Thanks for your advice. I think I have figure out why it doesn't works. By default, Fly.io provide a Dockerfile based on Puma server for Rails applications. Here is a topic to use Nginx instead : https://fly.io/docs/rails/advanced-guides/phusion-passenger/ – Louis Bertin Jul 17 '23 at 07:05
  • Also I have seen this post : https://stackoverflow.com/questions/44477031/rails-assets-dont-have-cache-control-headers-with-puma-on-heroku If I can avoid Nginx and use Puma it could be better – Louis Bertin Jul 17 '23 at 07:12

1 Answers1

0

Finally, it was because of the fly.toml and the lines about statics I have just remove these lines :

[[statics]]
  guest_path = "/rails/public"
  url_prefix = "/"

But Fly.io seems to have a proxy strategy to serve assets : https://fly.io/docs/reference/configuration/#the-statics-sections so maybe I will use CDN or keep this settings

Louis Bertin
  • 552
  • 2
  • 12