Script Relocator: Anything wrong with this?


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 =
  if headers['Content-Type'] !~ %r{^text/html}
    return status, headers, response
  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 == 'head'
    s.remove'body') << s
  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
  return status, headers, [transformed_body]

end end

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


Off the top of my head, it seems like it would not work with ActionController::Streaming - which may or may not be a concern.


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).