Skip to content

Accelerate asset delivery in Rails 4, yay or nay? #10291

@SamSaffron

Description

@SamSaffron

At Discourse we unfortunately have an enormous amount of assets to deliver in development mode.

Current count is 373 css and js files.

This means that clicking the "reload" button in the browser in development mode results in 800 requests to the web server.

Other big "asset heavy" apps (like ember js etc) tend to have lots of js assets. This is also discussed here: http://discuss.emberjs.com/t/what-are-people-doing-about-the-gazzillion-file-problem/1006


The main reason asset delivery is slow in Rails dev environment is that the entire middleware stack needs to be walked prior to reaching sprockets and determining if an asset changed.

For context, this is Discourse prior to improving this:

image

Introducing this middleware in front of the stack:

module Middleware
  # this class cheats and bypasses rails altogether if the client attempts
  # to download a static asset
  class TurboDev
    def initialize(app, settings={})
      @app = app
    end
    def call(env)
      # hack to bypass all middleware if serving assets, a lot faster 4.5 seconds -> 1.5 seconds
      if (etag = env['HTTP_IF_NONE_MATCH']) && env['REQUEST_PATH'] =~ /^\/assets\//
        name = $'
        etag = etag.gsub "\"", ""
        asset = Rails.application.assets.find_asset(name)
        if asset && asset.digest == etag
          return [304,{},[]]
        end
      end

      @app.call(env)
    end
  end
end

Takes us to:

image

So in this test run that is over 4 seconds down to 1.3 seconds.


I discussed this with @josh over twitter, the current thinking is that sprockets 3 is going to use source maps only for dev, bypassing much of this issue.

My concern is that sourcemaps may introduce extra server delays and outlaw some optimisations you can do with split up files. For example, when assets are split you could use $LAB to load the js files, circumventing the browser refresh forced round trip.


Anyway, we need to decide if we want this optimisation or not in Rails 4.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions