Script Relocator: Anything wrong with this?

Hi!

For a faster initial render of my pages, I have added a script relocator initializer that scans the page and moves all script tags to the bottom of the body tag. Order is kept, and the script tags in the head tag are marked with data-turbolinks-eval=“false” so they are not executed again on new pages when using turbolinks.

It seems to work well and do exactly what I want. Can anybody see anything wrong with it? Any reason NOT to use it? What can it break?

cat config/initializers/rack-script_relocator.rb

require ‘nokogiri’

module Rack
class ScriptRelocator
def initialize(app)
@app = app
end

def call(env)
  status, headers, response = @app.call(env)
  if headers['Content-Type'] !~ %r{^text/html}
    return status, headers, response
  end
  response_body = ''
  response.each { |part| response_body << part }
  doc = Nokogiri::HTML(response_body)
  scripts = doc.css('script')
  return status, headers, response if scripts.empty?
  scripts.each do |s|
    s['data-turbolinks-eval'] = 'false' if s.parent.name == 'head'
    s.remove
    doc.at('body') << s
  end
  transformed_body = doc.to_html
  if headers.key?('Content-Length') &&
      headers['Content-Length'].to_i != transformed_body.length
    headers['Content-Length'] = transformed_body.length.to_s
  end
  return status, headers, [transformed_body]
end

end
end

Rails.application.config.middleware.use Rack::ScriptRelocator

``

Off the top of my head, it seems like it would not work with http://api.rubyonrails.org/classes/ActionController/Streaming.html - which may or may not be a concern.

Fred

Yeah, thanks for the tip. I will disable it for streaming responses. For my specific app it is not a concern since I don’t stream HTML responses, and the script relocator is only active for text/html responses. I will add detection for streaming and leave the response alone if it is a streaming response so I don’t have to worry about it if I later decide to stream text/html responses (like from a document archive).