Utilizzo dei caratteri con la pipeline di asset Rails


345

Ho alcuni font configurati nel mio file Scss in questo modo:

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

Il file del font effettivo è archiviato in / app / assets / fonts /

Ho aggiunto config.assets.paths << Rails.root.join("app", "assets", "fonts")al mio file application.rb

e l'origine CSS di compilazione è la seguente:

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

Ma quando eseguo l'app, i file dei caratteri non vengono trovati. I registri:

Ha iniziato a OTTENERE "/assets/icoMoon.ttf" per 127.0.0.1 alle 2012-06-05 23:21:17 +0100 Asset pubblicato /icoMoon.ttf - 404 non trovato (13ms)

Perché la pipeline delle risorse non appiattisce i file dei caratteri in solo / assets?

Qualche idea gente?

Cordiali saluti, Neil

Informazioni extra:

Quando si controlla la console delle rotaie per i percorsi delle risorse e per la compilazione delle risorse ottengo quanto segue:

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

3
Hai font-urlaiutante in SCSS in Rails.
Hauleth,

Purtroppo non fa alcuna differenza. Pertanto la mia domanda è ancora
valida

Ho scritto un modo generico per diagnosticare e risolvere questo problema su stackoverflow.com/a/40898227/1197775 .
siti

Risposte:


651
  1. Se la tua versione di Rails è tra > 3.1.0e < 4, posiziona i tuoi caratteri in una di queste cartelle:

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


    Per le versioni di Rails > 4, è necessario posizionare i caratteri nella app/assets/fontscartella.

    Nota: per posizionare i caratteri al di fuori di queste cartelle designate, utilizzare la seguente configurazione:

    config.assets.precompile << /\.(?:svg|eot|woff|ttf)\z/

    Per le versioni di Rails > 4.2, si consiglia di aggiungere questa configurazione a config/initializers/assets.rb.

    Tuttavia, puoi anche aggiungerlo a config/application.rbo aconfig/production.rb

  2. Dichiara il tuo carattere nel tuo file 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;
    }

    Assicurati che il tuo font sia chiamato esattamente come nella parte URL della dichiarazione. Le lettere maiuscole e i segni di punteggiatura contano. In questo caso, il carattere dovrebbe avere il nome icomoon.

  3. Se stai usando Sass o Less with Rails > 3.1.0(il tuo file CSS ha .scsso .lessestensione), modifica il url(...)nella dichiarazione del carattere in font-url(...).

    Altrimenti, il tuo file CSS dovrebbe avere l'estensione .css.erbe la dichiarazione del carattere dovrebbe essere url('<%= asset_path(...) %>').

    Se stai usando Rails > 3.2.1, puoi usare font_path(...)invece di asset_path(...). Questo aiuto fa esattamente la stessa cosa ma è più chiaro.

  4. Infine, usa il tuo carattere nel tuo CSS come lo hai dichiarato nella font-familyparte. Se è stato dichiarato in maiuscolo, puoi usarlo in questo modo:

    font-family: 'Icomoon';

36
Hai riavviato il tuo server?
Ashitaka,

9
@NadeemYasin Grazie per il tuo commento, ho avuto lo stesso problema. I nomi dei file contenevano delle ipotesi e quando ho rimosso le soluzioni proposte qui funzionavano.
Tsega,

35
config.assets.precompile += %w( .svg .eot .woff .ttf )è effettivamente sbagliato, devi aggiungere per precompilare qualcosa che corrisponda al nome completo dell'asset. Una regexp ha funzionato per me:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Sunny

2
Bene, il modo in cui è ora funziona per me. Quindi o quella riga di codice non è affatto necessaria o il modo in cui impostare questa configurazione dipende dalla versione di Rails (o qualcos'altro). @Jim aveva già detto che doveva rimuovere le configurazioni al passaggio 2, quindi forse ci manca qualcosa qui. Amico, dovrebbe essere più semplice usare i caratteri con la pipeline delle risorse.
Ashitaka,

3
Il passaggio 2 dovrebbe essere rimosso. Secondo Rails Guides , config.assets.pathsè per i riferimenti Pignoni, non pertinente qui. config.assets.precompileè anche inutile perché "Il matcher predefinito per la compilazione dei file include application.js, application.css e tutti i file non JS / CSS (questo includerà automaticamente tutti gli asset di immagini) dalle cartelle app / asset" (vedi qui )
Eric L.

38

Ora ecco un colpo di scena:

È necessario posizionare tutti i font in app/assets/fonts/quanto SARANNO ottenere precompilato nella stadiazione e nella produzione di default-otterranno precompilato quando spinto a Heroku .

Font file inseriti in vendor/assetssarà NON essere precompilati sulla messa in scena o di produzione di default - verranno a mancare su Heroku . Fonte!

- @plapier, Thoughbot / Bourbon

Sono fermamente convinto che inserire i caratteri dei fornitori vendor/assets/fonts abbia molto più senso che inserirli app/assets/fonts. Con queste 2 linee di configurazione extra questo ha funzionato bene per me (su Rails 4):

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

- @jhilden, Thoughbot / Bourbon

L'ho anche provato rails 4.0.0. In realtà l'ultima riga è sufficiente per precompilare in modo sicuro i caratteri dalla vendorcartella. Ci sono voluti un paio d'ore per capirlo. Spero che abbia aiutato qualcuno.


2
+1 edgeguides.rubyonrails.org/… spiega il layout della pipeline degli asset e aiuta a capire come funziona. Corretto dal 04/07/2014
Zachary Moshansky

Ti servono entrambi? app.config.assets.paths << Rails.root.join('vendor', 'assets', 'fonts') app.config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/Un commento su un'altra risposta afferma che quest'ultimo si occupa di entrambi.
ahnbizcad,

Anche in Rails 4.2 + -land, penso davvero che l' app/assetsinput a pignoni e amici sia stato elaborato come output public/assets, mentre vendor/assetspuò comunque essere utile per distribuire risorse senza modifiche; entrambi hanno i loro casi d'uso. L'intera convenzione di vendita si basa sulla garanzia che non accadrà nulla vendor/*. (Sì, è vendor/pluginsstato abusato di accaparramento del codice, mania pre-nascosta nell'era pre gemma e gente ha appena copiato incollato js non esaminati in vendor/assets/javascriptspre-bower / rails-assets.)

2
Per quelli che si chiedono; buttalo dentroconfig/initializers/assets.rb
TJ Biddle,

23

Se non vuoi tenere traccia dello spostamento dei caratteri:

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

1
Penso che questa sia la soluzione migliore; a meno che tu non abbia creato i caratteri che probabilmente appartengono a / vendor / assets / fonts - non / app / assets / fonts. Questo approccio risolve per entrambi, quanto sopra non lo è
Casey,

5
@Casey: questa soluzione consente di inserire i caratteri all'interno del fornitore / delle risorse. @Nathan Colgate: questo può essere semplificato per:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Sunny

@Sunny - Lo so, è per questo che penso sia meglio della risposta accettata
Casey,

2
Inoltre dovresti terminare il tuo regex con \ Z - stackoverflow.com/questions/577653/…
Casey

1
Come gestisci gli hash che Rails aggiunge al file dei caratteri?
James McMahon,

21

È necessario utilizzare font-urlnel blocco @ font-face, nonurl

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

così come questa riga in application.rb, come hai detto (per i caratteri in app/assets/fonts

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

devi anche abilitare la precompilazione per la produzione
ahnbizcad

Su un marchio rotaie nuova 4.2 app, sia src: url(someFont.ttf)e src: font-url(someFont.ttf)lavorato quando avere i file in app/assets/fonts. Ho le .scssestensioni per impostazione predefinita. Non ho avuto bisogno di aggiungere a config.assets.paths.
Danny,

9

Ecco il mio approccio all'utilizzo dei caratteri nella pipeline delle risorse:

1) Metti tutti i tuoi file di font sotto app/assets/fonts/, in realtà non sei limitato a metterli sotto il fontsnome della cartella. Puoi inserire qualsiasi nome di sottocartella che ti piace. Ad esempio app/assets/abco app/assets/anotherfonts. Ma consiglio vivamente di metterlo sotto app/assets/fonts/per una migliore struttura delle cartelle.

2) Dal tuo file sass, usa l'helper sass font-pathper richiedere le tue risorse di font in questo modo

@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) Esegui bundle exec rake assets:precompiledal tuo computer locale e vedi il risultato application.css. Dovresti vedere qualcosa del genere:

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

Se vuoi sapere di più su come funziona la pipeline di risorse, puoi visitare la seguente semplice guida: https://designcode.commandrun.com/rails-asset-pipeline-simple-guide-830e2e666f6c#.6lejlayk2


5

Stavo riscontrando questo problema su Rails 4.2 (con ruby ​​2.2.3) e ho dovuto modificare il parziale _paths.scss font-awesome per rimuovere i riferimenti $fa-font-pathe rimuovere una barra. Si è rotto quanto segue:

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

E i seguenti lavori:

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

Un'alternativa sarebbe semplicemente rimuovere la barra in avanti seguendo quella interpolata $fa-font-pathe quindi definire $fa-font-pathcome stringa vuota o sottodirectory con barra in avanti (se necessario).

Ricorda di ricompilare le risorse e riavviare il server in base alle esigenze. Ad esempio, in una configurazione passeggero:

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

Quindi ricaricare il browser.


5

Sto usando Rails 4.2 e non sono riuscito a visualizzare le icone dei footable. Stavano mostrando delle piccole caselle, invece del (+) sulle righe compresse e le piccole frecce di ordinamento che mi aspettavo. Dopo aver studiato le informazioni qui, ho apportato una semplice modifica al mio codice: rimuovere la directory dei caratteri in CSS. Cioè, cambia tutte le voci CSS in questo modo:

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

assomigliare a questo:

src:url('footable.eot');

Ha funzionato. Penso che Rails 4.2 assuma già la directory dei font, quindi specificandola di nuovo nel codice CSS non si trovano i file dei font. Spero che questo ti aiuti.


3

Ho avuto un problema simile quando ho aggiornato di recente la mia app Rails 3 a Rails 4. I miei caratteri non funzionavano correttamente come in Rails 4+, ci è permesso solo di tenere i caratteri nella app/assets/fontsdirectory. Ma la mia app Rails 3 aveva un'organizzazione dei caratteri diversa. Quindi ho dovuto configurare l'app in modo che funzioni ancora con Rails 4+ con i miei caratteri in un posto diverso da app/assets/fonts. Ho provato diverse soluzioni, ma dopo aver trovato un gioiello non stupido-digest-asset , è diventato così facile.

Aggiungi questa gemma aggiungendo la seguente riga al tuo Gemfile:

gem 'non-stupid-digest-assets'

Quindi eseguire:

bundle install

E infine aggiungi la seguente riga nel tuo file config / initializer / non_digest_assets.rb :

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

Questo è tutto. Questo ha risolto bene il mio problema. Spero che questo aiuti qualcuno che ha riscontrato problemi simili come me.


3

Ecco un repository che dimostra di servire un font personalizzato con Rails 5.2 che funziona su Heroku. Va oltre e ottimizza il servizio dei font per essere il più veloce possibile secondo https://www.webpagetest.org/

https://github.com/nzoschke/edgecors

Per iniziare ho scelto pezzi dalle risposte sopra. Per Rails 5.2+ non dovresti aver bisogno di una configurazione extra della pipeline delle risorse.

Asset Pipeline e SCSS

  • Inserisci i caratteri in app/assets/fonts
  • Inserire la @font-facedichiarazione in un file scss e utilizzare l' font-urlhelper

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

Servire da CDN con CORS

Sto usando CloudFront, aggiunto con il componente aggiuntivo Heroku Edge .

Per prima cosa configura un prefisso CDN e le Cache-Controlintestazioni predefinite in 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

Se provi ad accedere al carattere dall'URL herokuapp.com all'URL CDN, visualizzerai un errore CORS nel tuo browser:

L'accesso al carattere in " https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf " dall'origine " https://edgecors.herokuapp.com " è stato bloccato dalla politica CORS: No "Access-Control-Allow -L'intestazione originale è presente sulla risorsa richiesta. edgecors.herokuapp.com/ OTTIENI https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf net :: ERR_FAILED

Quindi configurare CORS per consentire l'accesso al carattere da Heroku all'URL CDN:

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

Servi gzip Font Asset

La pipeline delle risorse crea un .ttf.gzfile ma non lo serve. Questa patch scimmia cambia la whitelist gzip della pipeline di asset in una lista nera:

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

Il risultato finale è un file di caratteri personalizzato app/assets/fontsservito da una cache CloudFront di lunga durata.


2

Nel mio caso la domanda originale stava usando asset-urlsenza risultati invece della semplice urlproprietà CSS. L'utilizzo ha asset-urlfinito per funzionare per me ad Heroku. Inoltre, imposta i caratteri nella /assets/fontscartella e chiama asset-url('font.eot')senza aggiungere alcuna sottocartella o altra configurazione.


1

Se hai un file chiamato scaffolds.css.scss, allora c'è una possibilità che sovrascriva tutte le cose personalizzate che stai facendo negli altri file. Ho commentato quel file e improvvisamente tutto ha funzionato. Se non c'è nulla di importante in quel file, potresti anche cancellarlo!


-7

basta inserire i caratteri all'interno della cartella app / assets / fonts e impostare il percorso di caricamento automatico quando l'app inizia a usare la scrittura del codice in application.rb

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

quindi utilizzare il seguente codice in CSS.

@ font-face {

 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;

}

Provaci.

Grazie


In che modo questo aggiunge qualcosa rispetto alle risposte esistenti?
cimmanon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.