353

我在我的 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 年 6 月 5 日 23:21:17 +0100 开始获取 127.0.0.1 的“/assets/icoMoon.ttf” 服务资产 /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
4

12 回答 12

660
  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 中使用 Sass 或 Less > 3.1.0(您的 CSS 文件具有.scss.less扩展名),则将url(...)字体声明中的font-url(...).

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

    如果您使用的是 Rails > 3.2.1,则可以font_path(...)使用asset_path(...). 这个助手做同样的事情,但更清楚。

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

    font-family: 'Icomoon';
    
于 2012-06-06T01:54:55.120 回答
38

现在有一个转折:

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

默认情况下,放置的字体文件vendor/assets不会在登台或生产中预编译——它们将在heroku上失败来源!

@plapier,思想机器人/波旁威士忌

我坚信将供应商字体放入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,思想机器人/波旁威士忌

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

于 2014-05-12T14:34:00.573 回答
23

如果您不想跟踪移动字体:

# Adding Webfonts to the Asset Pipeline
config.assets.precompile << Proc.new { |path|
  if path =~ /\.(eot|svg|ttf|woff)\z/
    true
  end
}
于 2013-06-28T14:36:47.597 回答
23

您需要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")
于 2014-05-22T17:40:25.840 回答
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

于 2015-11-24T11:44:29.283 回答
6

这是一个 repo,演示了在 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;
}

使用 CORS 从 CDN 提供服务

我正在使用 CloudFront,添加了Heroku Edge 插件

首先在中配置 CDN 前缀和默认Cache-Control标头production.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 错误:

从源“ https://edgecors.herokuapp.com ”访问“ https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf ”字体已被 CORS 策略阻止:否 '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 缓存中提供自定义字体文件。

于 2018-12-26T22:42:42.817 回答
5

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

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

看起来像这样:

src:url('footable.eot');

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

于 2015-03-23T16:31:03.113 回答
5

我在 Rails 4.2(使用 ruby​​ 2.2.3)上遇到了这个问题,并且不得不编辑 font-awesome _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

然后重新加载浏览器。

于 2015-12-15T21:48:14.760 回答
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)$/ ]

就是这样。这很好地解决了我的问题。希望这可以帮助像我一样遇到类似问题的人。

于 2014-07-24T16:27:53.467 回答
2

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

于 2016-04-27T15:56:10.060 回答
1

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

于 2013-05-27T13:05:45.223 回答
-6

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

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

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

@字体脸{

 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;

}

试试看。

谢谢

于 2015-04-20T12:37:25.357 回答