在Rails资产管道中使用字体


345

我在Scss文件中配置了一些字体,如下所示:

@font-face {
  font-family: 'Icomoon';
  src: asset-url('icoMoon.eot?#iefix', font) format('embedded-opentype'),
       asset-url('icoMoon.woff', font) format('woff'),
       asset-url('icoMoon.ttf', font)  format('truetype'),
       asset-url('icoMoon.svg#Icomoon', font) format('svg');
}

实际的字体文件存储在/ app / assets / fonts /中

我已添加config.assets.paths << Rails.root.join("app", "assets", "fonts")到我的application.rb文件

并且编译的CSS源代码如下:

@font-face {
  font-family: 'Icomoon';
  src: url(/assets/icoMoon.eot?#iefix) format("embedded-opentype"), url(/assets/icoMoon.woff) format("woff"), url(/assets/icoMoon.ttf) format("truetype"), url(/assets/icoMoon.svg#Icomoon) format("svg");
}

但是,当我运行该应用程序时,找不到字体文件。日志:

在2012-06-05 23:21:17 +0100投放的资产/icoMoon.ttf-127.0.0.1开始获取“ /assets/icoMoon.ttf”-找不到404(13毫秒)

为什么资产管道不将字体文件压缩为/ assets?

有什么想法的人吗?

亲切的问候,尼尔

额外信息:

当检查Rails控制台的资产路径和资产预编译时,我得到以下信息:

1.9.2p320 :001 > y Rails.application.config.assets.precompile
---
- !ruby/object:Proc {}
- !ruby/regexp /(?:\/|\\|\A)application\.(css|js)$/
- .svg
- .eot
- .woff
- .ttf
=> nil



1.9.2p320 :002 > y Rails.application.config.assets.paths
---
- /Users/neiltonge/code/neiltonge/app/assets/fonts
- /Users/neiltonge/code/neiltonge/app/assets/images
- /Users/neiltonge/code/neiltonge/app/assets/javascripts
- /Users/neiltonge/code/neiltonge/app/assets/stylesheets
- /Users/neiltonge/code/neiltonge/vendor/assets/images
- /Users/neiltonge/code/neiltonge/vendor/assets/javascripts
- /Users/neiltonge/code/neiltonge/vendor/assets/stylesheets
- /Users/neiltonge/.rvm/gems/ruby-1.9.2-p320@neiltonge/gems/jquery-rails-2.0.0/vendor/assets/javascripts
- /Users/neiltonge/.rvm/gems/ruby-1.9.2-p320@neiltonge/gems/coffee-rails-3.2.1/lib/assets/javascripts
- /Users/neiltonge/.rvm/gems/ruby-1.9.2-p320@neiltonge/gems/bourbon-1.3.0/app/assets/stylesheets
- !ruby/object:Pathname
  path: /Users/neiltonge/code/neiltonge/app/assets/fonts
 => nil

3
font-url在Rails的SCSS中有帮助。
Hauleth 2012年

不幸的是,这没有任何区别。因此,我的问题仍然存在
rctneil

我在stackoverflow.com/a/40898227/1197775上写了一种诊断和解决此问题的通用方法。
网站

Answers:


651
  1. 如果您的Rails版本介于> 3.1.0和之间< 4,请将字体放在以下任何文件夹中:

    • app/assets/fonts
    • lib/assets/fonts
    • vendor/assets/fonts


    对于Rails版本> 4必须将字体放在 app/assets/fonts文件夹中。

    注意:要将字体放在这些指定的文件夹之外,请使用以下配置:

    config.assets.precompile << /\.(?:svg|eot|woff|ttf)\z/

    对于Rails版本> 4.2建议将此配置添加到config/initializers/assets.rb

    但是,您也可以将其添加到config/application.rbconfig/production.rb

  2. 在CSS文件中声明字体:

    @font-face {
      font-family: 'Icomoon';
      src:url('icomoon.eot');
      src:url('icomoon.eot?#iefix') format('embedded-opentype'),
        url('icomoon.svg#icomoon') format('svg'),
        url('icomoon.woff') format('woff'),
        url('icomoon.ttf') format('truetype');
      font-weight: normal;
      font-style: normal;
    }

    确保字体的名称与声明的URL部分中的名称完全相同。大写字母和标点符号很重要。在这种情况下,字体应具有名称icomoon

  3. 如果使用的是萨斯或使用Rails更少> 3.1.0(你的CSS文件有.scss.less扩展名),然后更改url(...)在字体声明font-url(...)

    否则,您的CSS文件应具有扩展名.css.erb,字体声明应为url('<%= asset_path(...) %>')

    如果您使用的是Rails > 3.2.1,则可以使用font_path(...)代替asset_path(...)。该帮助程序做的事情完全相同,但是更加清楚。

  4. 最后,像在font-family部分中声明的那样,在CSS中使用字体。如果声明为大写,则可以这样使用:

    font-family: 'Icomoon';

36
您是否重新启动服务器?
Ashitaka 2012年

9
@NadeemYasin感谢您的评论,我遇到了同样的问题。文件名中包含连字符,当我删除文件名时,此处提出的解决方案起作用。
tsega 2013年

35
config.assets.precompile += %w( .svg .eot .woff .ttf )实际上是错误的,您需要添加一些与完整资产名称匹配的东西进行预编译。一个正则表达式为我工作:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
2013年

2
好吧,它现在对我有效。因此,根本不需要该行代码,或者设置此配置的方式取决于Rails版本(或其他版本)。@Jim已经说过他必须在第2步中删除配置,所以也许我们在这里遗漏了一些东西。伙计,在资产管道中使用字体应该更简单。
Ashitaka 2013年

3
步骤2应该删除。根据Rails指南config.assets.paths仅供链轮齿参考,此处不相关。config.assets.precompile也是没有用的,因为“用于编译文件的默认匹配器包括application / assets文件夹中的application.js,application.css和所有非JS / CSS文件(这将自动包括所有图像资产)”(请参见此处
EricL。

38

现在有一个转折:

您应该将所有字体放进去,app/assets/fonts/因为它们会在默认情况下在登台和生产时进行预编译-将它们推到heroku时将进行预编译。

字体文件放在vendor/assets上登台或生产被默认预编译-他们会在失败的Heroku资源!

@ plapier,thoughtbot / bourbon

我坚信将供应商字体放入vendor/assets/fonts 比加入字体有意义app/assets/fonts。通过这两行额外的配置,这对我来说效果很好(在Rails 4上):

app.config.assets.paths << Rails.root.join('vendor', 'assets', 'fonts')  
app.config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/

@ jhilden,thoughtbot /波旁威士忌

我也在上进行了测试rails 4.0.0。实际上,最后一行足以安全地从vendor文件夹中预编译字体。花了几个小时才弄清楚。希望它对某人有所帮助。


2
+ 1edgeguides.rubyonrails.org/…解释了资产管道的布局,并有助于了解其工作原理。正确截至
2014年

您都需要这两个吗?app.config.assets.paths << Rails.root.join('vendor', 'assets', 'fonts') app.config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/对另一个答案的评论说,后者可以同时解决这两个问题。
ahnbizcad 2015年

即使在Rails 4.2 + -land中,我也确实认为app/assets链轮和朋友的输入作为输出处理public/assets,而vendor/assets对于无需修改即可部署资产仍然很有用。都有自己的用例。整个销售惯例都以保证什么都不会发生为前提vendor/*。(是的,vendor/plugins在代码存储,滥用宝石狂热前的宝石时代被滥用,而人们只是将未版本化的js复制粘贴到了vendor/assets/javascriptsbower / rails资产之前。)

2
对于那些想知道的人;把它扔进config/initializers/assets.rb
TJ Biddle 2016年

23

如果不想跟踪字体移动:

# Adding Webfonts to the Asset Pipeline
config.assets.precompile << Proc.new { |path|
  if path =~ /\.(eot|svg|ttf|woff)\z/
    true
  end
}

1
我认为这是最好的解决方案。除非您创作了字体,否则它们可能属于/ vendor / assets / fonts而不是/ app / assets / fonts。这种方法可以同时解决这两个问题,但上述方法并不能解决
Casey 2013年

5
@Casey:此解决方案可让您将字体放入供应商/资产中。@Nathan Colgate:可以简化为:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/

@Sunny-我知道,这就是为什么我认为它比公认的答案更好的原因
Casey

2
你也应该结束与\ž您正则表达式- stackoverflow.com/questions/577653/...
卡西

1
您如何处理Rails附加到字体文件的哈希?
詹姆斯·麦克马洪

21

您需要font-url在@ font-face块中使用,而不是url

@font-face {
font-family: 'Inconsolata';
src:font-url('Inconsolata-Regular.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}

以及您提到的application.rb中的这一行(对于 app/assets/fonts

config.assets.paths << Rails.root.join("app", "assets", "fonts")

您还需要启用预编译以进行生产
ahnbizcad 2015年

在全新的Rails 4.2应用程序上,在中都包含src: url(someFont.ttf)src: font-url(someFont.ttf)时都可以使用app/assets/fonts.scss默认情况下,我有扩展程序。我不需要添加到config.assets.paths中。
Danny

9

这是我在资产管道中使用字体的方法:

1)将所有字体文件放在下app/assets/fonts/,实际上您不受限制地放在fonts文件夹名称下。您可以输入任何喜欢的子文件夹名称。例如app/assets/abcapp/assets/anotherfonts。但是我强烈建议您将其放在app/assets/fonts/更好的文件夹结构下。

2)从您的sass文件中,使用sass助手font-path来请求您的字体资源,如下所示

@font-face {
    font-family: 'FontAwesome';
    src: url(font-path('fontawesome-webfont.eot') + '?v=4.4.0');
    src: url(font-path('fontawesome-webfont.eot') + '?#iefix&v=4.4.0') format('embedded-opentype'),
         url(font-path('fontawesome-webfont.woff2') + '?v=4.4.0') format('woff2'),
         url(font-path('fontawesome-webfont.woff') + '?v=4.4.0') format('woff'),
         url(font-path('fontawesome-webfont.ttf') + '?v=4.4.0') format('truetype'),
         url(font-path('fontawesome-webfont.svg') + '?v=4.4.0#fontawesomeregular') format('svg');
    font-weight: normal;
    font-style: normal;
}

3)bundle exec rake assets:precompile从本地计算机运行,然后查看application.css结果。您应该会看到以下内容:

@font-face {
    font-family: 'FontAwesome';
    src: url("/assets/fontawesome-webfont-d4f5a99224154f2a808e42a441ddc9248ffe78b7a4083684ce159270b30b912a.eot" "?v=4.4.0");
    src: url("/assets/fontawesome-webfont-d4f5a99224154f2a808e42a441ddc9248ffe78b7a4083684ce159270b30b912a.eot" "?#iefix&v=4.4.0") format("embedded-opentype"), url("/assets/fontawesome-webfont-3c4a1bb7ce3234407184f0d80cc4dec075e4ad616b44dcc5778e1cfb1bc24019.woff2" "?v=4.4.0") format("woff2"), url("/assets/fontawesome-webfont-a7c7e4930090e038a280fd61d88f0dc03dad4aeaedbd8c9be3dd9aa4c3b6f8d1.woff" "?v=4.4.0") format("woff"), url("/assets/fontawesome-webfont-1b7f3de49d68b01f415574ebb82e6110a1d09cda2071ad8451bdb5124131a292.ttf" "?v=4.4.0") format("truetype"), url("/assets/fontawesome-webfont-7414288c272f6cc10304aa18e89bf24fb30f40afd644623f425c2c3d71fbe06a.svg" "?v=4.4.0#fontawesomeregular") format("svg");
    font-weight: normal;
    font-style: normal;
}

如果您想了解更多资产管道的工作方式,可以访问以下简单指南:https : //designcode.commandrun.com/rails-asset-pipeline-simple-guide-830e2e666f6c#.6lejlayk2


5

我在Rails 4.2(使用ruby 2.2.3)上遇到了这个问题,不得不编辑字体真棒的_paths.scss部分,以删除对引用的引用$fa-font-path并删除前导斜杠。以下是坏处:

@font-face {
  font-family: 'FontAwesome';
  src: font-url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}');
  src: font-url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'),
    font-url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'),
    font-url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'),
    font-url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'),
    font-url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg');
  font-weight: normal;
  font-style: normal;
}

和以下作品:

@font-face {
  font-family: 'FontAwesome';
  src: font-url('fontawesome-webfont.eot?v=#{$fa-version}');
  src: font-url('fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'),
    font-url('fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'),
    font-url('fontawesome-webfont.woff?v=#{$fa-version}') format('woff'),
    font-url('fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'),
    font-url('fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg');
  font-weight: normal;
  font-style: normal;
}

一种替代方法是简单地删除插值后的正斜杠$fa-font-path,然后将其定义$fa-font-path为空字符串或带有尾随正斜杠的子目录(根据需要)。

记住要重新编译资产并根据需要重新启动服务器。例如,在乘客设置上:

prompt> rake assets:clean; rake assets:clobber
prompt> RAILS_ENV=production RAILS_GROUPS=assets rake assets:precompile
prompt> service passenger restart

然后重新加载您的浏览器。


5

我使用的是Rails 4.2,无法显示合适的图标。显示了小方框,而不是折叠行中的(+)和我期望的小排序箭头。在研究了这里的信息之后,我对代码做了一个简单的更改:删除css中的字体目录。也就是说,像这样更改所有的css条目:

src:url('fonts/footable.eot');

看起来像这样:

src:url('footable.eot');

有效。我认为Rails 4.2已经假定了字体目录,因此在CSS代码中再次指定它会导致找不到字体文件。希望这可以帮助。


3

最近将Rails 3应用程序升级到Rails 4时,我遇到了类似的问题。我的字体不能在Rails 4+中正常工作,我们只能将字体保留在app/assets/fonts目录下。但是我的Rails 3应用程序具有不同的字体组织。因此,我必须配置该应用程序,以便它仍能与Rails 4+一起使用,而我的字体不在app/assets/fonts。我尝试了几种解决方案,但是找到非愚蠢的资产宝石后,它变得如此简单。

通过将以下行添加到您的Gemfile中来添加此gem:

gem 'non-stupid-digest-assets'

然后运行:

bundle install

最后在您的config / initializers / non_digest_assets.rb文件中添加以下行:

NonStupidDigestAssets.whitelist = [ /\.(?:svg|eot|woff|ttf)$/ ]

而已。这很好地解决了我的问题。希望这对遇到类似我的问题的人有所帮助。


3

这是一个回购,演示了如何在Heroku上使用Rails 5.2提供自定义字体。它进一步完善并根据https://www.webpagetest.org/优化了字体的投放速度。

https://github.com/nzoschke/edgecors

首先,我从上面的答案中挑选了一些片段。对于Rails 5.2+,您不需要额外的资产管道配置。

资产管道和SCSS

  • 放置字体 app/assets/fonts
  • @font-face声明放在scss文件中并使用font-url帮助器

来自app/assets/stylesheets/welcome.scss

@font-face {
  font-family: 'Inconsolata';
  src: font-url('Inconsolata-Regular.ttf') format('truetype');
  font-weight: normal;
  font-style: normal;
}

body {
  font-family: "Inconsolata";
  font-weight: bold;
}

通过CDS从CDN服务

我正在使用随Heroku Edge插件添加的CloudFront 。

首先在中配置CDN前缀和默认Cache-Controlproduction.rb

Rails.application.configure do
  # e.g. https://d1unsc88mkka3m.cloudfront.net
  config.action_controller.asset_host = ENV["EDGE_URL"]

  config.public_file_server.headers = {
    'Cache-Control' => 'public, max-age=31536000'
  }
end

如果您尝试从herokuapp.com URL到CDN URL访问字体,则会在浏览器中出现CORS错误:

通过CORS策略禁止从来源“ https://edgecors.herokuapp.com ” 访问“ https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf ” 上的字体:否'Access-Control-Allow -Origin'标头出现在请求的资源上。edgecors.herokuapp.com/获取https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf net :: ERR_FAILED

因此,将CORS配置为允许从Heroku到CDN URL访问字体:

module EdgeCors
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

    config.middleware.insert_after ActionDispatch::Static, Rack::Deflater

    config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins %w[
          http://edgecors.herokuapp.com
          https://edgecors.herokuapp.com
        ]
        resource "*", headers: :any, methods: [:get, :post, :options]
      end
    end
  end
end

提供gzip字体资产

资产管道会生成.ttf.gz文件,但不会提供文件。此猴子补丁将资产管道gzip白名单更改为黑名单:

require 'action_dispatch/middleware/static'

ActionDispatch::FileHandler.class_eval do
  private

    def gzip_file_path(path)
      return false if ['image/png', 'image/jpeg', 'image/gif'].include? content_type(path)
      gzip_path = "#{path}.gz"
      if File.exist?(File.join(@root, ::Rack::Utils.unescape_path(gzip_path)))
        gzip_path
      else
        false
      end
    end
end

最终结果是app/assets/fonts从长期存在的CloudFront缓存中提供了自定义字体文件。


2

在我的情况下,最初的问题是使用asset-url无结果而不是普通的urlCSS属性。使用asset-url最终在Heroku中为我工作。加上在/assets/fonts文件夹中设置字体并调用,asset-url('font.eot')而无需向其添加任何子文件夹或任何其他配置。


1

如果您有一个名为scaffolds.css.scss的文件,则可能会覆盖其他文件中正在执行的所有自定义操作。我注释掉了该文件,然后突然一切正常。如果该文件中没有任何重要内容,则最好将其删除!


-7

只需将字体放在app / assets / fonts文件夹中,并在应用程序开始时使用在application.rb中编写代码来设置自动加载路径

config.assets.paths << Rails.root.join(“ app”,“ assets”,“ fonts”)

然后在css中使用以下代码。

@ font-face {

 font-family: 'icomoon';
 src: asset-url('icomoon.eot');
 src: asset-url('icomoon.eot') format('embedded-opentype'),
      asset-url('icomoon.woff') format('woff'),
      asset-url('icomoon.ttf') format('truetype'),
      asset-url('icomoon.svg') format('svg');
 font-weight: normal;
 font-style: normal;

}

试试看。

谢谢


如何在现有答案之外添加任何内容?
cimmanon 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.