{"action":"created","issue":{"url":"https://api.github.com/repos/rails/rails/issues/10291","labels_url":"https://api.github.com/repos/rails/rails/issues/10291/labels{/name}","comments_url":"https://api.github.com/repos/rails/rails/issues/10291/comments","events_url":"https://api.github.com/repos/rails/rails/issues/10291/events","html_url":"https://github.com/rails/rails/issues/10291","id":13459361,"number":10291,"title":"Accelerate asset delivery in Rails 4, yay or nay?","user":{"login":"SamSaffron","id":5213,"avatar_url":"https://avatars.githubusercontent.com/u/5213?v=3","gravatar_id":"","url":"https://api.github.com/users/SamSaffron","html_url":"https://github.com/SamSaffron","followers_url":"https://api.github.com/users/SamSaffron/followers","following_url":"https://api.github.com/users/SamSaffron/following{/other_user}","gists_url":"https://api.github.com/users/SamSaffron/gists{/gist_id}","starred_url":"https://api.github.com/users/SamSaffron/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SamSaffron/subscriptions","organizations_url":"https://api.github.com/users/SamSaffron/orgs","repos_url":"https://api.github.com/users/SamSaffron/repos","events_url":"https://api.github.com/users/SamSaffron/events{/privacy}","received_events_url":"https://api.github.com/users/SamSaffron/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/rails/rails/milestones/24","labels_url":"https://api.github.com/repos/rails/rails/milestones/24/labels","id":297919,"number":24,"title":"4.2.0","description":"","creator":{"login":"rafaelfranca","id":47848,"avatar_url":"https://avatars.githubusercontent.com/u/47848?v=3","gravatar_id":"","url":"https://api.github.com/users/rafaelfranca","html_url":"https://github.com/rafaelfranca","followers_url":"https://api.github.com/users/rafaelfranca/followers","following_url":"https://api.github.com/users/rafaelfranca/following{/other_user}","gists_url":"https://api.github.com/users/rafaelfranca/gists{/gist_id}","starred_url":"https://api.github.com/users/rafaelfranca/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rafaelfranca/subscriptions","organizations_url":"https://api.github.com/users/rafaelfranca/orgs","repos_url":"https://api.github.com/users/rafaelfranca/repos","events_url":"https://api.github.com/users/rafaelfranca/events{/privacy}","received_events_url":"https://api.github.com/users/rafaelfranca/received_events","type":"User","site_admin":false},"open_issues":0,"closed_issues":222,"state":"closed","created_at":"2013-03-27T19:29:42Z","updated_at":"2014-12-22T16:38:59Z","due_on":"2014-12-23T02:00:00Z","closed_at":"2014-12-22T16:38:59Z"},"comments":27,"created_at":"2013-04-22T00:26:32Z","updated_at":"2015-02-09T00:59:58Z","closed_at":"2014-04-01T02:13:07Z","body":"At Discourse we unfortunately have an enormous amount of assets to deliver in development mode. \r\n\r\nCurrent count is **373** css and js files. \r\n\r\nThis means that clicking the \"reload\" button in the browser in development mode results in 800 requests to the web server. \r\n\r\nOther 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\r\n\r\n--- \r\n\r\nThe 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. \r\n\r\nFor context, this is Discourse prior to improving this: \r\n\r\n![image](https://f.cloud.github.com/assets/5213/407132/69baa132-aae2-11e2-95a8-dfff32dcc768.png)\r\n\r\nIntroducing this middleware in front of the stack: \r\n\r\n```ruby\r\nmodule Middleware\r\n  # this class cheats and bypasses rails altogether if the client attempts\r\n  # to download a static asset\r\n  class TurboDev\r\n    def initialize(app, settings={})\r\n      @app = app\r\n    end\r\n    def call(env)\r\n      # hack to bypass all middleware if serving assets, a lot faster 4.5 seconds -> 1.5 seconds\r\n      if (etag = env['HTTP_IF_NONE_MATCH']) && env['REQUEST_PATH'] =~ /^\\/assets\\//\r\n        name = $'\r\n        etag = etag.gsub \"\\\"\", \"\"\r\n        asset = Rails.application.assets.find_asset(name)\r\n        if asset && asset.digest == etag\r\n          return [304,{},[]]\r\n        end\r\n      end\r\n\r\n      @app.call(env)\r\n    end\r\n  end\r\nend\r\n```\r\n\r\nTakes us to:\r\n\r\n![image](https://f.cloud.github.com/assets/5213/407136/be70a5e6-aae2-11e2-9b21-341cc7c19b93.png)\r\n\r\nSo in this test run that is over 4 seconds down to 1.3 seconds. \r\n\r\n---\r\n\r\nI 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. \r\n\r\nMy 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. \r\n\r\n--- \r\n\r\nAnyway, we need to decide if we want this optimisation or not in Rails 4. \r\n\r\n\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/rails/rails/issues/comments/73444065","html_url":"https://github.com/rails/rails/issues/10291#issuecomment-73444065","issue_url":"https://api.github.com/repos/rails/rails/issues/10291","id":73444065,"user":{"login":"SamSaffron","id":5213,"avatar_url":"https://avatars.githubusercontent.com/u/5213?v=3","gravatar_id":"","url":"https://api.github.com/users/SamSaffron","html_url":"https://github.com/SamSaffron","followers_url":"https://api.github.com/users/SamSaffron/followers","following_url":"https://api.github.com/users/SamSaffron/following{/other_user}","gists_url":"https://api.github.com/users/SamSaffron/gists{/gist_id}","starred_url":"https://api.github.com/users/SamSaffron/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SamSaffron/subscriptions","organizations_url":"https://api.github.com/users/SamSaffron/orgs","repos_url":"https://api.github.com/users/SamSaffron/repos","events_url":"https://api.github.com/users/SamSaffron/events{/privacy}","received_events_url":"https://api.github.com/users/SamSaffron/received_events","type":"User","site_admin":false},"created_at":"2015-02-09T00:59:58Z","updated_at":"2015-02-09T00:59:58Z","body":"@chancancode very good point about find_asset, I misread that and can confirm that its not really doing what I initially thought it was doing. \r\n\r\nI do however believe this is a severe issue that a lot are facing, and think there is a very simple solution to this problem with very minor changes on rails side. \r\n\r\nSince \"find_asset\" already has digests why not append them to the asset name, eg in development you would have:\r\n\r\n```\r\ndiscourse/lib/some-file.js?body=1&digest=abcabc123123\r\n```\r\n\r\nThen we can simply set these assets to never expire, which allows for people to run nginx in front or rack cache in front and cache server side forever if they wish. They will also get a more reasonable reload experience without any magic. Rails can consider then adding rack::cache or something similar to that in development so there is a turnkey solution that everyone get. \r\n\r\nThis seems like a reasonable solution to this problem and would add zero additional cost on rails side.\r\n\r\nI do not think sourcemaps will solve this issue. regenerating them on single asset invalidation and building up bundles is going to add up a lot on dev.\r\n\r\ncc @josh "}}