Utilisation de polices avec le pipeline d'actifs Rails

345

J'ai des polices configurées dans mon fichier Scss comme ceci:

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

Le fichier de police réel est stocké dans / app / assets / fonts /

J'ai ajouté config.assets.paths << Rails.root.join("app", "assets", "fonts")à mon fichier application.rb

et la source CSS de compilation est la suivante:

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

Mais lorsque j'exécute l'application, les fichiers de polices ne sont pas trouvés. Les journaux:

A commencé GET "/assets/icoMoon.ttf" pour 127.0.0.1 à 2012-06-05 23:21:17 +0100 Actif servi /icoMoon.ttf - 404 Not Found (13ms)

Pourquoi le pipeline d'actifs n'aplatit-il pas les fichiers de police en seulement / actifs?

Des idées des gens?

Cordialement, Neil

Informaitons supplémentaires:

Lorsque je vérifie la console des rails pour les chemins des actifs et la compilation des actifs, j'obtiens ce qui suit:

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
rctneil
la source
3
Vous avez une font-urlaide dans SCSS dans Rails.
Hauleth
Cela ne fait malheureusement aucune différence. Par conséquent, ma question est toujours
valable
J'ai écrit un moyen générique pour diagnostiquer et résoudre ce problème sur stackoverflow.com/a/40898227/1197775 .
sites

Réponses:

651
  1. Si votre version de Rails se situe entre > 3.1.0et < 4, placez vos polices dans l'un de ces dossiers:

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


    Pour les versions Rails > 4, vous devez placer vos polices dans le app/assets/fontsdossier.

    Remarque: Pour placer des polices en dehors de ces dossiers désignés, utilisez la configuration suivante:

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

    Pour les versions Rails > 4.2, il est recommandé d'ajouter cette configuration à config/initializers/assets.rb.

    Cependant, vous pouvez également l’ajouter soit config/application.rbàconfig/production.rb

  2. Déclarez votre police dans votre fichier 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;
    }

    Assurez-vous que votre police porte le même nom que dans la partie URL de la déclaration. Les majuscules et les signes de ponctuation sont importants. Dans ce cas, la police doit avoir le nom icomoon.

  3. Si vous utilisez Sass ou Less with Rails > 3.1.0(votre fichier CSS a .scssou une .lessextension), changez le url(...)dans la déclaration de police en font-url(...).

    Sinon, votre fichier CSS devrait avoir l'extension .css.erbet la déclaration de police devrait l'être url('<%= asset_path(...) %>').

    Si vous utilisez Rails > 3.2.1, vous pouvez utiliser font_path(...)au lieu deasset_path(...) . Cet assistant fait exactement la même chose mais c'est plus clair.

  4. Enfin, utilisez votre police dans votre CSS comme vous l'avez déclaré dans la font-familypartie. S'il a été déclaré en majuscule, vous pouvez l'utiliser comme ceci:

    font-family: 'Icomoon';
Ashitaka
la source
36
Avez-vous redémarré votre serveur?
Ashitaka
9
@NadeemYasin Merci pour votre commentaire, j'ai eu le même problème. Les noms de fichiers avaient des hypens et quand j'ai supprimé que les solutions proposées ici ont fonctionné.
tsega
35
config.assets.precompile += %w( .svg .eot .woff .ttf )est en fait faux, vous devez ajouter pour précompiler quelque chose qui correspond au nom complet de l'actif. Un regexp a fonctionné pour moi:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Sunny
2
Eh bien, la façon dont cela fonctionne maintenant pour moi. Donc, soit cette ligne de code n'est pas nécessaire du tout, soit la façon de définir cette configuration dépend de la version de Rails (ou autre chose). @Jim avait déjà dit qu'il devait supprimer les configurations à l'étape 2, alors peut-être que nous manquons quelque chose ici. Man, il devrait être plus simple d'utiliser des polices avec le pipeline d'actifs.
Ashitaka
3
L'étape 2 doit être supprimée. Selon Rails Guides , config.assets.pathsest pour les références Sprockets, non pertinent ici. config.assets.precompileest également inutile parce que "Le matcher par défaut pour la compilation des fichiers comprend application.js, application.css et tous les fichiers non JS / CSS (cela inclura automatiquement tous les actifs d'image) des dossiers app / assets" (voir ici )
Eric L.
38

Maintenant, voici une torsion:

Vous devez placer toutes les polices en app/assets/fonts/car ils VONT se précompilés dans la mise en scène et la production par défaut, ils seront poussés à précompilés quand heroku .

Les fichiers de polices placés vendor/assetsne seront PAS précompilés lors de la mise en scène ou de la production par défaut - ils échoueront sur Heroku . La source!

- @plapier, penséebot / bourbon

Je suis convaincu que la mise en place de polices de fournisseurs vendor/assets/fonts est beaucoup plus logique que leur mise en place app/assets/fonts. Avec ces 2 lignes de configuration supplémentaire, cela a bien fonctionné pour moi (sur Rails 4):

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

- @jhilden, penséebot / bourbon

Je l'ai également testé sur rails 4.0.0. En fait, la dernière ligne est suffisante pour précompiler en toute sécurité les polices à partir du vendordossier. Il a fallu quelques heures pour le comprendre. J'espère que cela a aidé quelqu'un.

jibiel
la source
2
+1 edgeguides.rubyonrails.org/… explique la disposition du pipeline d'actifs et aide à comprendre comment cela fonctionne. Correct à compter du 2014-07-04
Zachary Moshansky
Avez-vous besoin des deux? app.config.assets.paths << Rails.root.join('vendor', 'assets', 'fonts') app.config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/Un commentaire sur une autre réponse indique que ce dernier s'occupe des deux.
ahnbizcad
Même dans Rails 4.2 + -land, je pense vraiment que l' app/assetsentrée des sprockets et des amis est traitée comme une sortie public/assets, alors qu'elle vendor/assetspeut toujours être utile pour déployer des actifs sans modification; les deux ont leurs cas d'utilisation. Toute la convention de vente repose sur la garantie que rien ne se passera vendor/*. (Oui, a vendor/pluginsété abusé avec la thésaurisation de code, l'ère pré-maniaque de la manie à source fermée et les gens viennent de copier-coller les js non versionnés dans vendor/assets/javascriptsles actifs de pré-bower / rails.)
2
Pour ceux qui se demandent; jeter ceciconfig/initializers/assets.rb
TJ Biddle
23

Si vous ne souhaitez pas suivre le déplacement de vos polices:

# Adding Webfonts to the Asset Pipeline
config.assets.precompile << Proc.new { |path|
  if path =~ /\.(eot|svg|ttf|woff)\z/
    true
  end
}
Nathan Colgate
la source
1
Je pense que c'est la meilleure solution; sauf si vous avez créé les polices auxquelles elles appartiennent probablement dans / vendor / assets / fonts - pas / app / assets / fonts. Cette approche résout les deux, ce qui précède ne le fait pas
Casey
5
@Casey: cette solution vous permet de mettre des polices dans le fournisseur / actifs. @Nathan Colgate: Cela peut être simplifié comme suit:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Sunny
@Sunny - Je sais, c'est pourquoi je pense que c'est mieux que la réponse acceptée
Casey
2
Vous devez également terminer votre expression régulière avec \ Z - stackoverflow.com/questions/577653/…
Casey
1
Comment gérez-vous les hachages que Rails ajoute au fichier de police?
James McMahon
21

Vous devez utiliser font-urldans votre bloc @ font-face, pasurl

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

ainsi que cette ligne dans application.rb, comme vous l'avez mentionné (pour les polices app/assets/fonts

config.assets.paths << Rails.root.join("app", "assets", "fonts")
craic.com
la source
vous devez également activer la précompilation pour la production
ahnbizcad
Sur une toute nouvelle application rails 4.2, à la fois src: url(someFont.ttf)et a src: font-url(someFont.ttf)fonctionné lorsque des fichiers sont entrés app/assets/fonts. J'ai des .scssextensions par défaut. Je n'avais pas besoin d'ajouter aux config.assets.paths.
Danny
9

Voici mon approche de l'utilisation des polices dans le pipeline d'actifs:

1) Mettez tout votre fichier de polices sous app/assets/fonts/, en fait vous n'êtes pas limité à le mettre sous fontsle nom du dossier. Vous pouvez mettre n'importe quel nom de sous-dossier que vous aimez. Par exemple app/assets/abcou app/assets/anotherfonts. Mais je vous recommande fortement de le mettre sous app/assets/fonts/pour une meilleure structure de dossiers.

2) À partir de votre fichier sass, utilisez l'assistant sass font-pathpour demander vos ressources de police comme ceci

@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) Exécutez à bundle exec rake assets:precompilepartir de votre ordinateur local et voyez le résultat de votre application.css. Vous devriez voir quelque chose comme ceci:

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

Si vous souhaitez en savoir plus sur le fonctionnement du pipeline d'actifs, vous pouvez visiter le guide simple suivant: https://designcode.commandrun.com/rails-asset-pipeline-simple-guide-830e2e666f6c#.6lejlayk2

Tim
la source
5

J'avais ce problème sur Rails 4.2 (avec ruby ​​2.2.3) et j'ai dû éditer le partiel _paths.scss de font-awesome pour supprimer les références $fa-font-pathet supprimer une barre oblique avant. Ce qui suit était cassé:

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

Et les œuvres suivantes:

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

Une alternative serait de simplement supprimer la barre oblique suivant l'interpolation $fa-font-pathpuis de définir$fa-font-path comme une chaîne vide ou un sous-répertoire avec une barre oblique finale (si nécessaire).

N'oubliez pas de recompiler les actifs et de redémarrer votre serveur si nécessaire. Par exemple, sur une configuration passager:

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

Rechargez ensuite votre navigateur.

markeissler
la source
5

J'utilise Rails 4.2 et je n'ai pas pu afficher les icônes de bas de page. De petites boîtes apparaissaient, au lieu du (+) sur les lignes effondrées et des petites flèches de tri que j'attendais. Après avoir étudié les informations ici, j'ai apporté une modification simple à mon code: supprimer le répertoire des polices dans css. Autrement dit, changez toutes les entrées css comme ceci:

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

ressembler à ceci:

src:url('footable.eot');

Ça a marché. Je pense que Rails 4.2 assume déjà le répertoire des polices, donc en le spécifiant à nouveau dans le code CSS, les fichiers de polices ne sont pas trouvés. J'espère que cela t'aides.

Brian Doherty
la source
3

J'ai eu un problème similaire lorsque j'ai récemment mis à niveau mon application Rails 3 vers Rails 4. Mes polices ne fonctionnaient pas correctement comme dans Rails 4+, nous ne sommes autorisés à conserver les polices que dans le app/assets/fontsrépertoire. Mais mon application Rails 3 avait une organisation de polices différente. J'ai donc dû configurer l'application pour qu'elle fonctionne toujours avec Rails 4+ ayant mes polices dans un autre endroit que app/assets/fonts. J'ai essayé plusieurs solutions mais après avoir trouvé des actifs non-stupides bijou d' , cela a rendu les choses si faciles.

Ajoutez cette gemme en ajoutant la ligne suivante à votre Gemfile:

gem 'non-stupid-digest-assets'

Exécutez ensuite:

bundle install

Et enfin, ajoutez la ligne suivante dans votre fichier config / initializers / non_digest_assets.rb :

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

C'est ça. Cela a bien résolu mon problème. J'espère que cela aide quelqu'un qui a rencontré un problème similaire comme moi.

KM Rakibul Islam
la source
3

Voici un dépôt qui illustre le fait de servir une police personnalisée avec Rails 5.2 qui fonctionne sur Heroku. Il va plus loin et optimise la diffusion des polices le plus rapidement possible selon https://www.webpagetest.org/

https://github.com/nzoschke/edgecors

Pour commencer, j'ai choisi des morceaux des réponses ci-dessus. Pour Rails 5.2+, vous ne devriez pas avoir besoin d'une configuration de pipeline d'actifs supplémentaire.

Pipeline d'actifs et SCSS

  • Placer les polices dans app/assets/fonts
  • Placez la @font-facedéclaration dans un fichier scss et utilisez l' font-urlaide

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

Servir à partir de CDN avec CORS

J'utilise CloudFront, ajouté avec l' addon Heroku Edge .

Configurez d'abord un préfixe CDN et des en- Cache-Controltêtes par défaut dans 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

Si vous essayez d'accéder à la police de l'URL herokuapp.com à l'URL CDN, vous obtiendrez une erreur CORS dans votre navigateur:

L'accès à la police sur ' https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf ' depuis l'origine ' https://edgecors.herokuapp.com ' a été bloqué par la politique CORS: pas de 'Access-Control-Allow -En-tête d'origine est présent sur la ressource demandée. edgecors.herokuapp.com/ GET https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf net :: ERR_FAILED

Configurez donc CORS pour autoriser l'accès à la police de Heroku à l'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

Serve gzip Font Asset

Le pipeline d'actifs crée un .ttf.gzfichier mais ne le sert pas. Ce patch de singe change la liste blanche gzip du pipeline d'actifs en liste noire:

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

Le résultat final est un fichier de police personnalisé app/assets/fontsservi à partir d'un cache CloudFront de longue durée.

Noah Zoschke
la source
2

Dans mon cas, la question d'origine utilisait asset-urlsans résultats au lieu de la urlpropriété CSS simple . L'utilisation a asset-urlfini par fonctionner pour moi dans Heroku. De plus, définir les polices dans le /assets/fontsdossier et appeler asset-url('font.eot')sans y ajouter de sous-dossier ni aucune autre configuration.

Bartoindahouse
la source
1

Si vous avez un fichier appelé scaffolds.css.scss, il y a une chance qui remplace toutes les choses personnalisées que vous faites dans les autres fichiers. J'ai commenté ce fichier et tout a soudainement fonctionné. S'il n'y a rien d'important dans ce fichier, vous pouvez aussi bien le supprimer!

katfa
la source
-7

placez simplement vos polices dans le dossier app / assets / fonts et définissez le chemin de chargement automatique lorsque l'application commence à écrire le code dans application.rb

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

puis utilisez le code suivant dans 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;

}

Essaie.

Merci

Shoaib Malik
la source
Comment cela ajoute-t-il quelque chose aux réponses existantes?
cimmanon