如何使用 Asset Pipeline 从非标准目录传递字体
Posted
技术标签:
【中文标题】如何使用 Asset Pipeline 从非标准目录传递字体【英文标题】:How to deliver fonts from a non-standard directory using Asset Pipeline 【发布时间】:2013-11-08 21:51:02 【问题描述】:我正在尝试将 Fontawesome 包含在 Rails 4 应用程序中,但资产并未进入资产管道。但是,字体并没有在生产中出现,我不知道为什么。
文件结构组织
我所有的资产都存储在/assets/components
这样 Fontawesome 就会出现在:/assets/components/font-awesome
(它们位于不同的目录中,因为我使用的是 Bower)。
CSS 清单文件:
# application.css.scss
/* ...
*= require bootstrap/dist/css/bootstrap
*= require font-awesome/css/font-awesome
*= require_self
*= require_tree .
*/
资产管道设置为预编译字体
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
config.assets.paths << Rails.root.join('vendor', 'assets', 'components')
# Adding Webfonts to the Asset Pipeline
config.assets.precompile << Proc.new |path|
if path =~ /\.(eot|svg|ttf|woff|otf)\z/
true
end
我添加了预编译指令,以便所有字体都被预编译as per this question
包括 Heroku 12 Factor gem
#gemfile
group :production do
gem "rails_12factor"
end
那么问题出在哪里?
当我推送到 Heroku 时,它显示应用程序正在请求文件但它们没有加载:
查看日志,这似乎是一个路由问题 - 我原以为字体会从 /assets/fonts
提供,但它显然在 /fonts
中查找
app[web.1]: Started GET "/fonts/fontawesome-webfont.ttf?v=4.0.1" for 86.161.231.181 at 2013-10-29 15:53:01 +0000
app[web.1]: Started GET "/fonts/fontawesome-webfont.ttf?v=4.0.1" for 86.161.231.181 at 2013-10-29 15:53:01 +0000
app[web.1]:
app[web.1]: ActionController::RoutingError (No route matches [GET] "/fonts/fontawesome-webfont.ttf"):
为什么没有提供资产
我对这一切有点困惑。为什么不提供这些字体?
【问题讨论】:
它说'没有路由匹配 [GET] "/fonts/fontawesome-webfont.ttf',但你不想从 /assets/fontawesome-webfont.ttf 加载吗?在 fontawesome。 css,我使用了 url('../fontawesome-webfont.ttf') 而不是 url('fonts/fontawesome-webfont.ttf') 嗨@AmyHua。你是对的,但是你不应该需要指定单独的字体文件。清单文件和单行require font-awesome/css/font-awesome
应该处理所有其他文件。此外,字体确实在开发中正确加载,只是链轮无法正确解析。
Heroku 有一个临时文件系统,您可以在会话中创建文件,但这只是您的 dyno 的一个实例,文件不会出现在新会话中,因为它将是新实例。也许你应该在推送之前确定文件是否在你的仓库中。
【参考方案1】:
这个问题可能是由于 Rails 资源无法在 CSS 文件中预编译 url()
函数引起的。
由于您的字体文件是由资产预编译的,所有指向这些文件的 url 都必须重写为 MD5 消化的文件名。不幸的是,Rails 不能自动预编译url()
,至少我是这么认为的,因为我测试了一些案例并得出了这个结论:) 在 Rails 指南中,Rails 使用 ERB 和 Sass 提供了这些功能。见here。
我认为有两种方法可以解决您的问题。
首先,将.bowerrc
中的目录设置为public/components
并手动使用它们,不要在资产中要求它们。
第二个,我建议在 Font-Awesome 中使用font-url()
而不是url()
,这样你的application.css.scss
就会变成这样:
/* ...
*= require bootstrap/dist/css/bootstrap
*= require font-awesome/css/font-awesome
*= require_self
*= require_tree .
*/
@font-face
font-family: 'FontAwesome';
src: font-url('font-awesome/fonts/fontawesome-webfont.eot?v=4.0.3');
src: font-url('font-awesome/fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'),
font-url('font-awesome/fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'),
font-url('font-awesome/fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'),
font-url('font-awesome/fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');
font-weight: normal;
font-style: normal;
用你的实际字体路径重新定义字体路径,用font-url()
重新定义字体,这个功能由sass-rails提供。预编译后,您会看到您的 url 已被重写为 /assets/font-awesome/fonts/fontawesome-webfont-50b448f878a6489819d7dbc0f7dbfba0.eot?v=4.0.3
或 public/assets/application-xxxxxx.css
中的类似内容。
您可以在各种包含资产的 gem 中找到相同的方法,例如 bootstrap-sass,它是一个非常受欢迎的 gem。阅读此文件:_glyphicons.scss。你会看到:
@font-face
font-family: 'Glyphicons Halflings';
src: font-url('#$icon-font-path#$icon-font-name.eot');
src: font-url('#$icon-font-path#$icon-font-name.eot?#iefix') format('embedded-opentype'),
font-url('#$icon-font-path#$icon-font-name.woff') format('woff'),
font-url('#$icon-font-path#$icon-font-name.ttf') format('truetype'),
font-url('#$icon-font-path#$icon-font-name.svg#glyphicons_halflingsregular') format('svg');
url()
已被替换。所以我认为在application.css.scss
中重写@font-face
是最简单的方法:)
顺便说一下,bootstrap 和 font-awesome 都有@font-face
。我不知道是否需要font-awesome。
当您访问该页面时,它会显示正确的日志。因此,您无需更改 bower 存储库中的任何代码。希望对您有所帮助。
【讨论】:
你好。这太棒了,谢谢你花了这么多时间。令人沮丧的是,这是所需的解决方案类型。我想知道font-url()
声明是否是问题所在。修复需要的东西太多了,以至于我几乎想知道将文件简单地放入目录并忽略 bower 是否更容易。这似乎很遗憾,但实际上也似乎更容易。你认为什么更易于维护?
嗨彼得,我已经改进了答案,请看一下。我认为如果有可以使用资产的 gem,使用 gem 会更易于维护。 Bower 可用于在没有url()
的情况下轻松包含 javascript 和 css。
Rails、bower/bower-rails 和 font-awesome/bootstrap 字体也有同样的问题。 @Bigxiang您的解决方案运行良好,但我仍然很困惑是否设置不正确或者这是完成此操作的正确(不幸)方式。以上是关于如何使用 Asset Pipeline 从非标准目录传递字体的主要内容,如果未能解决你的问题,请参考以下文章
如何加快 Rails Asset Pipeline 预编译过程?
Rails Asset Pipeline 预编译,如何正确执行?
带有 3rd 方库的 Grails Asset-Pipeline 系统
使用 Grails Asset-Pipeline 将 JavaScript 置于底层