Używanie czcionek z potokiem zasobów Rails

345

Mam kilka czcionek konfigurowanych w moim pliku Scss, takich jak:

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

Rzeczywisty plik czcionek jest przechowywany w / app / asset / fonts /

Dodałem config.assets.paths << Rails.root.join("app", "assets", "fonts")do mojego pliku application.rb

a skompilowane źródło CSS wygląda następująco:

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

Ale kiedy uruchamiam aplikację, nie można znaleźć plików czcionek. Dzienniki:

Rozpoczęto GET „/assets/icoMoon.ttf” dla 127.0.0.1 na 06.06.2012 23:21:17 +0100 Obsługiwany zasób /icoMoon.ttf - 404 nie znaleziono (13ms)

Dlaczego potok zasobów nie spłaszcza plików czcionek do samych / zasobów?

Jakieś pomysły ludzie?

Z pozdrowieniami, Neil

Informacje dodatkowe:

Podczas sprawdzania konsoli szyn pod kątem ścieżek zasobów i zasobów prekompilacji otrzymuję:

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
źródło
3
Masz font-urlpomocnika w SCSS w Railsach.
Hauleth
To nie robi niestety różnicy. Dlatego moje pytanie nadal trwa
rctneil
Opisałem ogólny sposób diagnozowania i rozwiązywania tego problemu na stackoverflow.com/a/40898227/1197775 .
witryny

Odpowiedzi:

651
  1. Jeśli twoja wersja Railsów znajduje się pomiędzy > 3.1.0i < 4, umieść czcionki w jednym z tych folderów:

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


    Dla wersji Rails > 4, to należy umieścić czcionki w app/assets/fontsfolderze.

    Uwaga: Aby umieścić czcionki poza tymi wyznaczonymi folderami, użyj następującej konfiguracji:

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

    Dla wersji Rails > 4.2, jest zalecane , aby dodać tę konfigurację config/initializers/assets.rb.

    Możesz jednak również dodać go do albo config/application.rb, albo doconfig/production.rb

  2. Zadeklaruj czcionkę w pliku 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;
    }

    Upewnij się, że twoja czcionka ma dokładnie taką samą nazwę jak w części adresu URL deklaracji. Duże litery i znaki interpunkcyjne mają znaczenie. W takim przypadku czcionka powinna mieć nazwę icomoon.

  3. Jeśli używasz Sass lub Less z Railsami > 3.1.0(plik CSS ma .scsslub .lessrozszerzenie), zmień url(...)deklarację czcionki na font-url(...).

    W przeciwnym razie plik CSS powinien mieć rozszerzenie .css.erb, a deklaracja czcionki powinna mieć url('<%= asset_path(...) %>').

    Jeśli używasz Railsów > 3.2.1, możesz użyć font_path(...)zamiast asset_path(...). Ten pomocnik robi dokładnie to samo, ale jest bardziej przejrzysty.

  4. Na koniec użyj czcionki w CSS, tak jak zadeklarowałeś ją w font-familyczęści. Jeśli został zadeklarowany wielkimi literami, możesz użyć go w następujący sposób:

    font-family: 'Icomoon';
Ashitaka
źródło
36
Czy zrestartowałeś serwer?
Ashitaka,
9
@NadeemYasin Dzięki za komentarz, miałem ten sam problem. Nazwy plików zawierały myślniki, a kiedy usunąłem, zaproponowane tutaj rozwiązania zadziałały.
tsega
35
config.assets.precompile += %w( .svg .eot .woff .ttf )jest w rzeczywistości niepoprawny, musisz dodać, aby wstępnie skompilować coś, co pasuje do pełnej nazwy zasobu. Wyrażenie regularne działało dla mnie:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Słoneczny
2
Cóż, sposób, w jaki to teraz działa dla mnie. Więc albo ten wiersz kodu wcale nie jest potrzebny, albo sposób ustawienia tej konfiguracji zależy od wersji Railsów (lub czegoś innego). @Jim powiedział już, że musi usunąć konfiguracje w kroku 2, więc może coś tu brakuje. Człowieku, prostsze powinno być używanie czcionek w potoku zasobów.
Ashitaka,
3
Krok 2 powinien zostać usunięty. Według Rails Guides , config.assets.pathsjest o referencje zębatkami, nie ma znaczenia tutaj. config.assets.precompilejest również bezużyteczny, ponieważ „Domyślny moduł do kompilowania plików obejmuje application.js, application.css i wszystkie pliki inne niż JS / CSS (spowoduje to automatyczne włączenie wszystkich zasobów obrazu) z folderów aplikacji / zasobów” (patrz tutaj )
Eric L.
38

Oto zwrot:

Powinieneś wstawić wszystkie czcionki, app/assets/fonts/ponieważ BĘDĄ one domyślnie wstępnie skompilowane w fazie i produkcji - zostaną one skompilowane po wypchnięciu do heroku .

Pliki czcionek umieszczone w vendor/assetsbędzie nie być skompilowane na postoju lub produkcji domyślnie - nie będą one na Heroku . Źródło!

- @plapier, thinkbot / bourbon

Mocno wierzę, że umieszczanie czcionek dostawców vendor/assets/fonts ma o wiele większy sens niż wkładanie ich app/assets/fonts. Z tymi 2 liniami dodatkowej konfiguracji działało to dla mnie dobrze (na Railsach 4):

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

- @jhilden, thinkbot / bourbon

Przetestowałem to również rails 4.0.0. W rzeczywistości ostatni wiersz wystarczy, aby bezpiecznie wstępnie skompilować czcionki z vendorfolderu. Zajęło to kilka godzin, aby to rozgryźć. Mam nadzieję, że to komuś pomogło.

Jibiel
źródło
2
+1 edgeguides.rubyonrails.org/… wyjaśnia układ potoku zasobów i pomaga zrozumieć, jak to działa. Stan na dzień 2014-07-04
Zachary Moshansky
Potrzebujesz obu tych elementów? app.config.assets.paths << Rails.root.join('vendor', 'assets', 'fonts') app.config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/Komentarz do innej odpowiedzi mówi, że ta ostatnia zajmuje się obiema.
ahnbizcad
Nawet w wersji Rails 4.2 + naprawdę uważam, że app/assetsdane wejściowe do kół łańcuchowych i przyjaciół są przetwarzane jako dane wyjściowe public/assets, podczas gdy vendor/assetsnadal mogą być przydatne do wdrażania zasobów bez modyfikacji; oba mają swoje przypadki użycia. Cała konwencja sprzedaży oparta jest na gwarancji, że nic się nie stanie vendor/*. (Tak, vendor/pluginszostał wykorzystany do gromadzenia kodu, mania sprzed epoki klejnotów z zamkniętym kodem źródłowym, a ludzie po prostu kopiowali wklejone niewersjonowane pliki js do vendor/assets/javascriptszasobów przed altaną / szynami.)
2
Dla tych, którzy zastanawiają się; wrzuć toconfig/initializers/assets.rb
TJ Biddle
23

Jeśli nie chcesz śledzić przenoszenia czcionek:

# Adding Webfonts to the Asset Pipeline
config.assets.precompile << Proc.new { |path|
  if path =~ /\.(eot|svg|ttf|woff)\z/
    true
  end
}
Nathan Colgate
źródło
1
Myślę, że to najlepsze rozwiązanie; chyba że stworzyłeś czcionki, które prawdopodobnie należą do / vendor / asset / fonts - nie / app / asset / fonts. Podejście to rozwiązuje oba powyższe problemy
Casey
5
@Casey: to rozwiązanie pozwala wstawiać czcionki w dostawcy / zasobach. @Nathan Colgate: Można to uprościć do:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Sunny
@Sunny - wiem, dlatego uważam, że jest lepsza niż zaakceptowana odpowiedź
Casey
2
Powinieneś także zakończyć wyrażenie regularne znakiem \ Z - stackoverflow.com/questions/577653/…
Casey
1
Jak radzisz sobie z skrótami, które Rails dołącza do pliku czcionki?
James McMahon
21

Musisz użyć font-urlw swoim bloku @ font-face, a nieurl

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

jak również ten wiersz w application.rb, jak wspomniałeś (dla czcionek w app/assets/fonts

config.assets.paths << Rails.root.join("app", "assets", "fonts")
craic.com
źródło
musisz także włączyć prekompilację do produkcji
ahnbizcad
Na nowiutkim szyny 4.2 aplikacji, zarówno src: url(someFont.ttf)i src: font-url(someFont.ttf)pracował przy konieczności plików app/assets/fonts. .scssDomyślnie mam rozszerzenia. Nie musiałem dodawać ścieżek config.assets.path.
Danny,
9

Oto moje podejście do używania czcionek w potoku zasobów:

1) Umieść cały plik czcionek pod app/assets/fonts/, w rzeczywistości nie jesteś ograniczony, aby umieścić go pod fontsnazwą folderu. Możesz podać dowolną nazwę podfolderu. Np app/assets/abclub app/assets/anotherfonts. Ale gorąco polecam, aby umieścić go pod app/assets/fonts/lepszą strukturą folderów.

2) Z pliku sass za pomocą pomocnika sass, font-pathaby poprosić o takie zasoby czcionki

@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) Uruchom bundle exec rake assets:precompilez lokalnego komputera i zobacz wynik application.css. Powinieneś zobaczyć coś takiego:

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

Jeśli chcesz dowiedzieć się więcej, jak działa potok zasobów, możesz odwiedzić następujący prosty przewodnik: https://designcode.commandrun.com/rails-asset-pipeline-simple-guide-830e2e666f6c#.6lejlayk2

Tim
źródło
5

Miałem ten problem na Railsach 4.2 (z Ruby 2.2.3) i musiałem częściowo edytować edytor czcionek _paths.scss, aby usunąć odniesienia do $fa-font-pathi usunąć wiodący ukośnik. Następujące elementy zostały zepsute:

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

I następujące prace:

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

Alternatywą byłoby po prostu usunięcie ukośnika po interpolacji, $fa-font-patha następnie zdefiniowanie go $fa-font-pathjako pustego łańcucha lub podkatalogu z ukośnikiem (w razie potrzeby).

Pamiętaj, aby ponownie skompilować zasoby i zrestartować serwer w razie potrzeby. Na przykład w konfiguracji pasażera:

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

Następnie załaduj ponownie przeglądarkę.

Markeissler
źródło
5

Korzystam z Rails 4.2 i nie mogłem wyświetlić wyświetlanych ikon. Pojawiły się małe pola zamiast (+) w zwiniętych wierszach i małe strzałki sortowania, których się spodziewałem. Po przestudiowaniu informacji tutaj dokonałem jednej prostej zmiany w kodzie: usuń katalog czcionek z css. Oznacza to, że zmień wszystkie wpisy css w następujący sposób:

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

wyglądać tak:

src:url('footable.eot');

Zadziałało. Myślę, że Rails 4.2 już zakłada katalog czcionek, więc podanie go ponownie w kodzie css powoduje, że nie można znaleźć plików czcionek. Mam nadzieję że to pomoże.

Brian Doherty
źródło
3

Miałem podobny problem, kiedy ostatnio zaktualizowałem aplikację Rails 3 do Rails 4. Moje czcionki nie działały poprawnie, tak jak w Rails 4+, wolno nam tylko przechowywać czcionki w app/assets/fontskatalogu. Ale moja aplikacja Rails 3 miała inną organizację czcionek. Musiałem więc skonfigurować aplikację tak, aby nadal działała z Railsami 4+, mając moje czcionki w innym miejscu niż app/assets/fonts. Wypróbowałem kilka rozwiązań, ale po tym, jak znalazłem klejnot, który nie jest głupi .

Dodaj ten klejnot, dodając następujący wiersz do pliku Gemfile:

gem 'non-stupid-digest-assets'

Następnie uruchomić:

bundle install

I na koniec dodaj następujący wiersz w pliku config / initializers / non_digest_assets.rb :

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

Otóż ​​to. To ładnie rozwiązało mój problem. Mam nadzieję, że to pomoże komuś, kto napotkał podobny problem, jak ja.

KM Rakibul Islam
źródło
3

Oto repozytorium pokazujące wyświetlanie niestandardowej czcionki w Rails 5.2, która działa na Heroku. To idzie dalej i optymalizuje wyświetlanie czcionek tak szybko, jak to możliwe, zgodnie z https://www.webpagetest.org/

https://github.com/nzoschke/edgecors

Na początek wybrałem kawałki z powyższych odpowiedzi. W przypadku Railsów 5.2+ nie powinieneś potrzebować dodatkowej konfiguracji potoku zasobów.

Rurociąg zasobów i SCSS

  • Umieść czcionki w app/assets/fonts
  • Umieść @font-facedeklarację w pliku scss i użyj font-urlpomocnika

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

Podawać z CDN z CORS

Korzystam z CloudFront, dodanego z dodatkiem Heroku Edge .

Najpierw skonfiguruj prefiks CDN i domyślne Cache-Controlnagłówki w 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

Jeśli spróbujesz uzyskać dostęp do czcionki z adresu URL herokuapp.com do adresu URL CDN, w przeglądarce pojawi się błąd CORS:

Dostęp do czcionki na stroniehttps://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf ” od pochodzenia „ https://edgecors.herokuapp.com ” został zablokowany przez politykę CORS: Brak „Kontrola dostępu - Zezwól Nagłówek -Origin 'jest obecny w żądanym zasobie. edgecors.herokuapp.com/ GET https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf net :: ERR_FAILED

Skonfiguruj więc CORS, aby umożliwić dostęp do czcionki z Heroku do adresu 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

Podaj zasób czcionek gzip

Rurociąg zasobów tworzy .ttf.gzplik, ale go nie obsługuje. Ta małpia łatka zmienia białą listę gzip potoku zasobów na czarną listę:

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

Ostatecznym wynikiem jest niestandardowy plik czcionki app/assets/fontsdostarczany z długowiecznej pamięci podręcznej CloudFront.

Noah Zoschke
źródło
2

W moim przypadku pierwotne pytanie było używane asset-urlbez wyników zamiast zwykłej urlwłaściwości css. Używanie asset-urlskończyło się dla mnie działaniem w Heroku. Plus ustawianie czcionek w /assets/fontsfolderze i wywoływanie asset-url('font.eot')bez dodawania do niego podfolderu lub innej konfiguracji.

bartoindahouse
źródło
1

Jeśli masz plik o nazwie scaffolds.css.scss, istnieje szansa, że ​​zastąpi wszystkie niestandardowe czynności wykonywane w innych plikach. Skomentowałem ten plik i nagle wszystko zadziałało. Jeśli w tym pliku nie ma nic ważnego, możesz go po prostu usunąć!

katfa
źródło
-7

po prostu umieść czcionki w folderze app / asset / fonts i ustaw ścieżkę automatycznego ładowania, gdy aplikacja zacznie używać pisania kodu w application.rb

config.assets.paths << Rails.root.join („aplikacja”, „zasoby”, „czcionki”) i

następnie użyj następującego kodu w 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;

}

Spróbuj.

Dzięki

Shoaib Malik
źródło
Jak to coś dodaje do istniejących odpowiedzi?
cimmanon,