2012-06-29 13 views
23

Sto usando font-awesome in un'applicazione rails 3, e tutto è ok in modalità sviluppo, ma quando spingo su Heroku, Firefox non riesce a rendere le icone, e invece , vedo questo:Rails 3, @ font-face fallendo in produzione con firefox

enter image description here

  • Chrome rende le icone fini dello sviluppo e della produzione
  • questo influisce solo Firefox (anche se non ho provato IE)
  • L'applicazione è here, io apprezzare se qualcuno potrebbe confermare che questo non sta accadendo solo sulla mia macchina (per aiutarmi a escludere un problema di cache nella cache locale).
  • Tutte le risorse, inclusi font e fogli di stile, sono ospitate su S3, utilizzando la gemma asset_sync.

Ecco che cosa ho fatto:

aggiunto il seguente alla parte superiore del 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; 
} 

Poi ho messo questo in applicazione. RB:

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

Finalmente ho messo tutti i 4 file di font in app/assets/fonts.

Mi piacerebbe davvero sapere cosa sto facendo male qui.

risposta

13

Ho risolto il problema.

Da this article, ho imparato che:

Firefox rifiuta tutte le richieste di font cross-site a meno che non si trovano alcune intestazioni specifiche:

[vale a dire Access-Control-Allow-Origin]

E, da this article:

Purtroppo, in questo momento S3 non consente di specificare l'intestazione Access-Control-Allow-Origin che gli oggetti ottengono servito con

Così avete alcune opzioni:

  1. servire i font dalla cartella pubblica della tua app, non f rom S3
  2. Servire i font da Rackspace, dove è possibile impostare le intestazioni
  3. incorporare il font nel vostro come Base64 string

Sono andato con la prima opzione dal momento che questo sta andando essere un sito a basso traffico, ma ecco una bella recensione su come serve fonts from Rackspace mentre contemporaneamente serve tutte le altre risorse da S3.


UPDATE:

Amazon announced yesterday che ora supportano Croce Origin Resource Sharing (CORS), per cui la soluzione postato sopra non dovrebbe più essere necessario. Loro developer guide spiega di più.

+0

sto affrontando lo stesso problema, tranne che la mia domanda è ospitato su Heroku? i caratteri si caricano su chrome, chromium, safari ma non su firefox e IE8. potresti per favore indicarmi la direzione giusta per risolvere il problema? sto usando rails 4, BS 3 con font fantastico. Grazie. –

1

È possibile utilizzare il seguente sito per Base64 codificare un carattere. Provato con FontSquirel ma non ti consente di crittografare i font protetti da copyright/acquistati.

http://base64fonts.com/convert.php

+0

grazie, è un buon consiglio :) – stephenmurdoch

5

È inoltre possibile utilizzare alcuni middleware rack per servire i font direttamente con le intestazioni di controllo degli accessi necessarie per il 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 

----- 

Questa soluzione utilizza regole per l'impostazione di diverse intestazioni su ogni file in base alle regole. Le regole sono descritte qui: https://github.com/thomasklemm/butler#providing-rules-for-setting-http-headers. Fondamentalmente puoi fare qualsiasi cosa con Regexps, ma ci sono scorciatoie per terminazioni di file, cartelle, caratteri web e intestazioni globali.

+0

Un bel suggerimento, grazie anche per il collegamento - maggiordomo sembra una gemma molto utile – stephenmurdoch

+1

L'implementazione di Rack :: File non ha funzionato Permettere di impostare intestazioni HTTP personalizzate fino a molto tempo fa. È stato appena accettato un commit che introduce questa funzionalità, ma non esiste ancora una versione ufficiale (sarà in 1.4.2+). Mi aspetto che ActionDispatch :: Static di Rails abbia la funzionalità per aggiungere intestazioni personalizzate e poi un flag 'config.assets.http_header_rules = {}'. –

25

Questa è la configurazione ho aggiunto al mio secchio in console di gestione AWS per configurare questa cosa croce:

Accedere a AWS -> AWS Management Console -> S3 -> Trova la tua Bucket - > pulsante proprietà push (lente d'ingrandimento su carta per qualche motivo) -> Autorizzazioni Clic sul lato destro -> "Modifica configurazione CORS"

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

Dopo due ore di ricerche ... :-(

+2

Se ti fa sentire meglio, mi hai appena salvato due ore. Grazie! – kateray

+3

Se ti fa sentire meglio, ho sprecato tre giorni su questo. Grazie! – Hopstream

+0

come farlo in rotaie –

0

C'è un aggiornamento a questa discussione. Sembra che non sia possibile impostare CORS caricando il file cors.xml in un bucket. Ora devi FARE CLIC SU;). Questo thread mi ha salvato un po 'di tempo mentre cercavo una soluzione, ma d'altra parte ho perso un po' di tempo per caricare e modificare il file cors.xml.

La soluzione attuale è quella di cliccare sulle proprietà di un secchio> permissons> e quindi fare clic su Aggiungi configurazione CORS

Problemi correlati