23

我在 rails 3 应用程序中使用font-awesome,在开发模式下一切正常,但是当我推送到 Heroku 时,Firefox 无法呈现图标,相反,我看到了这个:

在此处输入图像描述

  • Chrome 在开发和生产中呈现良好的图标
  • 这只会影响 FireFox(虽然我没有尝试过 IE)
  • 该应用程序在这里,如果有人能确认这不仅发生在我的机器上(帮助我排除本地主机缓存问题),我将不胜感激。
  • 所有资产,包括字体和样式表,都使用asset_sync gem 托管在S3 上。

这是我所做的:

在 font-awesome.css.scss 的顶部添加了以下内容:**

// font-awesome.css.scss
@font-face {
  font-family: 'FontAwesome';
  src: font-url("fontawesome-webfont.eot");
  src: font-url("fontawesome-webfont.eot?#iefix") format("eot"),
       font-url("fontawesome-webfont.woff") format("woff"),
       font-url("fontawesome-webfont.ttf") format("truetype"),
       font-url("fontawesome-webfont.svg#FontAwesome") format("svg");
  font-weight: normal;
  font-style: normal;
}

然后我把它放在 application.rb 中:

# application.rb
config.assets.paths << Rails.root.join("app", "assets", "fonts")
config.assets.precompile += %w( .svg .eot .woff .ttf )

最后,我将所有 4 个字体文件放在app/assets/fonts.

我真的很想知道我在这里做错了什么。

4

7 回答 7

25

这是我在 AWS 管理控制台中添加到我的存储桶以配置这个交叉事物的配置:

登录 AWS -> AWS 管理控制台 -> S3 -> 找到您的存储桶 -> 推送属性按钮(出于某种原因在纸上放大镜) -> 右侧的 Clic 权限 -> “编辑 CORS 配置”

<CORSConfiguration>
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Content-*</AllowedHeader>
        <AllowedHeader>Host</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

经过两个小时的研究...... :-(

于 2013-05-13T20:46:40.013 回答
13

我解决了我的问题。

这篇文章中,我了解到:

除非设置了某些特定的标头,否则 Firefox 会拒绝所有跨站点字体请求:

[即访问控制允许来源]

而且,从这篇文章

可悲的是,现在 S3 不允许您指定为您的对象提供服务的 Access-Control-Allow-Origin 标头

所以你有几个选择:

  1. 从应用程序的公共文件夹中提供字体,而不是从 S3
  2. 从 Rackspace 提供字体,您可以在其中设置标题
  3. 将字体作为Base64 字符串嵌入

我选择了第一个选项,因为这将是一个低流量站点,但这里有一篇很好的文章,介绍了如何从 Rackspace 提供字体,同时从 S3 提供所有其他资产。


更新:

亚马逊昨天宣布,他们现在支持跨域资源共享 (CORS),因此不再需要上面发布的解决方案。他们的开发者指南解释了更多。

于 2012-06-29T23:33:27.200 回答
6

Amazon S3 现在支持 CORS,您不再需要在 CSS 中嵌入 BASE64 字体(它会为您节省一些带宽:)

http://aws.amazon.com/about-aws/whats-new/2012/08/31/amazon-s3-announces-cross-origin-resource-sharing-CORS-support/

于 2012-09-02T16:08:44.333 回答
5

You can also use some rack middleware to serve the fonts directly with the required access-control headers to cloudfront.

# config/environment/production.rb

  # Rack Headers
  # Set HTTP Headers on static assets

  config.assets.header_rules = {
    :global => {'Cache-Control' => 'public, max-age=31536000'},
    :fonts  => {'Access-Control-Allow-Origin' => '*'}
  }
  require 'rack_headers'
  config.middleware.insert_before '::ActionDispatch::Static', '::Rack::Headers'

-----

# lib/rack_headers.rb

require 'rack/utils'

module Rack
  class Headers

    def initialize(app, options={})
      @app = app

      default_path = Rails.application.config.assets.prefix || '/assets'
      @asset_path = options.fetch(:path, default_path)

      default_rules = Rails.application.config.assets.header_rules || {}
      @rules = options.fetch(:header_rules, default_rules)
    end

    def call(env)
      dup._call(env)
    end

    def _call(env)
      status, @headers, response = @app.call(env)
      @path = ::Rack::Utils.unescape(env['PATH_INFO'])

      if @path.start_with?(@asset_path)
        set_headers
      end

      [status, @headers, response]
    end

    def set_headers
      @rules.each do |rule, headers|
        case rule
        when :global # Global
          set_header(headers)
        when :fonts  # Fonts Shortcut
          set_header(headers) if @path.match %r{\.(?:ttf|otf|eot|woff|svg)\z}
        when Array   # Extension/Extensions
          extensions = rule.join('|')
          set_header(result) if @path.match %r{\.(#{extensions})\z}
        when String  # Folder
          set_header(result) if
            (@path.start_with? rule || @path.start_with?('/' + rule))
        when Regexp  # Flexible Regexp
          set_header(result) if @path.match rule
        else
        end
      end
    end

    def set_header(headers)
      headers.each { |field, content| @headers[field] = content }
    end
  end
end

-----

This solution uses rules for setting different headers on every file based on rules. The rules are described here: https://github.com/thomasklemm/butler#providing-rules-for-setting-http-headers. Basically you can do anything with Regexps, but there are shortcuts for file endings, folders, web fonts and global headers.

于 2012-09-08T05:39:12.633 回答
1

只需在 s3 中添加整个存储桶的标头即可。

http://aws.typepad.com/aws/2012/08/amazon-s3-cross-origin-resource-sharing.html

于 2013-01-14T22:38:20.823 回答
1

您可以使用以下站点对字体进行 Base64 编码。尝试使用 FontSquirel 但它不允许您加密版权/购买的字体。

http://base64fonts.com/convert.php

于 2012-07-13T12:35:43.073 回答
0

此线程有更新。似乎无法通过将 cors.xml 文件上传到存储桶来设置 CORS。现在你必须点击它;)。这个线程在寻找解决方案时为我节省了一些时间,但另一方面,我在上传和更改 cors.xml 文件时浪费了一些时间。

当前的解决方案是单击存储桶的属性 > 权限 > 然后单击添加 CORS 配置

于 2014-06-06T15:24:06.330 回答