Rails 使用字体和纱线的资产管道
Rails asset pipeline working with fonts and yarn
我有一个现有的 rails
应用程序,我正在使用一个单独的 b运行ch 来实现 yarn
来管理我的供应商资产。我的应用程序堆栈是:
- ruby-2.4.0
- rails 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
:
的样式表和 javascript
# 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
根据 ,我添加了一个新的
heroku buildpacks:set heroku/ruby
heroku buildpacks:add --index 1 heroku/nodejs
在我的 staging environment 中,我部署了这些更改,我突然意识到我的资产预编译 node_modules/
文件夹发生了一些 st运行ge 的事情:虽然对于 js 来说一切似乎都正常和 css 文件,我遇到了一些字体问题(尤其是 font-awesome 的字体)。
在网络检查器中调试文件 assets/font-awesome/fonts/fontawesome-webfont.ttf?v=4.7.0
未找到,因为它是预编译的,而不是刚刚复制到:
public/assets/font-awesome/fonts/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 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
}
});
解决方法:最简单的方法
我终于找到了 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)
我有一个现有的 rails
应用程序,我正在使用一个单独的 b运行ch 来实现 yarn
来管理我的供应商资产。我的应用程序堆栈是:
- ruby-2.4.0
- rails 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
:
# 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
根据
heroku buildpacks:set heroku/ruby
heroku buildpacks:add --index 1 heroku/nodejs
在我的 staging environment 中,我部署了这些更改,我突然意识到我的资产预编译 node_modules/
文件夹发生了一些 st运行ge 的事情:虽然对于 js 来说一切似乎都正常和 css 文件,我遇到了一些字体问题(尤其是 font-awesome 的字体)。
在网络检查器中调试文件 assets/font-awesome/fonts/fontawesome-webfont.ttf?v=4.7.0
未找到,因为它是预编译的,而不是刚刚复制到:
public/assets/font-awesome/fonts/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 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
}
});
解决方法:最简单的方法
我终于找到了 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)