Rails 및 Webpacker를 사용한 중요한 CSS - SprocketsLess 1부
우리 모두는 빠르고 안정적인 웹 페이지를 원합니다. Page Speed Audit을 수행할 때 권장 사항으로 자주 나오는 것은 중요한 CSS입니다. 중요한 CSS, 특히 접힌 부분 위의 중요한 CSS는 페이지 상단(접힌 부분 위)을 렌더링하는 데 필요한 최소한의 CSS를 인라인(HTML에서)하는 기능입니다. 나는 한동안 Rails 앱에서 이것을 달성하기 위한 쉬운 해결책을 찾았지만 실제로 성공하지 못했습니다.
Webpack(예: Rails의 Webpacker)의 장점 중 하나는 주변의 모든 에코 시스템입니다. Rails의 JS 측은 대부분 문서화되어 있지만 CSS 및 이미지에 사용할 수 있는 많은 도구도 있습니다.
몇 달 전에 나는 GoRails 을 사용하는 훌륭한 비디오를 PurgeCss in a Rails application 에서 발견했습니다.
PurgeCSS 이해
PurgeCSS의 글로벌 개념은 일부 CSS 클래스가 사용되는 모든 파일을 PurgeCSS에 공급한다는 것입니다(보통
.html
, html.erb
, .js
). PurgesCSS는 CSS 선택자가 될 수 있는 모든 토큰 목록을 생성합니다.반면에 Webpacker는
mini-css-extract-plugin
를 사용하여 CSS 번들을 만듭니다. PurgeCSS는 토큰 목록을 추출합니다.결과는 두 토큰 목록의 교차점입니다.
여러 규칙이 있는 여러 팩
Webpacker를 사용하면 여러 개의 팩을 쉽게 가질 수 있습니다.
some-pack.js
디렉토리에 새 app/javascript/packs
파일을 생성하기만 하면 됩니다.우리가 할 일에 대한 글로벌 아이디어는 다음과 같습니다.
critical.js
을 정의합니다. critical.css
에 훨씬 더 엄격한 규칙을 적용합니다. Dev.to
로 인라인합니다. application.css
을 지연 로드합니다. critical.js 진입점
다음과 같은 application.js가 주어집니다.
// app/javascript/packs/application.js
require("@rails/ujs").start();
require("local-time").start();
require("turbolinks").start();
window.Rails = Rails;
// import CSS
import "stylesheets/application.scss";
// import Stimulus controllers
import "controllers/index";
// import vendor JS
import "bootstrap";
기본 진입점은 일반적으로 다음과 같이 보이는 기본 application.scss를 가져옵니다.
// app/javascript/stylesheets/application.scss
// Fonts
@import "config/fonts";
// Graphical variables
@import "config/colors";
// Vendor
@import "~bootstrap/scss/functions";
@import "config/bootstrap_variables";
@import "~bootstrap/scss/bootstrap";
$fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
@import "~@fortawesome/fontawesome-free/scss/fontawesome";
@import "~@fortawesome/fontawesome-free/scss/brands";
// Components
@import "components/index";
// layouts
@import "layouts/sticky-footer";
우리는 매우 기본적인
critical.js
를 생성할 수 있으며, 새로운 critical.scss 스타일시트를 가져오기만 하면 됩니다.// app/javascript/packs/critical.js
import "stylesheets/critical.scss";
critical.scss
파일에서 PurgeCSS가 더 나은 작업을 수행하는 데 도움이 되도록 내부에 넣는 항목을 좀 더 선택적으로 시작할 수 있습니다. (약간의 차이가 있습니다)// colors
@import "config/colors";
// vendor
@import "~bootstrap/scss/functions";
@import "config/bootstrap_variables";
@import "config/bootstrap_critical"; // pick only the Bootstrap module you need
// Components
@import "components/banner"; //just pick the components you need for the homepage
PostCSS / PurgeCSS 구성
그럼 중요한 부분입니다. 파일마다 다른 규칙을 적용하도록 PurgeCSS에 지시해야 합니다. 다행스럽게도 PostCSS에는 정보로 가득 찬 컨텍스트가 있습니다.
따라서 정보 컨텍스트를 환경에 전달할 수 있습니다.
module.exports = ctx => environment(ctx);
환경에 컨텍스트 변수 추가
const environment = ctx => ({
plugins: [
require("postcss-import"),
require("postcss-flexbugs-fixes"),
require("postcss-preset-env")({
autoprefixer: {
flexbox: "no-2009"
},
stage: 3
}),
purgeCss(ctx)
]
});
이 컨텍스트로 PurgeCss 플러그인을 호출합니다.
const purgeCss = ({ file }) => {
return require("@fullhuman/postcss-purgecss")({
content: htmlFilePatterns(file.basename),
defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || []
});
};
이제 PurgeCss에 파일 이름이 있으므로 각 파일에 대해 다른 규칙을 지정할 수 있습니다. 내 중요한 CSS의 경우 홈 페이지와 관련된 페이지와 다른 모든 파일에 대한 일반적인 패턴 세트만 지정합니다.
const htmlFilePatterns = filename => {
switch (filename) {
case "critical.scss":
return [
"./app/views/pages/index.html.erb",
"./app/views/shared/_navbar.html.erb",
"./app/views/layouts/application.html.erb"
];
default:
return [
"./app/**/*.html.erb",
"./config/initializers/simple_form_bootstrap.rb",
"./app/helpers/**/*.rb",
"./app/javascript/**/*.js"
];
}
};
그래서 전체, 그것은 그렇게 보인다
// postcss.config.js
const environment = ctx => ({
plugins: [
require("postcss-import"),
require("postcss-flexbugs-fixes"),
require("postcss-preset-env")({
autoprefixer: {
flexbox: "no-2009"
},
stage: 3
}),
purgeCss(ctx)
]
});
const purgeCss = ({ file }) => {
return require("@fullhuman/postcss-purgecss")({
content: htmlFilePatterns(file.basename),
defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || [],
});
};
const htmlFilePatterns = filename => {
switch (filename) {
case "critical.scss":
return [
"./app/views/pages/index.html.erb",
"./app/views/shared/_navbar.html.erb",
"./app/views/layouts/application.html.erb"
];
default:
return [
"./app/**/*.html.erb",
"./config/initializers/simple_form_bootstrap.rb",
"./app/helpers/**/*.rb",
"./app/javascript/**/*.js"
];
}
};
module.exports = ctx => environment(ctx);
결과
작은 테스트에서 나는 그 결과를 얻었습니다.
BAMMMMM 🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉
Webpacker의 인라인 CSS
내 CSS 파일을 HTML에 인라인하기 위해 머리를 약간 긁었습니다. Stackoverflow 덕분에 여기에서 도움을 받을 수 있었습니다.
<% if current_page?(root_path) %>
<!-- Inline the critical CSS -->
<style>
<%= File.read(File.join(Rails.root, 'public', Webpacker.manifest.lookup('critical.css'))).html_safe %>
</style>
<!-- Lazy load the rest with loadCSS -->
<link rel="preload" href="<%= Webpacker.manifest.lookup('application.css') %>" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="<%= Webpacker.manifest.lookup('application.css') %>"></noscript>
<% else %>
<%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
<% end %>
짜잔!!!!
데모: https://sprockets-less-rails6.herokuapp.com
소스 코드: https://github.com/adrienpoly/sprockets-less-rails6
Reference
이 문제에 관하여(Rails 및 Webpacker를 사용한 중요한 CSS - SprocketsLess 1부), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/adrienpoly/critical-css-with-rails-and-webpacker-sprocketsless-part-1-2bck텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)