使用Sinatra提供静态文件服务

143

我有一个只使用HTML、CSS和JavaScript的单页面网站。 我想将应用程序部署到Heroku,但是我找不到方法来实现。 现在我正在尝试使用Sinatra让应用程序工作。

.
|-- application.css
|-- application.js
|-- index.html
|-- jquery.js
`-- myapp.rb

以下是myapp.rb的内容。

require 'rubygems'
require 'sinatra'

get "/" do
  # What should I write here to point to the `index.html`
end

1
我已经学会了访问 http://localhost:2345/index.html 的方法。 - TK.
你可以使用 WebBrick 在几行代码中提供静态文件服务。require 'webrick'; server = WEBrick::HTTPServer.new Port: 1234; server.mount '/', WEBrick::HTTPServlet::FileHandler, 'www/'; trap("INT") { server.stop }; server.start; 然后运行 ruby myapp.rb。在 Heroku 中移除端口。将 web: ruby myapp.rb 放入你的 Procfile 文件中。请注意,这不是针对 Sinatra 的回答,但我认为它简化了依赖关系。 - Chloe
14个回答

169
你可以使用send_file助手来提供文件服务。
require 'sinatra'

get '/' do
  send_file File.join(settings.public_folder, 'index.html')
end

这将从已配置为具有应用程序静态文件的目录中提供index.html


19
我认为较新的Sinatra应用程序使用set :public_folder,因此您需要使用settings.public_folder而不是settings.public - Andrew
4
我更新了答案,使用了settings.public_folder。旧应用程序可能仍需要使用settings.public。 - Chad DeShon

134

在没有任何额外配置的情况下,Sinatra将会服务于public目录下的资源文件。对于空路由,你需要渲染首页文档。

require 'rubygems'
require 'sinatra'

get '/' do
  File.read(File.join('public', 'index.html'))
end

路由应该返回一个字符串,这个字符串将成为HTTP响应主体。File.read打开一个文件,读取文件,关闭文件并返回一个字符串。


54
建议使用 send_file File.expand_path('index.html', settings.public) 替代之前的代码。 - Konstantin Haase
33
现在这是不正确的。你应该将 settings.public 替换为 settings.public_folder,以获得 send_file File.expand_path('index.html', settings.public_folder) - Alistair Holt
2
@zhirzh send_file,它可以为您执行额外的操作 https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L351 - ian
1
File.read 读取整个文件到内存中。这可能是可以的,也可能不可以,这取决于文件的大小和并发请求的数量。 - Wayne Conrad
@WayneConrad 相反,send_file可以吗?还是它的作用相同? - Ben
@Ben 我不确定,但如果 send_file 不能优雅地处理大文件,我会感到惊讶。 - Wayne Conrad

65

您可以直接从公共文件夹中托管它们,而不需要路由。

.
-- myapp.rb
`-- public
    |-- application.css
    |-- application.js
    |-- index.html
    `-- jquery.js

在myapp.rb文件中

set :public_folder, 'public'

get "/" do
  redirect '/index.html'
end

链接到public文件夹中的某个子文件夹

set :public_folder, 'public'
get "/" do
  redirect '/subfolder/index.html' 
end

./public文件夹中的所有内容都可以通过'/whatever/bla.html'路径访问

例如:
./public/stylesheets/screen.css
将可以通过'/stylesheets/screen.css'路径直接访问,无需路由


1
如果公共文件夹有许多嵌套的文件夹(您不想创建路由),并且这些文件夹中有index.html文件,您希望将其作为默认文件怎么办? - Derek Prior
我已经扩展了解决方案。希望它能够澄清问题,所有内容都是公开可访问的,不需要路由,只需省略路径中的“public”部分即可。 - Morgan
1
在Heroku上使用rackup时,我不得不使用set:public_folder,'public'。尽管Sinatra文档暗示这已经作为默认设置,但这是使其工作的关键。 - Daniel C

12

请记住,在生产环境中,您可以让您的Web服务器自动发送index.html,这样请求就不会传递给Sinatra。 这样做可以提高性能,因为您无需经过Sinatra / Rack堆栈来提供静态文本,而这正是Apache / Nginx的强项。


哦,是啊。我只需使用Erb,然后使用Varnish进行缓存即可。 - ma11hew28
3
你如何在生产环境中配置这个?我一直在搜索有关Sinatra和Rack交叉引用的文档,但找不到。基本上,如果用户只输入文件夹名称,则希望在任何具有index.html的/public文件夹中加载它。 - user44484

11

Sinatra让你可以从public目录(如文档中所述)提供静态文件:

静态文件

静态文件从./public目录中提供。您可以通过设置:public选项来指定不同的位置:

请注意,公共目录名称不包含在URL中。例如,一个名为./public/css/style.css的文件可作为example.com/css/style.css使用。


6
这个为什么有4票?它没有回答如何在请求文件夹时呈现默认文档的问题。 - Derek Prior

6

3

3
您可以始终使用Rack::Static。
只需在“config.ru”中的“run”命令之前添加此行即可。 https://www.rubydoc.info/gems/rack/Rack/Static
use Rack::Static, :urls => [""], :root => 'public', :index => 'index.html'

2

更新的答案: 我尝试了上述所有方法,但无法成功加载css、js等内容,唯一能够加载的是index.html... 其余的都会出现404错误

我的解决方案:app文件夹看起来像这样。

index.rb ==>> 放置Sinatra代码。

require 'rubygems'
require 'sinatra'

get '/' do
  html :index
end

def html(view)
  File.read(File.join('public', "#{view.to_s}.html"))
end

public文件夹==>> 包含其他所有内容...css,js,等等。

user@user-SVE1411EGXB:~/sintra1$ ls
index.rb  public
user@user-SVE1411EGXB:~/sintra1$ find public/
public/
public/index.html
public/about_us.html
public/contact.html
public/fonts
public/fonts/fontawesome-webfont.svg
public/fonts/fontawesome-webfont.ttf
public/img
public/img/drink_ZIDO.jpg
public/js
public/js/bootstrap.min.js
public/js/jquery.min.js
public/js/bootstrap.js
public/carsoul2.html
public/css
public/css/font-awesome-ie7.css
public/css/bootstrap.min.css
public/css/font-awesome.min.css
public/css/bootstrap.css
public/css/font-awesome.css
public/css/style.css
user@user-SVE1411EGXB:~/sintra1$

现在启动服务器,您将能够轻松浏览静态页面。
user@user-SVE1411EGXB:~/sintra1$ ruby index.rb 
== Sinatra/1.4.5 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.5.1 codename Straight Razor)
>> Maximum connections set to 1024
>> Listening on localhost:4567, CTRL+C to stop

2

Sinatra-Assetpack宝石提供了许多功能。语法很简洁:

serve '/js', from: '/app/javascripts'

虽然我仍然在处理Rails资产管道方面遇到问题,但是我觉得使用sinatra-assetpack可以更好地控制 - 但大多数情况下只需几行代码即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接