由于您已经为此使用 ERB:
body
{
background-image:url('banner2.jpg');
}
会成为:
body
{
background-image:url('<%= aws_asset "/assets/img/banner2.jpg" %>');
}
这就是简单的答案。但是,由于您可能要从 AWS 提供相当多的文件,然后在您需要的所有不同地方使用帮助程序可能会变得令人厌烦,而且也很困难 - 也许您将来会想要预编译 CSS 等等。这是什么时候使用 Rack 中间件隐藏一些实现是个好主意。
module MySinatraApp
# A remote file called banner2.jpg would have the relative path
# in the app of "/images/extra/banner2.jpg"
# and on being requested, this middleware/app would check if
# the remote file is in the list you've given
# if it is, a 307 redirect is issued.
# If it isn't, then a 404. Use with Rack::Cascade to pass on
# to another app that may serve a local version of the file.
# @example
# use RemoteImageServer,
# :asset_host => "//s3-eu-west-1.amazonaws.com"
# :files => ["banner2.jpg", "blah.gif"]
class RemoteImageServer
DEFAULT_OPTIONS = {
subdir: "images/extra",
cascade: false # until I work it out more, see note at bottom
}
def initialize(app,options={})
app, options = app, DEFAULT_OPTIONS.merge(options)
@asset_host = options[:asset_host]
files = options[:files]
@subdir = options[:subdir]
@http_path_files = files.map{|file| File.join @subdir, file }
end
def call( env )
dup._call( env ) # for thread safety
end
def _call( env )
request = Rack::Request.new env
if request.path_info.start_with? @subdir
response = Rack::Response.new env
if @http_path_files.include? request.path_info
response.redirect File.join(@asset_host,request.path_info), 307
response.finish
else
if @options[:cascade]
response.status = 404
response.finish
end
end
else
@app.call env
end
end
end
class MainApp < Sinatra::Base do
# other stuff here…
end
end
您可以在 Sinatra Application或 rackup 文件中使用它。我更喜欢后者并使用Rack::Cascade:
运行 Rack::Cascade.new([MySinatraApp::RemoteImageServer, MySinatraApp::MainApp])(我不确定在使用级联时如何最好地传递选项,我可能需要更多地考虑这一点)。
use RemoteImageServer,
:asset_host => "//s3-eu-west-1.amazonaws.com"
:files => ["banner2.jpg", "blah.gif"]
run MySinatraApp::MainApp
这样,远程主机就“隐藏”在了相对 url 后面,您可以用本地文件替换远程文件,或者轻松更改远程提供程序。最后的 Sinatra 应用程序仍将提供其公用文件夹中的任何本地文件。不过,这段代码完全未经测试!可能有一个 Rack 中间件已经这样做了(Rack Static Fallback可能很接近)。
编辑:通过 ERB 提供 CSS。
主要有2种方式:
- 预编译 CSS 并通过
public_folder
.
- 从
get
路线上服务。
预编译 CSS
可能有一个 gem 或其他东西可以做到这一点(可能是一个Guard助手或其他东西),但这将在控制台中工作:
require 'erb'
require 'tilt'
template = Tilt.new( "path/to/erb/file" )
File.open "app/public/stylesheets/main.css", "w" do |f|
f.write template.render
end
由于编译后的 CSS 文件将驻留在 Sinatra 的公共目录中,因此它将作为静态文件提供。由于您在aws_asset
文件中获得了来自 Sinatra 的帮助程序,因此您需要稍微更改它,或者在运行它之前在控制台中重新定义帮助程序,或者对路径进行硬编码,或者将其传递给变量。
从 Sinatra 获取路线上提供服务
get "/css/main.css" do
erb :main # it will server main.erb from the views directory
# and it will have access to helpers.
end
由于它是一个不会经常更改的文件,因此您最好添加缓存控制标头。