Usando fontes com o pipeline de ativos do Rails

345

Eu tenho algumas fontes sendo configuradas no meu arquivo Scss da seguinte forma:

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

O arquivo de fonte real é armazenado em / app / assets / fonts /

Eu adicionei config.assets.paths << Rails.root.join("app", "assets", "fonts")ao meu arquivo application.rb

e a fonte CSS de compilação é a seguinte:

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

Mas quando executo o aplicativo, os arquivos de fonte não estão sendo encontrados. Os logs:

Iniciado GET "/assets/icoMoon.ttf" para 127.0.0.1 em 05/06/2012 23:21:17 +0100 ativo servido /icoMoon.ttf - 404 não encontrado (13ms)

Por que o pipeline de ativos não está nivelando os arquivos de fonte em apenas / assets?

Alguma idéia pessoal?

Atenciosamente, Neil

Informação extra:

Ao verificar o console do Rails quanto a caminhos de ativos e o assetprecompile, recebo o seguinte:

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
fonte
3
Você tem font-urlauxiliar no SCSS no Rails.
9307 HaulethJul
Infelizmente, isso não faz diferença. Portanto, minha pergunta ainda está de pé
rctneil
Eu escrevi uma maneira genérica de diagnosticar e resolver esse problema em stackoverflow.com/a/40898227/1197775 .
sites

Respostas:

651
  1. Se a sua versão do Rails estiver entre > 3.1.0e < 4, coloque suas fontes em qualquer uma destas pastas:

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


    Para versões do Rails > 4, você deve colocar suas fontes na app/assets/fontspasta

    Nota: Para colocar fontes fora dessas pastas designadas, use a seguinte configuração:

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

    Para versões do Rails > 4.2 , é recomendável adicionar essa configuração ao config/initializers/assets.rb.

    No entanto, você também pode adicioná-lo a config/application.rb, ou aconfig/production.rb

  2. Declare sua fonte no seu arquivo 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;
    }

    Certifique-se de que sua fonte tenha o nome exatamente igual ao da URL da declaração. Letras maiúsculas e sinais de pontuação são importantes. Nesse caso, a fonte deve ter o nomeicomoon .

  3. Se você estiver usando Sass ou Less with Rails > 3.1.0(seu arquivo CSS possui .scssou .lessextensão), altere o url(...)na declaração da fonte para font-url(...).

    Caso contrário, seu arquivo CSS deverá ter a extensão .css.erb e a declaração da fonte url('<%= asset_path(...) %>').

    Se você estiver usando o Rails > 3.2.1, poderá usarfont_path(...) vez de asset_path(...). Esse ajudante faz exatamente a mesma coisa, mas é mais claro.

  4. Por fim, use sua fonte em seu CSS como você a declarou na font-familyparte. Se foi declarado em maiúscula, você pode usá-lo assim:

    font-family: 'Icomoon';
Ashitaka
fonte
36
Você reiniciou o servidor?
Ashitaka
9
@ NadeemYasin Obrigado pelo seu comentário, tive o mesmo problema. Os nomes dos arquivos tinham hífens e, quando removi, as soluções propostas aqui funcionavam.
Tseg #
35
config.assets.precompile += %w( .svg .eot .woff .ttf )está realmente errado, você precisa adicionar para pré-compilar algo que corresponda ao nome completo do ativo. A regexp trabalhou para mim:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Ensolarado
2
Bem, do jeito que está agora funciona para mim. Portanto, essa linha de código não é necessária ou a maneira de definir essa configuração depende da versão do Rails (ou de outra coisa). @ Jim já havia dito que tinha que remover as configurações na etapa 2, então talvez estejamos perdendo algo aqui. Cara, deve ser mais simples usar fontes com o pipeline de ativos.
Ashitaka 23/08
3
O passo 2 deve ser removido. De acordo com os Guias do Rails , config.assets.pathsé para referências de Sprockets, não relevantes aqui. config.assets.precompiletambém é inútil porque "O correspondente padrão para compilar arquivos inclui application.js, application.css e todos os arquivos não JS / CSS (isso incluirá todos os ativos de imagem automaticamente) das pastas de aplicativos / ativos" (veja aqui )
Eric L.
38

Agora, aqui está uma torção:

Você deve colocar todas as fontes em app/assets/fonts/como eles vai se pré-compilados no estadiamento e produção por default-eles vão ficar pré-compilados quando empurrado para heroku .

Font arquivos colocados em vendor/assetsvão não ser pré-compilados em teste ou produção por padrão - eles vão falhar em heroku . Fonte!

- @plapier, thinkbot / bourbon

Acredito firmemente que colocar fontes de fornecedores vendor/assets/fonts faz muito mais sentido do que colocá-las app/assets/fonts. Com essas duas linhas de configuração extra, isso funcionou bem para mim (no Rails 4):

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

- @jhilden, thinkbot / bourbon

Eu também testei rails 4.0.0. Na verdade, a última linha é suficiente para pré-compilar com segurança as fontes da vendorpasta. Demorou algumas horas para descobrir. Espero que tenha ajudado alguém.

jibiel
fonte
2
+1 edgeguides.rubyonrails.org/… explica o layout do pipeline de ativos e ajuda a entender como isso funciona. Corrigido a partir de 04/07/2014
Zachary Moshansky
Você precisa dos dois? app.config.assets.paths << Rails.root.join('vendor', 'assets', 'fonts') app.config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/Um comentário em outra resposta diz que a última cuida de ambas.
ahnbizcad
Mesmo no Rails 4.2 +, eu realmente acho que as app/assetsentradas para rodas dentadas e amigos são processadas como saída public/assets, embora vendor/assetsainda possa ser útil para implantar ativos sem modificação; ambos têm seus casos de uso. Toda a convenção de vendas tem como premissa a garantia de que nada acontecerá vendor/*. (Sim, vendor/pluginsfoi abusado com código-hoarding, closed-fonte mania pré gem era e as pessoas simplesmente copiar-colar js sem versão em vendor/assets/javascriptspré-Bower / rails-ativos.)
2
Para aqueles que se perguntam; jogue isso emconfig/initializers/assets.rb
TJ Biddle
23

Se você não deseja acompanhar o movimento de suas fontes:

# Adding Webfonts to the Asset Pipeline
config.assets.precompile << Proc.new { |path|
  if path =~ /\.(eot|svg|ttf|woff)\z/
    true
  end
}
Nathan Colgate
fonte
11
Eu acho que essa é a melhor solução; a menos que você tenha criado as fontes, elas provavelmente pertencem a / vendor / assets / fonts - não a / app / assets / fonts. Esta abordagem resolve para ambos, o acima não faz
Casey
5
@ Casey: esta solução permite que você coloque fontes dentro do fornecedor / ativos. @ Nathan Colgate: Isso pode ser simplificado para:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Sunny
@Sunny - Eu sei, é por isso que eu acho que é melhor do que a resposta aceita
Casey
2
Além disso, você deve finalizar seu regex com \ Z - stackoverflow.com/questions/577653/…
Casey
11
Como você lida com os hashes que o Rails anexa ao arquivo de fonte?
James McMahon.
21

Você precisa usar font-urlno seu bloco @ font-face, nãourl

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

bem como esta linha em application.rb, como você mencionou (para fontes em app/assets/fonts

config.assets.paths << Rails.root.join("app", "assets", "fonts")
craic.com
fonte
você também precisa habilitar a pré-compilação para a produção
ahnbizcad
Em um novo trilhos 4.2 aplicativo, tanto src: url(someFont.ttf)e src: font-url(someFont.ttf)trabalhou ao ter os arquivos em app/assets/fonts. Eu tenho .scssextensões por padrão. Não precisei adicionar o config.assets.paths.
Danny
9

Aqui, minha abordagem ao uso de fontes no pipeline de ativos:

1) Coloque todo o seu arquivo de fonte app/assets/fonts/, na verdade você não está restrito a colocá-lo no fontsnome da pasta. Você pode colocar qualquer nome de subpasta que desejar. Por exemplo, app/assets/abcou app/assets/anotherfonts. Mas eu recomendo que você o coloque app/assets/fonts/para melhor estrutura de pastas.

2) No seu arquivo sass, use o auxiliar sass font-pathpara solicitar seus recursos de fonte 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) Execute a bundle exec rake assets:precompilepartir da sua máquina local e veja o resultado do seu application.css. Você deve ver algo assim:

@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 você quiser saber mais sobre como o pipeline de ativos funciona, visite o seguinte guia simples: https://designcode.commandrun.com/rails-asset-pipeline-simple-guide-830e2e666f6c#.6lejlayk2

Tim
fonte
5

Eu estava tendo esse problema no Rails 4.2 (com ruby ​​2.2.3) e tive que editar o _paths.scss parcial da font-awesome para remover referências $fa-font-pathe remover uma barra principal. O seguinte foi quebrado:

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

Uma alternativa seria simplesmente remover a barra seguinte ao interpolado $fa-font-pathe depois definir$fa-font-path como uma string ou subdiretório vazio com barra à direita (conforme necessário).

Lembre-se de recompilar ativos e reiniciar o servidor conforme necessário. Por exemplo, em uma configuração de passageiro:

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

Em seguida, recarregue seu navegador.

markeissler
fonte
5

Estou usando o Rails 4.2 e não foi possível exibir os ícones de rodapé. Pequenas caixas estavam aparecendo, em vez do (+) nas linhas recolhidas e das pequenas flechas de classificação que eu esperava. Depois de estudar as informações aqui, fiz uma alteração simples no meu código: remova o diretório da fonte em css. Ou seja, altere todas as entradas css assim:

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

para ficar assim:

src:url('footable.eot');

Funcionou. Eu acho que o Rails 4.2 já assume o diretório da fonte, portanto, especificá-lo novamente no código css faz com que os arquivos da fonte não sejam encontrados. Espero que isto ajude.

Brian Doherty
fonte
3

Eu tive um problema semelhante ao atualizar meu aplicativo Rails 3 para o Rails 4 recentemente. Minhas fontes não estavam funcionando corretamente, como no Rails 4+, nós apenas podemos manter as fontes no app/assets/fontsdiretório. Mas meu aplicativo Rails 3 tinha uma organização de fonte diferente. Então eu tive que configurar o aplicativo para que ele ainda funcione com o Rails 4+ com minhas fontes em um local diferente app/assets/fonts. Eu tentei várias soluções, mas depois que encontrei a gema de ativos de digestão não estúpida , ela ficou muito fácil.

Adicione esta gema adicionando a seguinte linha ao seu Gemfile:

gem 'non-stupid-digest-assets'

Então corra:

bundle install

E, finalmente, adicione a seguinte linha no seu arquivo config / initializers / non_digest_assets.rb :

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

É isso aí. Isso resolveu meu problema muito bem. Espero que isso ajude alguém que encontrou um problema semelhante ao meu.

KM Rakibul Islam
fonte
3

Aqui está um repositório que demonstra servindo uma fonte personalizada com o Rails 5.2 que funciona no Heroku. Ele vai além e otimiza o fornecimento das fontes para que seja o mais rápido possível, de acordo com https://www.webpagetest.org/

https://github.com/nzoschke/edgecors

Para começar, peguei peças das respostas acima. Para o Rails 5.2 ou superior, você não precisa de uma configuração extra de pipeline de ativos.

Pipeline de ativos e SCSS

  • Coloque fontes em app/assets/fonts
  • Coloque a @font-facedeclaração em um arquivo scss e use o font-urlauxiliar

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 de CDN com CORS

Estou usando o CloudFront, adicionado com o complemento Heroku Edge .

Primeiro, configure um prefixo CDN e Cache-Controlcabeçalhos padrão em 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 você tentar acessar a fonte do URL herokuapp.com para o URL da CDN, receberá um erro CORS no seu navegador:

O acesso à fonte em ' https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf ' from origin ' https://edgecors.herokuapp.com ' foi bloqueado pela política do CORS: Não 'Access-Control-Allow O cabeçalho -Origin 'está presente no recurso solicitado. edgecors.herokuapp.com/ GET https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf net :: ERR_FAILED

Portanto, configure o CORS para permitir o acesso à fonte do Heroku na URL da 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

Ativar recurso de fonte gzip

O pipeline de ativos cria um .ttf.gzarquivo, mas não o serve. Esse patch de macaco altera a lista de permissões gzip do pipeline de ativos para uma 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

O resultado final é um arquivo de fonte personalizado app/assets/fontsservido em um cache do CloudFront de longa duração.

Noah Zoschke
fonte
2

No meu caso, a pergunta original estava usando asset-urlsem resultados, em vez de urlpropriedade css simples . Usando asset-urlacabou trabalhando para mim em Heroku. Além disso, defina as fontes na /assets/fontspasta e faça a chamada asset-url('font.eot')sem adicionar nenhuma subpasta ou qualquer outra configuração a ela.

bartoindahouse
fonte
1

Se você tiver um arquivo chamado scaffolds.css.scss, existe a chance de substituir todas as coisas personalizadas que você está fazendo nos outros arquivos. Comentei esse arquivo e de repente tudo funcionou. Se não houver nada importante nesse arquivo, você também pode excluí-lo!

Katfa
fonte
-7

basta colocar suas fontes na pasta app / assets / fonts e definir o caminho de carregamento automático quando o aplicativo começar a escrever o código em application.rb

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

em seguida, use o seguinte código em css.

@Tipo de letra {

 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;

}

De uma chance.

obrigado

Shoaib Malik
fonte
Como isso adiciona algo sobre as respostas existentes?
Cimmanon