Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need to skip asset_host sometimes for server rendering. #571

Closed
justin808 opened this issue Jul 18, 2017 · 2 comments
Closed

Need to skip asset_host sometimes for server rendering. #571

justin808 opened this issue Jul 18, 2017 · 2 comments

Comments

@justin808
Copy link
Contributor

justin808 commented Jul 18, 2017

Webpacker asset_path will use a CDN if configured. Usually, that's correct. However, in the case of doing server rendering of JavaScript, we want to fetch the JS file locally, as there is no reason to fetch the file from the CDN.

We need to pass a flag to asset_path of skip_asset_host. Thus, maybe the issue needs to be done in the main rails/rails repo.

Webpacker code:

  # Computes the full path for a given webpacker asset.
  # Return relative path using manifest.json and passes it to asset_url helper
  # This will use asset_path internally, so most of their behaviors will be the same.
  # Examples:
  #
  # In development mode:
  #   <%= asset_pack_path 'calendar.js' %> # => "/packs/calendar.js"
  # In production mode:
  #   <%= asset_pack_path 'calendar.css' %> # => "/packs/calendar-1016838bab065ae1e122.css"
  def asset_pack_path(name, **options)
    asset_path(Webpacker::Manifest.lookup(name), **options)
  end

and from the Rails source:
actionview/lib/action_view/helpers/asset_url_helper.rb#L181

I think the fix is to add a flag to allow skipping the asset_host:

So instead of

        if host = compute_asset_host(source, options)
          source = File.join(host, source)
        end

Use:

        if !options[:skip_asset_host] && host = compute_asset_host(source, options)
          source = File.join(host, source)
        end

Here's the full source:

   # This is the entry point for all assets.
      # When using the asset pipeline (i.e. sprockets and sprockets-rails), the
      # behavior is "enhanced". You can bypass the asset pipeline by passing in
      # <tt>skip_pipeline: true</tt> to the options.
      #
      # All other asset *_path helpers delegate through this method.
      #
      # === With the asset pipeline
      #
      # All options passed to +asset_path+ will be passed to +compute_asset_path+
      # which is implemented by sprockets-rails.
      #
      #   asset_path("application.js") # => "/assets/application-60aa4fdc5cea14baf5400fba1abf4f2a46a5166bad4772b1effe341570f07de9.js"
      #
      # === Without the asset pipeline (<tt>skip_pipeline: true</tt>)
      #
      # Accepts a <tt>type</tt> option that can specify the asset's extension. No error
      # checking is done to verify the source passed into +asset_path+ is valid
      # and that the file exists on disk.
      #
      #   asset_path("application.js", skip_pipeline: true)                 # => "application.js"
      #   asset_path("filedoesnotexist.png", skip_pipeline: true)           # => "filedoesnotexist.png"
      #   asset_path("application", type: :javascript, skip_pipeline: true) # => "/javascripts/application.js"
      #   asset_path("application", type: :stylesheet, skip_pipeline: true) # => "/stylesheets/application.css"
      #
      # === Options applying to all assets
      #
      # Below lists scenarios that apply to +asset_path+ whether or not you're
      # using the asset pipeline.
      #
      # - All fully qualified urls are returned immediately. This bypasses the
      #   asset pipeline and all other behavior described.
      #
      #     asset_path("http://www.example.com/js/xmlhr.js") # => "http://www.example.com/js/xmlhr.js"
      #
      # - All assets that begin with a forward slash are assumed to be full
      #   urls and will not be expanded. This will bypass the asset pipeline.
      #
      #     asset_path("/foo.png") # => "/foo.png"
      #
      # - All blank strings will be returned immediately. This bypasses the
      #   asset pipeline and all other behavior described.
      #
      #     asset_path("") # => ""
      #
      # - If <tt>config.relative_url_root</tt> is specified, all assets will have that
      #   root prepended.
      #
      #     Rails.application.config.relative_url_root = "bar"
      #     asset_path("foo.js", skip_pipeline: true) # => "bar/foo.js"
      #
      # - A different asset host can be specified via <tt>config.action_controller.asset_host</tt>
      #   this is commonly used in conjunction with a CDN.
      #
      #     Rails.application.config.action_controller.asset_host = "assets.example.com"
      #     asset_path("foo.js", skip_pipeline: true) # => "http://assets.example.com/foo.js"
      #
      # - An extension name can be specified manually with <tt>extname</tt>.
      #
      #     asset_path("foo", skip_pipeline: true, extname: ".js")     # => "/foo.js"
      #     asset_path("foo.css", skip_pipeline: true, extname: ".js") # => "/foo.css.js"
      def asset_path(source, options = {})
        raise ArgumentError, "nil is not a valid asset source" if source.nil?

        source = source.to_s
        return "" if source.blank?
        return source if URI_REGEXP.match?(source)

        tail, source = source[/([\?#].+)$/], source.sub(/([\?#].+)$/, "".freeze)

        if extname = compute_asset_extname(source, options)
          source = "#{source}#{extname}"
        end

        if source[0] != ?/
          if options[:skip_pipeline]
            source = public_compute_asset_path(source, options)
          else
            source = compute_asset_path(source, options)
          end
        end

        relative_url_root = defined?(config.relative_url_root) && config.relative_url_root
        if relative_url_root
          source = File.join(relative_url_root, source) unless source.starts_with?("#{relative_url_root}/")
        end

        if host = compute_asset_host(source, options)
          source = File.join(host, source)
        end

        "#{source}#{tail}"
      end
@justin808
Copy link
Contributor Author

@gauravtiwari I think I found a simpler solution:

shakacode/webpacker_lite#23

Please advise if this small API addition is OK for rails/webpacker.

@gauravtiwari
Copy link
Member

I think this is no longer an issue right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants