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

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

  • ruby2.4.0
  • 铁轨5.1.4
  • 节点9.4.0
  • 纱线1.3.2

安装yarn之后,我运行了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 

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

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

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

我明白为什么我要面对这种情况(这与两个月前的这个未解答的问题非常相似)。

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

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

尝试1:Sass和覆盖字体目录

我在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的语法方面都存在一些问题。

尝试2:安装Webpack并创建app / javascripts / pack / application.sass

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

我仍然面临着相对路径的一些问题。 我发现webpacker文档中的解决方案在我的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 } }); 

解决方案:最简单的方法

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

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

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

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

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

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)