Использование шрифтов с конвейером ресурсов Rails

345

У меня есть несколько шрифтов, настроенных в моем файле Scss, например:

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

Фактический файл шрифта хранится в / app / assets / fonts /

Я добавил config.assets.paths << Rails.root.join("app", "assets", "fonts")в свой файл application.rb

и исходный код CSS для компиляции выглядит следующим образом:

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

Но когда я запускаю приложение, файлы шрифтов не обнаруживаются. Журналы:

Запущен GET "/assets/icoMoon.ttf" для 127.0.0.1 в 2012-06-05 23:21:17 +0100 Обслуживаемый актив /icoMoon.ttf - 404 Not Found (13ms)

Почему конвейер ресурсов не сглаживает файлы шрифтов просто в / assets?

Есть идеи, люди?

С наилучшими пожеланиями, Нил

Дополнительная информация:

Когда я проверяю консоль rails на наличие путей к ресурсам и предварительную компиляцию, я получаю следующее:

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
источник
3
У вас есть font-urlпомощник в SCSS в Rails.
Хаулет
Это не имеет никакого значения, к сожалению. Поэтому мой вопрос все еще стоит
rctneil
Я написал общий способ диагностики и решения этой проблемы на stackoverflow.com/a/40898227/1197775 .
сайты

Ответы:

651
  1. Если ваша версия Rails находится между > 3.1.0и < 4, поместите ваши шрифты в любую из следующих папок:

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


    Для версий Rails > 4вы должны поместить свои шрифты в app/assets/fontsпапку.

    Примечание. Чтобы разместить шрифты вне указанных папок, используйте следующую конфигурацию:

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

    Для версий Rails > 4.2, то рекомендуется добавить эту конфигурацию config/initializers/assets.rb.

    Тем не менее, вы можете также добавить его либо config/application.rb, илиconfig/production.rb

  2. Объявите свой шрифт в своем файле 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;
    }

    Убедитесь, что ваш шрифт назван точно так же, как в части URL объявления. Заглавные буквы и знаки препинания имеют значение. В этом случае шрифт должен иметь название icomoon.

  3. Если вы используете Sass или менее Rails > 3.1.0(файл CSS имеет .scssили .lessрасширение), то изменить url(...)в объявлении шрифта в font-url(...).

    В противном случае ваш CSS-файл должен иметь расширение .css.erb, а объявление шрифта должно быть url('<%= asset_path(...) %>').

    Если вы используете Rails > 3.2.1, вы можете использовать font_path(...)вместо asset_path(...). Этот помощник делает то же самое, но это более понятно.

  4. Наконец, используйте свой шрифт в своем CSS, как вы объявили в этой font-familyчасти. Если он был объявлен заглавными, вы можете использовать его следующим образом:

    font-family: 'Icomoon';
Ашитака
источник
36
Вы перезапустили свой сервер?
Ашитака
9
@NadeemYasin Спасибо за ваш комментарий, у меня была такая же проблема. В именах файлов были пометки, и когда я удалил, предложенные здесь решения сработали.
Цега
35
config.assets.precompile += %w( .svg .eot .woff .ttf )на самом деле неправильно, вам нужно добавить, чтобы предварительно скомпилировать то, что соответствует полному имени ресурса. У меня сработало регулярное выражение:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Солнечный
2
Ну, как это сейчас работает для меня. Так что либо эта строка кода не нужна вообще, либо способ установки этого конфига зависит от версии Rails (или чего-то еще). @Jim уже сказал, что ему нужно удалить конфиги на шаге 2, так что, может быть, мы что-то здесь упустили. Человек, должно быть проще использовать шрифты с конвейером ресурсов.
Ашитака
3
Шаг 2 должен быть удален. Согласно Rails Guides , config.assets.pathsэто для ссылок Sprockets, здесь не актуально. config.assets.precompileтакже бесполезен, потому что «Сопоставление по умолчанию для компиляции файлов включает application.js, application.css и все файлы, не относящиеся к JS / CSS (это будет включать все ресурсы изображений автоматически) из папок app / assets» (см. здесь )
Эрик Л.
38

Теперь вот поворот:

Вы должны поместить все шрифты , app/assets/fonts/как они БУДУТ получить прекомпилированы в постановке и производстве по умолчанию, они будут получать прекомпилированы при нажатии на Heroku .

Файлы шрифтов, помещенные в них vendor/assets, НЕ будут предварительно скомпилированы при постановке или производстве по умолчанию - они потерпят неудачу на heroku . Источник!

- @plapier, мыслибот / бурбон

Я твердо верю, что использование шрифтов вендоров vendor/assets/fonts имеет гораздо больше смысла, чем их использование app/assets/fonts. С этими двумя строками дополнительной конфигурации это хорошо работает для меня (на Rails 4):

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

- @jhilden, мыслебот / бурбон

Я также проверил это на rails 4.0.0. На самом деле последней строки достаточно, чтобы безопасно скомпилировать шрифты из vendorпапки. Потребовалось пару часов, чтобы понять это. Надеюсь, это помогло кому-то.

jibiel
источник
2
+1 edgeguides.rubyonrails.org/… объясняет расположение конвейера активов и помогает понять, как это работает. Исправить по состоянию на 2014-07-04
Захарий Мошанский
Вам нужны оба из них? app.config.assets.paths << Rails.root.join('vendor', 'assets', 'fonts') app.config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/Комментарий к другому ответу говорит, что последний заботится об обоих.
Анбизкад
Даже в Rails 4.2+ -land я действительно считаю, что app/assetsвходные данные для звездочек и друзей обрабатываются как выходные public/assets, тогда как vendor/assetsвсе еще могут быть полезны для развертывания ресурсов без изменений; у обоих есть свои варианты использования. Все соглашение о продаже базируется на гарантии того, что ничего не случится vendor/*. (Да, vendor/pluginsон подвергался злоупотреблениям из-за сокрытия кода, мании pre-gem с закрытым исходным кодом, и люди просто копировали неверсированные js в vendor/assets/javascriptspre-bower / rails-assets.)
2
Для тех, кто интересуется; добавьте этоconfig/initializers/assets.rb
TJ Biddle
23

Если вы не хотите отслеживать перемещение шрифтов:

# Adding Webfonts to the Asset Pipeline
config.assets.precompile << Proc.new { |path|
  if path =~ /\.(eot|svg|ttf|woff)\z/
    true
  end
}
Натан Колгейт
источник
1
Я думаю, что это лучшее решение; если вы не создали шрифты, они, вероятно, принадлежат в / vendor / assets / fonts, а не в / app / assets / fonts. Этот подход решает для обоих, выше нет
Кейси
5
@Casey: это решение позволяет размещать шрифты внутри вендора / активов. @ Натан Колгейт: Это может быть упрощено до:config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Солнечный
@Sunny - я знаю, поэтому я думаю, что это лучше, чем принятый ответ
Кейси
2
Также вы должны завершить свое регулярное выражение \ Z - stackoverflow.com/questions/577653/…
Кейси
1
Как вы справляетесь с хешами, которые Rails добавляет в файл шрифтов?
Джеймс МакМэхон
21

Вы должны использовать font-urlв своем блоке @ font-face, а неurl

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

а также эту строку в application.rb, как вы упомянули (для шрифтов в app/assets/fonts

config.assets.paths << Rails.root.join("app", "assets", "fonts")
craic.com
источник
Вам также нужно включить прекомпиляцию для производства
ahnbizcad
На новеньких рельсы 4.2 приложение, как src: url(someFont.ttf)и src: font-url(someFont.ttf)работал, имея файлы app/assets/fonts. У меня есть .scssрасширения по умолчанию. Мне не нужно было добавлять в config.assets.paths.
Дэнни
9

Вот мой подход к использованию шрифтов в конвейере ресурсов:

1) Поместите все ваши файлы шрифтов под app/assets/fonts/, на самом деле вы не ограничены, чтобы поместить его под fontsименем папки. Вы можете указать любое имя подпапки. Например, app/assets/abcили app/assets/anotherfonts. Но я настоятельно рекомендую вам положить его app/assets/fonts/для лучшей структуры папок.

2) Из вашего sass-файла используйте помощника sass font-pathдля запроса таких ресурсов шрифта, как этот

@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) Запустите bundle exec rake assets:precompileс локального компьютера и посмотрите результат application.css. Вы должны увидеть что-то вроде этого:

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

Если вы хотите узнать больше о том, как работает конвейер активов, вы можете посетить следующее простое руководство: https://designcode.commandrun.com/rails-asset-pipeline-simple-guide-830e2e666f6c#.6lejlayk2

Тим
источник
5

У меня возникла эта проблема в Rails 4.2 (с ruby ​​2.2.3), и мне пришлось отредактировать частичку font-awesome _paths.scss, чтобы удалить ссылки $fa-font-pathи удалить косую черту. Следующее было сломано:

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

И следующие работы:

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

Альтернативой было бы просто удалить косую черту после интерполированной, $fa-font-pathа затем определить $fa-font-pathкак пустую строку или подкаталог с косой чертой (при необходимости).

Не забудьте перекомпилировать ресурсы и перезапустить сервер по мере необходимости. Например, на пассажирской установке:

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

Затем перезагрузите браузер.

markeissler
источник
5

Я использую Rails 4.2, и мне не удалось отобразить иконки footable. Вместо (+) на свернутых строках и маленьких сортировочных стрелок, которые я ожидал, показывались маленькие прямоугольники. Изучив информацию здесь, я внес одно простое изменение в свой код: удалил каталог шрифтов в css. То есть измените все записи CSS следующим образом:

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

выглядеть так:

src:url('footable.eot');

Это сработало. Я думаю, что Rails 4.2 уже использует каталог шрифтов, поэтому повторное указание его в коде css делает файлы шрифтов не найденными. Надеюсь это поможет.

Брайан Доэрти
источник
3

У меня была похожая проблема, когда я недавно обновил свое приложение Rails 3 до Rails 4. Мои шрифты не работали должным образом, как в Rails 4+, нам разрешено хранить шрифты только в app/assets/fontsкаталоге. Но мое приложение Rails 3 имело другую организацию шрифтов. Поэтому мне пришлось настроить приложение так, чтобы оно по-прежнему работало с Rails 4+, где мои шрифты были в другом месте, кроме app/assets/fonts. Я попробовал несколько решений, но после того, как я нашел драгоценный камень non-stupid-digest-assets , он стал таким простым.

Добавьте этот драгоценный камень, добавив следующую строку в ваш Gemfile:

gem 'non-stupid-digest-assets'

Затем запустите:

bundle install

И, наконец, добавьте следующую строку в ваш файл config / initializers / non_digest_assets.rb :

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

Вот и все. Это решило мою проблему красиво. Надеюсь, это поможет кому-то, кто столкнулся с подобной проблемой, как я.

К.М. Ракибул Ислам
источник
3

Вот репозиторий, демонстрирующий использование пользовательского шрифта с Rails 5.2, который работает на Heroku. Это идет дальше и оптимизирует обслуживание шрифтов, чтобы быть максимально быстрым согласно https://www.webpagetest.org/

https://github.com/nzoschke/edgecors

Для начала я выбрал кусочки из ответов выше. Для Rails 5.2+ вам не понадобится дополнительная конфигурация конвейера активов.

Asset Pipeline и SCSS

  • Поместите шрифты в app/assets/fonts
  • Поместите @font-faceобъявление в файл scss и используйте font-urlпомощник

От 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;
}

Подавать из CDN с CORS

Я использую CloudFront, добавленный с помощью дополнения Heroku Edge .

Сначала настройте префикс CDN и Cache-Controlзаголовки по умолчанию в 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

Если вы попытаетесь получить доступ к шрифту с URL-адреса herokuapp.com по URL-адресу CDN, вы получите сообщение об ошибке CORS в своем браузере:

Доступ к шрифту по адресу https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf из источника « https://edgecors.herokuapp.com » заблокирован политикой CORS: нет «Access-Control-Allow» Заголовок -Origin 'присутствует на запрашиваемом ресурсе. edgecors.herokuapp.com/ ПОЛУЧИТЕ https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf net :: ERR_FAILED

Поэтому настройте CORS, чтобы разрешить доступ к шрифту из Heroku по 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

Служить gzip Font Asset

Конвейер ресурсов создает .ttf.gzфайл, но не обслуживает его. Этот патч обезьяны изменяет белый список gzip конвейера ресурсов на черный список:

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

Конечным результатом является пользовательский файл шрифта, который app/assets/fontsподается из долгоживущего кеша CloudFront.

Ной Зошке
источник
2

В моем случае оригинальный вопрос использовался asset-urlбез результатов вместо простого urlсвойства CSS. Использование в asset-urlконечном итоге работает на меня в Heroku. Плюс установка шрифтов в /assets/fontsпапке и вызов asset-url('font.eot')без добавления какой-либо подпапки или любой другой конфигурации.

bartoindahouse
источник
1

Если у вас есть файл с именем scaffolds.css.scss, то есть шанс, что он переопределит все пользовательские действия, которые вы делаете в других файлах. Я закомментировал этот файл, и вдруг все заработало. Если в этом файле нет ничего важного, вы можете просто удалить его!

katfa
источник
-7

просто поместите ваши шрифты в папку app / assets / fonts и установите путь автозагрузки, когда приложение начнет использовать написание кода в application.rb

config.assets.paths << Rails.root.join ("приложение", "активы", "шрифты") и

затем используйте следующий код в 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;

}

Попробуйте.

Спасибо

Шоаиб Малик
источник
Как это добавляет что-то поверх существующих ответов?
Цимманон