首页 文章

Rails资产管道使用字体和纱线

提问于
浏览
1

我有一个现有的 rails 应用程序,我正在一个单独的分支机构实施 yarn 来管理我的供应商资产 . 我的应用程序堆栈是:

  • ruby-2.4.0

  • rails 5.1.4

  • node 9.4.0

  • 纱线1.3.2

安装完纱后,我运行 yarn init 并在项目根目录中生成了一个package.json . 添加几个包后,它看起来像:

# package.json

{
  "name": "my-project-name",
  "version": "1.0.0",
  "private": true,
  "repository": "my-repo",
  "author": "me",
  "license": "MIT",
  "dependencies": {
    "bootstrap": "3",
    "font-awesome": "^4.7.0",
    "jquery": "^3.3.1",
    "jquery-backstretch": "^2.1.16",
    "jquery-ujs": "^1.2.2",
    "waypoints": "^4.0.1"
  }
}

我在app / assets下创建了几个文件,包括来自 node_modules 的样式表和javascripts:

# app/assets/javascripts/node_modules.js
//= require jquery
//= require jquery-ujs
//= require bootstrap/dist/js/bootstrap.min.js
//= require waypoints
//= require jquery-backstretch

# app/assets/stylesheets/font_path_overwrite.scss
$fa-font-path: "font-awesome/fonts/";

# app/assets/stylesheets/node_modules.css.scss
/*
 *= require bootstrap/dist/css/bootstrap.min.css
 *= require font_path_overwrite
 *= require font-awesome/scss/font-awesome
*/

我也改变了:

# config/initializers/assets.rb
# ...
Rails.application.config.assets.paths << Rails.root.join('node_modules')

Rails.application.config.assets.precompile += %w(*.js *.scss)
Rails.application.config.assets.precompile += %w(*.png *.woff2 *.woff *.ttf *.eot *.jpg *.gif *.svg *.ico)

# Rakefile
# ...
Rake::Task['assets:precompile'].enhance [:js_deps_install]
task :js_deps_install do
  sh 'yarn install'
end

根据SO-43170792,我添加了一个新的

heroku buildpacks:set heroku/ruby
heroku buildpacks:add --index 1 heroku/nodejs

在我的staging environment中,我部署了这些更改,我突然意识到我的资产预编译 node_modules/ 文件夹发生了一些奇怪的事情:虽然一切似乎都适用于js和css文件,但我遇到了一些字体问题(特别是font-awesome的字体) .

在网络检查器中调试找不到文件 assets/font-awesome/fonts/fontawesome-webfont.ttf?v=4.7.0 ,因为它是预编译的,而不仅仅是复制到:

公共/资产/ fontawesome /字体/ fontawesome-webfont- [散列]的.ttf

我理解为什么我要面对这种情况(这与两个月前的this unaswered question非常相似) .

我正在寻找一个干净的解决方案或智能解决方法(例如创建一个中间件,将普通的 .ttf 请求重定向到rails投诉哈希版本并缓存x小时的答案 . 你有什么建议吗?

2 回答

  • 2

    我想我在几次尝试后找到了最干净的解决方案:

    Attempt 1: Sass and overwrite fonts directories

    我在 app/assets/stylesheets 目录中对sass模块进行了相当广泛的重构 . 这里有几个例子:

    对于字体

    // sass_font_awesome.scss
    $fa-font-path: "font-awesome/fonts";
    @import 'font-awesome/scss/font-awesome';
    @font-face {
      font-family: 'FontAwesome';
      src: asset-url('#{$fa-font-path}/fontawesome-webfont.eot');
      src: asset-url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix') format('embedded-opentype'),
        asset-url('#{$fa-font-path}/fontawesome-webfont.woff2') format('woff2'),
        asset-url('#{$fa-font-path}/fontawesome-webfont.woff') format('woff'),
        asset-url('#{$fa-font-path}/fontawesome-webfont.ttf') format('truetype'),
        asset-url('#{$fa-font-path}/fontawesome-webfont.svg?#fontawesomeregular') format('svg');
      font-weight: normal;
      font-style: normal;
    }
    

    对于图像

    // sass_multiselect.scss
    $ms-img-path: 'multiselect/js/img';
    @import 'multiselect/css/multi-select';
    .ms-container{
      background: transparent asset-url('#{$ms-img-path}/switch.png') no-repeat 50% 50%;
      width: 370px;
    }
    

    当预编译node_modules文件夹时,此方法仍然存在 . 实际上,所有节点cli脚本在Ugflifier的语法方面都存在一些问题 .

    Attempt 2: Install Webpack and create a app/javascripts/pack/application.sass

    @import '~font-awesome/scss/font-awesome'
    @import '~multiselect/css/multi-select'
    

    我仍然面临着相对路径的一些问题 . 我发现webpacker documentation中的解决方案在我的 config/webpacker/environment.js 中添加了以下加载器:

    // webpack/environment.js
    const { environment } = require('@rails/webpacker')
    
    // resolve-url-loader must be used before sass-loader
    environment.loaders.get('sass').use.splice(-1, 0, {
      loader: 'resolve-url-loader',
      options: {
        attempts: 1
      }
    });
    

    Solution: the easiest way

    我终于找到了webpacker gem的默认行为,这非常简单:

    // app/javascripts/packs/styles.js
    import 'font-awesome/scss/font-awesome.scss';
    import 'multiselect/css/multi-select.css';
    

    这将编译为捆绑的styles.css,无需任何其他加载器 .

    我花了很多时间才弄明白,我希望它对你也有帮助!

  • 1

    我通过覆盖字体路径使其工作 .

    application.scss:

    $fa-font-path:"font-awesome/fonts";
    
    @import 'font-awesome/scss/font-awesome';
    
    @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');
      //  src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts
      font-weight: normal;
      font-style: normal;
    }
    

    运行 rake assets:precompile ,您应该在 public/assets/font-awesome/fonts 中看到带有消化文件名的字体文件 .

    编译的CSS应该从Rails资产访问字体文件:

    @font-face{
       font-family:'FontAwesome';
       src:url(/assets/font-awesome/fonts/fontawesome-webfont-7bfcab6db99...979.eot?v=4.7.0)
    

相关问题