Usar fuentes con la canalización de activos de Rails

345

Tengo algunas fuentes configuradas en mi archivo Scss así:

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

El archivo de fuente real se almacena en / app / assets / fonts /

He agregado config.assets.paths << Rails.root.join("app", "assets", "fonts")a mi archivo application.rb

y la fuente de compilación CSS es la siguiente:

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

Pero cuando ejecuto la aplicación, no se encuentran los archivos de fuente. Los registros:

Comenzó GET "/assets/icoMoon.ttf" para 127.0.0.1 en 2012-06-05 23:21:17 +0100 Activo servido /icoMoon.ttf - 404 no encontrado (13 ms)

¿Por qué la canalización de activos no aplana los archivos de fuentes en solo / assets?

¿Alguna idea de personas?

Saludos cordiales, Neil

Información extra:

Al verificar la consola de rails para las rutas de los activos y la compilación de activos, obtengo lo siguiente:

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
fuente
3
Tienes font-urlayudante en SCSS en Rails.
Hauleth
Desafortunadamente, eso no hace ninguna diferencia. Por lo tanto, mi pregunta sigue en pie
rctneil 05 de
Escribí una forma genérica de diagnosticar y resolver este problema en stackoverflow.com/a/40898227/1197775 .
sitios

Respuestas:

651
  1. Si su versión de Rails está entre > 3.1.0y < 4, coloque sus fuentes en cualquiera de estas carpetas:

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


    Para las versiones de Rails > 4, usted debe colocar sus fuentes en la app/assets/fontscarpeta.

    Nota: Para colocar fuentes fuera de estas carpetas designadas, use la siguiente configuración:

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

    Para las versiones de Rails > 4.2, se recomienda agregar esta configuración a config/initializers/assets.rb.

    Sin embargo, también puede agregarlo a cualquiera config/application.rb oconfig/production.rb

  2. Declara tu fuente en tu archivo 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;
    }

    Asegúrese de que su fuente tenga el mismo nombre que en la parte de URL de la declaración. Las letras mayúsculas y los signos de puntuación son importantes. En este caso, la fuente debe tener el nombreicomoon .

  3. Si está utilizando Sass o Less con Rails > 3.1.0(su archivo CSS tiene .scsso.less extensión), cambie el url(...)en la declaración de fuente a font-url(...).

    De lo contrario, su archivo CSS debería tener la extensión .css.erb y la declaración de fuente debería ser url('<%= asset_path(...) %>').

    Si está utilizando Rails > 3.2.1, puede usar en font_path(...)lugar deasset_path(...) . Este ayudante hace exactamente lo mismo pero es más claro.

  4. Finalmente, use su fuente en su CSS como lo declaró en la font-familyparte. Si se declaró en mayúscula, puede usarlo así:

    font-family: 'Icomoon';
Ashitaka
fuente
36
¿Reiniciaste tu servidor?
Ashitaka
99
@NadeemYasin Gracias por tu comentario, tuve el mismo problema. Los nombres de los archivos tenían hipensos y cuando eliminé las soluciones propuestas aquí funcionaron.
tsega
35
config.assets.precompile += %w( .svg .eot .woff .ttf )está realmente mal, debe agregar para precompilar algo que coincida con el nombre completo del activo. Una expresión regular funcionó para mí:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Sunny
2
Bueno, la forma en que es ahora funciona para mí. Entonces, o esa línea de código no es necesaria o la forma de establecer esta configuración depende de la versión de Rails (o algo más). @Jim ya había dicho que tenía que eliminar las configuraciones en el paso 2, así que tal vez nos falta algo aquí. Hombre, debería ser más simple usar fuentes con la canalización de activos.
Ashitaka
3
El paso 2 debe ser eliminado. De acuerdo con Rails Guides , config.assets.pathses para referencias de Sprockets, no relevante aquí. config.assets.precompiletambién es inútil porque "El comparador predeterminado para compilar archivos incluye application.js, application.css y todos los archivos que no sean JS / CSS (esto incluirá todos los activos de imagen automáticamente) de las carpetas de aplicaciones / activos" (ver aquí )
Eric L.
38

Ahora aquí hay un giro:

Usted debe colocar todas las fuentes app/assets/fonts/, ya que SE consiguen precompilado en la estadificación y la producción de forma predeterminada, se conseguirán precompiled cuando se empuja a heroku .

Fuente archivos colocados en vendor/assetsse NO ser precompilado de ensayo o de producción por defecto - estos fallan en heroku . ¡Fuente!

- @plapier, thoughtbot / bourbon

Creo firmemente que poner las fuentes de los proveedores vendor/assets/fonts tiene mucho más sentido que ponerlas app/assets/fonts. Con estas 2 líneas de configuración adicional, esto me ha funcionado bien (en Rails 4):

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

- @jhilden, thoughtbot / bourbon

También lo he probado rails 4.0.0. En realidad, la última línea es suficiente para precompilar de forma segura las fuentes de la vendorcarpeta. Tomó un par de horas para resolverlo. Espero que haya ayudado a alguien.

jibiel
fuente
2
+1 edgeguides.rubyonrails.org/… explica el diseño de la canalización de activos y ayuda a comprender cómo funciona esto. Correcto a partir del 2014-07-04
Zachary Moshansky
¿Necesitas ambos? app.config.assets.paths << Rails.root.join('vendor', 'assets', 'fonts') app.config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/Un comentario sobre otra respuesta dice que esta última se encarga de ambas.
ahnbizcad
Incluso en Rails 4.2 + -land, realmente creo que la app/assetsentrada a los piñones y amigos procesados ​​como salida public/assets, mientras vendor/assetsque todavía puede ser útil para desplegar activos sin modificación; ambos tienen sus casos de uso. Toda la convención de venta se basa en la garantía de que no sucederá nada vendor/*. (Sí, vendor/pluginsfue abusado con el acaparamiento de códigos, la era pre-manía de código cerrado y la gente simplemente copió y pegó js no versionados envendor/assets/javascripts pre-Bower / carriles-activos.)
2
Para aquellos que se preguntan; tirar estoconfig/initializers/assets.rb
TJ Biddle
23

Si no desea realizar un seguimiento del movimiento de sus fuentes:

# Adding Webfonts to the Asset Pipeline
config.assets.precompile << Proc.new { |path|
  if path =~ /\.(eot|svg|ttf|woff)\z/
    true
  end
}
Nathan Colgate
fuente
1
Creo que esta es la mejor solución; a menos que haya creado las fuentes, probablemente pertenezcan a / vendor / assets / fonts - not / app / assets / fonts. Este enfoque resuelve para ambos, lo anterior no
Casey
55
@Casey: esta solución le permite poner fuentes dentro de proveedores / activos. @Nathan Colgate: Esto se puede simplificar a:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Soleado
@Sunny - Lo sé, por eso creo que es mejor que la respuesta aceptada
Casey
2
También debe finalizar su expresión regular con \ Z - stackoverflow.com/questions/577653/…
Casey
1
¿Cómo manejas los hashes que Rails agrega al archivo de fuente?
James McMahon el
21

Debe usar font-urlen su bloque @ font-face, nourl

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

así como esta línea en application.rb, como mencionaste (para fuentes en app/assets/fonts

config.assets.paths << Rails.root.join("app", "assets", "fonts")
craic.com
fuente
también necesita habilitar la precompilación para la producción
ahnbizcad
En un nuevo carriles 4.2 aplicación, tanto src: url(someFont.ttf)y src: font-url(someFont.ttf)trabajado al tener los archivos en app/assets/fonts. Tengo .scssextensiones por defecto. No necesitaba agregar a config.assets.paths.
Danny
9

Aquí mi enfoque para usar fuentes en la cartera de activos:

1) Ponga todo su archivo de fuente debajo app/assets/fonts/, en realidad no está restringido a ponerlo bajo el fontsnombre de la carpeta. Puede poner cualquier nombre de subcarpeta que desee. Por ejemplo app/assets/abco app/assets/anotherfonts. Pero le recomiendo que lo ponga app/assets/fonts/para una mejor estructura de carpetas.

2) Desde su archivo sass, usando el ayudante sass font-pathpara solicitar sus recursos de fuente como este

@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) Ejecute bundle exec rake assets:precompiledesde su máquina local y vea el resultado de su application.css. Debería ver algo como esto:

@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 desea saber más sobre cómo funciona la canalización de activos, puede visitar la siguiente guía simple: https://designcode.commandrun.com/rails-asset-pipeline-simple-guide-830e2e666f6c#.6lejlayk2

Tim
fuente
5

Estaba teniendo este problema en Rails 4.2 (con ruby ​​2.2.3) y tuve que editar el font-awesome _paths.scss parcial para eliminar referencias $fa-font-pathy eliminar una barra diagonal delantera. Lo siguiente estaba roto:

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

Y lo siguiente funciona:

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

Una alternativa sería simplemente eliminar la barra diagonal después de la interpolada $fa-font-pathy luego definir$fa-font-path como una cadena vacía o subdirectorio con la barra diagonal posterior (según sea necesario).

Recuerde volver a compilar activos y reiniciar su servidor según sea necesario. Por ejemplo, en una configuración de pasajero:

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

Luego vuelva a cargar su navegador.

markeissler
fuente
5

Estoy usando Rails 4.2, y no pude mostrar los íconos de footable. Se mostraban pequeñas cajas, en lugar del (+) en las filas colapsadas y las pequeñas flechas de clasificación que esperaba. Después de estudiar la información aquí, hice un cambio simple en mi código: eliminar el directorio de fuentes en css. Es decir, cambie todas las entradas de CSS como esta:

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

para lucir así:

src:url('footable.eot');

Funcionó. Creo que Rails 4.2 ya asume el directorio de fuentes, por lo que especificarlo nuevamente en el código CSS hace que no se encuentren los archivos de fuentes. Espero que esto ayude.

Brian Doherty
fuente
3

Tuve un problema similar cuando actualicé mi aplicación Rails 3 a Rails 4 recientemente. Mis fuentes no funcionaban correctamente como en Rails 4+, solo se nos permite mantener las fuentes en el app/assets/fontsdirectorio. Pero mi aplicación Rails 3 tenía una organización de fuentes diferente. Así que tuve que configurar la aplicación para que todavía funcione con Rails 4+ teniendo mis fuentes en un lugar diferente que no sea app/assets/fonts. He intentado varias soluciones, pero después de encontrar una gema no estúpida de digest-assets , me lo hizo muy fácil.

Agregue esta gema agregando la siguiente línea a su Gemfile:

gem 'non-stupid-digest-assets'

Entonces corre:

bundle install

Y finalmente agregue la siguiente línea en su archivo config / initializers / non_digest_assets.rb :

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

Eso es. Esto resolvió mi problema muy bien. Espero que esto ayude a alguien que ha encontrado un problema similar como yo.

KM Rakibul Islam
fuente
3

Aquí hay un repositorio que muestra una fuente personalizada con Rails 5.2 que funciona en Heroku. Va más allá y optimiza el servicio de las fuentes para que sea lo más rápido posible de acuerdo con https://www.webpagetest.org/

https://github.com/nzoschke/edgecors

Para comenzar, elegí piezas de las respuestas anteriores. Para Rails 5.2+ no debería necesitar una configuración de canalización de activos adicional.

Tubería de activos y SCSS

  • Colocar fuentes en app/assets/fonts
  • Coloque la @font-facedeclaración en un archivo scss y use el font-urlayudante

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 desde CDN con CORS

Estoy usando CloudFront, agregado con el complemento Heroku Edge .

Primero configure un prefijo CDN y Cache-Controlencabezados predeterminados en 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 intenta acceder a la fuente desde la URL herokuapp.com a la URL de CDN, recibirá un error CORS en su navegador:

El acceso a la fuente en ' https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf ' desde el origen ' https://edgecors.herokuapp.com ' ha sido bloqueado por la política de CORS: No 'Access-Control-Allow -El encabezado de origen está presente en el recurso solicitado. edgecors.herokuapp.com/ GET https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf net :: ERR_FAILED

Configure CORS para permitir el acceso a la fuente de Heroku a la URL de 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

Servir gzip Font Asset

La canalización de activos crea un .ttf.gzarchivo pero no lo sirve. Este parche de mono cambia la lista blanca de gzip de la canalización de activos a una lista negra:

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

El resultado final es un archivo de fuente personalizado app/assets/fontsservido desde un caché de CloudFront de larga duración.

Noah Zoschke
fuente
2

En mi caso, la pregunta original se usaba asset-urlsin resultados en lugar de la urlpropiedad CSS simple . El uso asset-urlterminó trabajando para mí en Heroku. Además, configura las fuentes en la /assets/fontscarpeta y llama asset-url('font.eot')sin agregar ninguna subcarpeta ni ninguna otra configuración.

bartoindahouse
fuente
1

Si tiene un archivo llamado scaffolds.css.scss, existe la posibilidad de que anule todas las cosas personalizadas que está haciendo en los otros archivos. Comenté ese archivo y de repente todo funcionó. Si no hay nada importante en ese archivo, ¡también podrías eliminarlo!

katfa
fuente
-7

simplemente coloque sus fuentes dentro de la carpeta app / assets / fonts y configure la ruta de carga automática cuando la aplicación comience a escribir el código en application.rb

config.assets.paths << Rails.root.join ("aplicación", "activos", "fuentes") y

luego use el siguiente código en css.

@Perfil delantero {

 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;

}

Darle una oportunidad.

Gracias

Shoaib Malik
fuente
¿Cómo agrega esto algo sobre las respuestas existentes?
cimmanon