在创建静态应用程序时,我经常启动一个新的 Rails 应用程序。这使得一些事情变得更容易,比如编译(Coffeescript、SCSS)、最小化(JS、CSS)和浏览器限制(页面从 localhost:3000 提供,因此可以加载外部源等)。
最后,我想导出应用程序,以便将其放到网上。然后我只需要 HTML+CSS+JS。可以手动提取文件,但可能有一种更简单的方法。
那么:有没有一种工具可以存储来自 Rails 应用程序的已编译、最小化的 HTML+CSS+JS 文件?
在创建静态应用程序时,我经常启动一个新的 Rails 应用程序。这使得一些事情变得更容易,比如编译(Coffeescript、SCSS)、最小化(JS、CSS)和浏览器限制(页面从 localhost:3000 提供,因此可以加载外部源等)。
最后,我想导出应用程序,以便将其放到网上。然后我只需要 HTML+CSS+JS。可以手动提取文件,但可能有一种更简单的方法。
那么:有没有一种工具可以存储来自 Rails 应用程序的已编译、最小化的 HTML+CSS+JS 文件?
如果您只想复制网站,因为它将由 rails 呈现(并且不需要服务器端代码执行),您可以使用镜像 rails-website
wget --page-requisites --convert-links http://URL-to-Start
但是,这只会下载从条目 URL 引用的那些文件,因此您可能需要在所有子 URL 上单独运行它。
来源:下载网页的工作本地副本
同意 Screenmutt。我已经尝试了其中提到的几个,但在以下方面取得了最大的成功:
几乎可以满足您的所有要求,并让您导出为静态 HTML。
安装:
gem install middleman
创建项目:
middleman init my_new_project (or even better with template --template=html5)
在本地服务器上运行以进行实时编辑:
bundle exec middleman
转储静态代码:
bundle exec middleman build
也许您可以从提供它的本地主机“抓取”HTML?
一般而言,似乎有一些用于下载网站的工具......您可能可以将它们限制为localhost:3000
仅下载资源。
更新:这是另一个可能有助于将 Rails 3.1 用于静态站点的教程
这不是常见的用法。您可以通过手动缓存所有内容来提取所有静态页面。
我建议看看一些替代方案。
很抱歉,这不是一个好的答案,但老实说......您正在使用 Rails 做一些它从未打算做的事情。制作静态网站有很多更好的方法。
此外,静态网站不是“应用程序”。:)
您所要做的就是在本地切换到 Rails 生产模式,以便合并和缩小资产。然后您所要做的就是查看 HTML、CSS 和 JS 的源代码。这应该只需要几秒钟。
所以步骤是
您可以使用 Wget(如前所述)。我会去:
wget --mirror --convert-links --adjust-extension --page-requisites --no-parent http://www.yourdomain.com
哟也可以使用Httrack。
确保在设置 Httrack 时排除所有带有脚本的外部网站,这样您就不会下载 fe Google Analytics js 文件或 Adsense 或 Facebook 脚本。在 Httrack 中,您在首选项中排除它:
-*.googlesyndication.com/* -*.facebook.net/* -*.google-analytics.com/*
完成后,您仍然需要重写所有链接,因为它们将指向.../some-page/index.html您需要.../some-page/。这解决了从动态到静态脚本的问题。
您不应该从 rails 为它们提供服务,也不应该做任何将您的静态文件绑定到从 rails 提供服务的事情。您可能有一天会决定从 CDN 为您的应用程序提供服务。
一个重要提示是查看使用 AMD(异步模块定义),它允许您指定 JS 文件依赖项。然后,您可以使用 require.js 和 r.js(在预编译步骤中抓取和编译依赖项的工具)。这对你的 JS 有用。
对于 CSS,您可以使用 sass 或更少。您最终会在页面上包含 1 个文件,但编译过程将涉及将您的 CSS 文件合并在一起。再一次,这可以在预编译步骤中完成。
那里有一些宝石可以显示你的资产并将它们传递给像 S3 这样的东西,这个答案和其他类似的东西会有所帮助:有没有办法在推送到 heroku 时将管道资产资产到 s3?; 但是,当您第一次开始时,这不是必需的。
我使用一个 Rake 任务来完成它,该任务将一次获取每个 Rails 路由。它需要一些狡猾的扑克来处理您可能有冲突的路线这一事实 - 例如,wget 将/objects
作为一个名为“objects”的文件获取,但是当您想要获取/objects/4
它时,它会用一个名为“objects”的文件夹覆盖该文件嵌套文件名为“4”。所以我将每个下载的页面移动到同名目录中的“index.html”。
这是我的代码,我在其中lib/tasks/export.rake
:
def adjust_paths(path)
text = File.read(path)
new_contents = text.gsub(/("|\.\.\/)(assets|packs)\//, "\\1../\\2/")
new_contents = new_contents.gsub("http://localhost:3020", "")
File.write(path, new_contents)
end
namespace :static do
desc 'Generate static site in ./out/ directory'
task :export => [
'assets:clean',
'assets:precompile',
:start_rails_server
] do
begin
out_prefix = "dist"
paths = Rails.application.routes.routes.map do |route|
route.path.spec.to_s
end.uniq.reject { |p| p.starts_with?("/rails") || p == "/cable" || p == "/assets" }
paths = paths.map { |p| p.sub("(.:format)", "") }
paths.sort_by(&:length).each do |path|
if path.include?(":id")
# You'll have to use your own method for deciding which ids to use
ids = ["1", "2", "3", "4"]
else
ids = [""]
end
ids.each do |id|
id_path = path.sub(":id", id)
`wget -P #{out_prefix} -nH -p -k http://localhost:3020#{id_path}`
if id_path != "/"
file_path = "#{out_prefix}#{id_path}"
FileUtils.mv(file_path, "#{file_path}.tmp", force: true)
FileUtils.mkdir_p(file_path)
result = FileUtils.mv("#{file_path}.tmp", "#{file_path}/index.html", force: true)
puts "Moving #{id_path} to #{id_path}/index.html: #{result}"
# Will then need to relativise all of the asset paths, since we've moved it
adjust_paths("#{file_path}/index.html")
end
end
end
ensure
# stop the server when we're done
Rake::Task['static:stop_rails_server'].reenable
Rake::Task['static:stop_rails_server'].invoke
end
end
desc 'Start a Rails server in the static Rails.env on port 3020'
task :start_rails_server do
`RAILS_SERVE_STATIC_FILES=1,RAILS_ENV=static rails s -p 3020 -d`
end
desc 'Stop Rails server'
task :stop_rails_server do
`cat tmp/pids/server.pid | xargs -I {} kill {}`
end
end
然后你可以做bundle exec rake static:export