我有一些字体被配置在我的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。加入(“应用程序”,“资产”,“字体”)到我的应用程序。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");
}

但当我运行应用程序的字体文件没有被发现。日志:

start GET "/assets/icoMoon.ttf" for 127.0.0.1 at 2012-06-05 23:21:17 +0100 已服务资产/icoMoon.ttf - 404 Not Found (13ms)

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

大家有什么想法吗?

亲切的问候, 尼尔。

额外信息:

当检查rails控制台的资产路径和assetprecompile时,我得到如下:

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

当前回答

如果你不想跟踪字体的移动:

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

其他回答

If your Rails version is between > 3.1.0 and < 4, place your fonts in any of the these folders: app/assets/fonts lib/assets/fonts vendor/assets/fonts For Rails versions > 4, you must place your fonts in the app/assets/fonts folder. Note: To place fonts outside of these designated folders, use the following configuration: config.assets.precompile << /\.(?:svg|eot|woff|ttf)\z/ For Rails versions > 4.2, it is recommended to add this configuration to config/initializers/assets.rb. However, you can also add it to either config/application.rb , or to config/production.rb Declare your font in your CSS file: @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; } Make sure your font is named exactly the same as in the URL portion of the declaration. Capital letters and punctuation marks matter. In this case, the font should have the name icomoon. If you are using Sass or Less with Rails > 3.1.0 (your CSS file has .scss or .less extension), then change the url(...) in the font declaration to font-url(...). Otherwise, your CSS file should have the extension .css.erb, and the font declaration should be url('<%= asset_path(...) %>'). If you are using Rails > 3.2.1, you can use font_path(...) instead of asset_path(...). This helper does exactly the same thing but it's more clear. Finally, use your font in your CSS like you declared it in the font-family part. If it was declared capitalized, you can use it like this: font-family: 'Icomoon';

如果你有一个叫做scaffold。css的文件。Scss,那么就有可能覆盖您在其他文件中所做的所有自定义操作。我把那个文件注释掉了,突然之间一切都正常了。如果那个文件里没有什么重要的东西,你还不如把它删掉!

如果你不想跟踪字体的移动:

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

这里有一个转折:

你应该把所有的字体放在app/assets/fonts/中,因为它们在默认情况下会在登台和生产中被预编译——当推送到heroku时,它们会被预编译。 默认情况下,放置在vendor/assets中的字体文件不会在登台或生产时预编译-它们将在heroku上失败。源!

- @plapier,以为机器人/波旁威士忌

我坚信把厂商字体放到厂商/资产/字体中 这比把它们放到app/assets/字体中更有意义。与 这两行额外的配置对我来说工作得很好 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上测试了它。实际上,最后一行已经足够从供应商文件夹安全预编译字体了。花了几个小时才弄明白。希望它能帮助到某人。

这里是一个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 /资产/样式表/ 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;
}

从CDN与CORS服务

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

首先在生产端配置CDN前缀和默认的Cache-Control头。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/ GET 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文件,但不为它服务。这个monkey补丁将资产管道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长期缓存提供。