rstacruz / sinatra-assetpack

Package your assets transparently in Sinatra.
http://ricostacruz.com/sinatra-assetpack/
MIT License
541 stars 97 forks source link

Serve assets from subpath #92

Closed doits closed 11 years ago

doits commented 11 years ago

I have the following config:

# where sinatra lives
http://HOST/PATH/

# my js files should be served from
http://HOST/PATH/js/global.js

Ho can I make sinatra-assetpack work in the sub path? I tried the following which nearly works:

assets do
    serve "/PATH/js", from: "wherever/js"

    js :global, [
        "/PATH/js/global.js"
    ]
end

the layout js helper puts out correct scripts and path, but the file can only be accessed by doubling the path:

http://HOST/PATH/PATH/js/global.js

Maybe either sinatra-assetpack should be aware by itself of the sub path it (ENV['RACK_BASE_URI']?) or at least the user should have the possiblity to configure it by itself, something like:

assets do
    base_uri '/PATH/'

    serve "/js", from: "wherever/js"

    js :global, [
        "/js/global.js"
    ]
end
j15e commented 11 years ago

Use a rack middleware to rewrite paths to do this, it will avoid adding complexity to our codebase :

# config.ru
 use Rack::Rewrite do
      rewrite %r{^/\w{2}/utils}, '/utils'
      rewrite %r{^/\w{2}/ctrl},  '/ctrl'
      rewrite %r{^/\w{2}/},      '/'
    end

Source : http://stackoverflow.com/questions/6221019/is-it-possible-to-to-rewrite-the-base-url-in-sinatra?answertab=active#tab-top

doits commented 11 years ago

can you explain this further? With the code I posted above I can only access the generated assets by doubling the PATH:

http://HOST/PATH/PATH/js/global.js

But the js helper puts out the path once obviously:

http://HOST/PATH/js/global.js

The problem is that the assets are served from /PATH/PATH/.

If I remove the PATH from serve like this:

assets do
    serve "/js", from: "wherever/js"

    js :global, [
        "/PATH/js/global.js"
    ]
end

I can access the file by http://HOST/PATH/js/global.js (which is correct!), but the helper does not generate all files with wildcards:

assets do
    serve "/js", from: "wherever/js"

    js :global, [
        "/PATH/js/*" # does not recognize the global.js
    ]
end

I can access http://HOST/PATH/js/global.js manually, but the js helper does not output a script tag to the file (in development mode, did not test whether it merges the file in production mode correctly)

doits commented 11 years ago

okey, looks like I got it working:

use Rack::Rewrite do
    rewrite %r{/js/(.*)}, '/PATH/js/$1'
end 

assets do
    serve "/PATH/js", from: "wherever/js"

    js :global, [
        "/PATH/js/*"
    ]
end

Hopefully this works with css and img, too.

j15e commented 11 years ago

Should work too if you add a rewrite for it. Thanks for sharing your solution, I hope this helps others!

doits commented 11 years ago

any chance to get cache busting to work in css url helper? I now have:

use Rack::Rewrite do
    rewrite %r{/(img|css)/(.*)}, '/PATH/$1/$2'
end 

assets do
    serve "/PATH/img", from: "wherever/img"
    serve "/PATH/css", from: "wherever/css"
end

I can correctly access http://HOST/PATH/img/file.png and with cache busting suffix too http://HOST/PATH/img/file.655d07a92161761073733dadee2094da.png.

My scss files are served correctly, too, but my urls are not being rewritten. eg:

body {
    background-image: url('/PATH/img/file.png');
}

stays the same in output, it should have the md5 suffix automatically afaik:

body {
    background-image: url('/PATH/img/file.655d07a92161761073733dadee2094da.png');
}

any suggestions?

j15e commented 11 years ago

Duh, yeah, that is problematic. Maybe assetpack should use rack base uri somehow (if that concept exist) to build the uri. If you look into it and find a solution I'll add a fix for this. Maybe we should look at how sprockets deal with url, there might be a solution for this kind of problem.

j15e commented 11 years ago

Have you try using relative urls ex. ../img/?

That being said, I don't know if sinatra-assetpack filters to add md5 to url() will still work

doits commented 11 years ago

I tried with ../img, but no luck. Serves the file but without suffix.

In my env I got the following three vars with the sub path, but I am using passenger with apache, so don't know if they exist everywhere.

ENV["RAILS_RELATIVE_URL_ROOT"]
ENV["RACK_BASE_URI"]
ENV["PASSENGER_BASE_URI"] #  looks like only there with passenger ;-)

In addition to this, afaik sinatra (or rack?) populates request.script_name with the correct sub path. since request.script_name cannot be accessed in config.ru it cannot be used, but maybe the same method can be used.

bct commented 11 years ago

Rack sets the request.script_name. I think it's the right thing to use, since (for example) Sinatra uses it in its uri() helper to generate internal URLs: https://github.com/sinatra/sinatra/blob/7c3a194935b7c9871783039958ac2963f83539b9/lib/sinatra/base.rb#L267

j15e commented 11 years ago

Very nice finding, I will have a look at this next time I work on assetpack for sure

Rack sets the request.script_name. I think it's the right thing to use, since (for example) Sinatra uses it in its uri() helper to generate internal URLs: https://github.com/sinatra/sinatra/blob/7c3a194935b7c9871783039958ac2963f83539b9/lib/sinatra/base.rb#L267

— Reply to this email directly or view it on GitHubhttps://github.com/rstacruz/sinatra-assetpack/issues/92#issuecomment-18322571 .