Ruby-on-rails 在 Rails 资产管道中使用字体

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10905905/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 03:29:56  来源:igfitidea点击:

Using fonts with Rails asset pipeline

ruby-on-railssassasset-pipelinefont-faceassets

提问by rctneil

I have some fonts being configured in my Scss file like so:

我在 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');
}

The actual font file are stored in /app/assets/fonts/

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

I have added config.assets.paths << Rails.root.join("app", "assets", "fonts")to my application.rb file

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

and the compile CSS source is as follows:

编译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");
}

But when I run the app the font files are not being found. The logs:

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

Started GET "/assets/icoMoon.ttf" for 127.0.0.1 at 2012-06-05 23:21:17 +0100 Served asset /icoMoon.ttf - 404 Not Found (13ms)

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

Why isn't the asset pipeline flattening the font files down into just /assets?

为什么资产管道不将字体文件扁平化为 /assets?

Any ideas people?

有什么想法吗?

Kind regards, Neil

亲切的问候,尼尔

Extra info:

额外信息:

When checking the rails console for assets paths and assetprecompile I get the following:

在检查 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

回答by Ashitaka

  1. If your Rails version is between > 3.1.0and < 4, place your fonts in any of the these folders:

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


    For Rails versions > 4, you mustplace your fonts in the app/assets/fontsfolder.

    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 recommendedto add this configuration to config/initializers/assets.rb.

    However, you can also add it to either config/application.rb, or to config/production.rb

  2. 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.

  3. If you are using Sass or Less with Rails > 3.1.0(your CSS file has .scssor .lessextension), 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.

  4. Finally, use your font in your CSS like you declared it in the font-familypart. If it was declared capitalized, you can use it like this:

    font-family: 'Icomoon';
    
  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.rb, 或config/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. 最后,像您在font-family部分中声明的那样在 CSS 中使用您的字体。如果它被声明为大写,你可以像这样使用它:

    font-family: 'Icomoon';
    

回答by jibiel

Now here's a twist:

现在有一个转折:

You should place all fonts in app/assets/fonts/as they WILLget precompiled in staging and production by default—they will get precompiled when pushed to heroku.

Font files placed in vendor/assetswill NOTbe precompiled on staging or production by default — they will fail on heroku. Source!

您应该将所有字体放入其中,app/assets/fonts/因为它们在默认情况下在暂存和生产中预编译 - 当推送到heroku时,它们将被预编译。

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

@plapier, thoughtbot/bourbon

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

I strongly believe that putting vendor fonts into vendor/assets/fontsmakes a lot more sense than putting them into app/assets/fonts. With these 2 lines of extra configuration this has worked well for me (on Rails 4):

我坚信将供应商字体放入vendor/assets/fonts比将它们放入app/assets/fonts. 使用这 2 行额外配置,这对我来说效果很好(在 Rails 4 上):

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

@jhilden, thoughtbot/bourbon

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

I've also tested it on rails 4.0.0. Actually the last one line is enough to safely precompile fonts from vendorfolder. Took a couple of hours to figure it out. Hope it helped someone.

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

回答by Nathan Colgate

If you don't want to keep track of moving your fonts around:

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

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

回答by craic.com

You need to use font-urlin your @font-face block, not url

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

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

as well as this line in application.rb, as you mentioned (for fonts in app/assets/fonts

以及 application.rb 中的这一行,正如您所提到的(对于字体 app/assets/fonts

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

回答by Tim

Here my approach to using fonts in asset pipeline:

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

1) Put all your font file under app/assets/fonts/, actually you are not restricted to put it under fontsfolder name. You can put any subfolder name you like. E.g. app/assets/abcor app/assets/anotherfonts. But i highly recommend you put it under app/assets/fonts/for better folder structure.

1) 把你所有的字体文件放在 下app/assets/fonts/,实际上你不限于把它放在fonts文件夹名下。您可以输入任何您喜欢的子文件夹名称。例如app/assets/abcapp/assets/anotherfonts。但我强烈建议你把它放在下面app/assets/fonts/以获得更好的文件夹结构。

2) From your sass file, using the sass helper font-pathto request your font assets like this

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) Run bundle exec rake assets:precompilefrom your local machine and see your application.css result. You should see something like this:

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;
}

If you want to know more how asset pipeline work, you can visit the following simple guide: https://designcode.commandrun.com/rails-asset-pipeline-simple-guide-830e2e666f6c#.6lejlayk2

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

回答by markeissler

I was having this problem on Rails 4.2 (with ruby 2.2.3) and had to edit the font-awesome _paths.scss partial to remove references to $fa-font-pathand removing a leading forward slash. The following was broken:

我在 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;
}

And the following works:

以下工作:

@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;
}

An alternative would be to simply remove the forward slash following the interpolated $fa-font-pathand then define $fa-font-pathas an empty string or subdirectory with trailing forward slash (as needed).

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

Remember to recompile assets and restart your server as needed. For example, on a passenger setup:

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

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

Then reload your browser.

然后重新加载浏览器。

回答by Brian Doherty

I'm using Rails 4.2, and could not get the footable icons to show up. Little boxes were showing, instead of the (+) on collapsed rows and the little sorting arrows I expected. After studying the information here, I made one simple change to my code: remove the font directory in css. That is, change all the css entries like this:

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

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

to look like this:

看起来像这样:

src:url('footable.eot');

It worked. I think Rails 4.2 already assumes the font directory, so specifying it again in the css code makes the font files not get found. Hope this helps.

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

回答by K M Rakibul Islam

I had a similar issue when I upgraded my Rails 3 app to Rails 4 recently. My fonts were not working properly as in the Rails 4+, we are only allowed to keep the fonts under app/assets/fontsdirectory. But my Rails 3 app had a different font organization. So I had to configure the app so that it still works with Rails 4+ having my fonts in a different place other than app/assets/fonts. I have tried several solutions but after I found non-stupid-digest-assetsgem, it just made it so easy.

我最近将 Rails 3 应用程序升级到 Rails 4 时遇到了类似的问题。我的字体在 Rails 4+ 中无法正常工作,我们只允许将字体保存在app/assets/fonts目录下。但是我的 Rails 3 应用程序有不同的字体组织。所以我必须配置应用程序,以便它仍然适用于 Rails 4+,将我的字体放在app/assets/fonts. 我尝试了几种解决方案,但在我发现非愚蠢的消化资产gem 之后,它变得如此简单。

Add this gem by adding the following line to your Gemfile:

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

gem 'non-stupid-digest-assets'

Then run:

然后运行:

bundle install

And finally add the following line in your config/initializers/non_digest_assets.rbfile:

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

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

That's it. This solved my problem nicely. Hope this helps someone who have encountered similar problem like me.

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

回答by Noah Zoschke

Here is a repo the demonstrates serving a custom font with Rails 5.2 that works on Heroku. It goes further and optimizes serving the fonts to be as fast as possible according to https://www.webpagetest.org/

这是一个使用 Rails 5.2 为 Heroku 提供自定义字体的演示。根据https://www.webpagetest.org/,它进一步优化了字体的服务速度,使其尽可能快

https://github.com/nzoschke/edgecors

https://github.com/nzoschke/edgecors

To start I picked pieces from answers above. For Rails 5.2+ you shouldn't need extra asset pipeline config.

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

Asset Pipeline and SCSS

资产管道和 SCSS

  • Place fonts in app/assets/fonts
  • Place the @font-facedeclaration in an scss file and use the font-urlhelper
  • 将字体放入 app/assets/fonts
  • @font-face声明放在 scss 文件中并使用font-url帮助程序

From app/assets/stylesheets/welcome.scss:

来自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;
}

Serve from CDN with CORS

使用 CORS 从 CDN 提供服务

I'm using CloudFront, added with the Heroku Edge addon.

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

First configure a CDN prefix and default Cache-Controlheaders in production.rb:

首先在 中配置 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

If you try to access the font from the herokuapp.com URL to the CDN URL, you will get a CORS error in your browser:

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

Access to font at 'https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf' from origin 'https://edgecors.herokuapp.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. edgecors.herokuapp.com/ GET https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttfnet::ERR_FAILED

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.ttfnet::ERR_FAILED

So configure CORS to allow access to the font from Heroku to the CDN URL:

因此,配置 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

Serve gzip Font Asset

提供 gzip 字体资源

The asset pipeline builds a .ttf.gzfile but doesn't serve it. This monkey patch changes the asset pipeline gzip whitelist to a blacklist:

资产管道构建一个.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

The ultimate result is a custom font file in app/assets/fontsserved from a long-lived CloudFront cache.

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

回答by bartoindahouse

In my case the original question was using asset-urlwithout results instead of plain urlcss property. Using asset-urlended up working for me in Heroku. Plus setting the fonts in /assets/fontsfolder and calling asset-url('font.eot')without adding any subfolder or any other configuration to it.

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