如何刪除未使用的 CSS 代碼?
隨著前端項目的不斷迭代,就可能出現(xiàn)部分 CSS 代碼未使用的情況。這些未使用代碼就可能影響應用性能。
那么,如何有效地刪除未使用的 CSS 代碼呢?本文將介紹一種強大的工具——PurgeCSS,它可以自動檢測和刪除未使用的 CSS 代碼。無論是在 Vue、React 還是其他前端框架中,PurgeCSS 都能輕松集成。
接下來,讓我們一起探索如何配置和使用 PurgeCSS,以及一些高級配置選項,幫助我們根據(jù)項目需求定制刪除未使用的 CSS 代碼的過程!
未使用的 CSS
使用 Chrome 瀏覽器的 Coverage 面板,就可以看到當前頁面所有CSS 文件的使用情況(打開Coverage面板方式:Ctrl+Shift+P,搜索 Coverage):
這里顯示了每個文件的總大小、未使用的CSS 的大小、未使用的 CSS 所占比例。可以看到,文件中未使用的 CSS 占大多數(shù)。
點開一個文件,就可以看到這個文件中有哪些樣式使用了(藍色),有哪些樣式未使用(紅色):
默認情況下,瀏覽器必須下載、解析和處理它遇到的所有外部樣式表,然后才能將內(nèi)容渲染到用戶屏幕。每個外部樣式表都必須從網(wǎng)絡下載。這些額外的網(wǎng)絡任務會顯著增加用戶在屏幕上看到任何內(nèi)容之前必須等待的時間。
未使用的 CSS 還會減慢瀏覽器構建渲染樹的速度。渲染樹類似于 DOM 樹,不同之處在于它還包含每個節(jié)點的樣式。要構建渲染樹,瀏覽器必須遍歷整個 DOM 樹,并檢查哪些 CSS 規(guī)則適用于每個節(jié)點。未使用的 CSS 越多,瀏覽器可能需要花費更多的時間來計算每個節(jié)點的樣式。
PurgeCSS 是什么?
PurgeCSS 是一個用于刪除未使用的 CSS 的工具。它對于優(yōu)化應用通常很有用。當使用 Bulma、Bootstrap 或 Tailwind 等 CSS 框架時,就會有很多未使用的 CSS。這就是 PurgeCSS 的用武之地。它會分析內(nèi)容和 CSS 文件,以確定哪些樣式未使用,并將其刪除。PurgeCSS 可以與最常見的 JavaScript 庫/框架配合使用,例如 Vue.js、React、Gatsby 等。
雖然 PurgeCSS 并不是刪除未使用的 CSS 的唯一工具,但它因其模塊化、易用性和廣泛的自定義選項而脫穎而出。模塊化使開發(fā)人員能夠為特定用例和框架創(chuàng)建模塊提取器。提取器是讀取文件內(nèi)容并提取所使用的 CSS 選擇器列表的函數(shù)。
PurgeCSS 提供了一個非常可靠的默認提取器,可以處理多種文件類型。但是,默認情況下,PurgeCSS 會忽略包含 @、:和 / 等特殊字符的未使用 CSS 代碼。因此,PurgeCSS 可能無法完全適配你正在使用的文件類型或 CSS 框架。
此外,PurgeCSS 還有很多配置項,可以根據(jù)需求自定義其行為。例如,PurgeCSS 包括針對 fontFace、keyframes、extractors、CSS 等選項。定制化可以改善 PurgeCSS 的性能和效率。PurgeCSS 很容易上手,并提供了詳細的文檔。截至撰寫本文時,PurgeCSS 在 npm 上每周下載量超過 90 萬次,GitHub[1] 上獲得了 7.4k+ Star。
PurgeCSS 是如何工作的?
PurgeCSS 適合在生產(chǎn)環(huán)境使用,可以分析內(nèi)容和 CSS 并刪除未使用的樣式。在開發(fā)過程中運行 PurgeCSS 是沒必要的,因為在開發(fā)過程中,可能會經(jīng)常創(chuàng)建未使用的樣式,這意味著每次都必須運行 PurgeCSS。
相反,可以僅針對生產(chǎn)構建運行它。這樣,就不必重新創(chuàng)建已刪除的樣式。因此,當應用準備好投入生產(chǎn)時,可以運行 PurgeCSS 一次。在開始將 PurgeCSS 與流行的庫/框架一起使用之前,先來看一下它如何與普通 JavaScript 一起使用。代碼如下:
(async () => {
const purgecss = await new PurgeCSS().purge({
content: ['index.html'],
css: ['style.css'],
});
console.log(purgecss);
})();
這里將 index.html 指定為內(nèi)容之一,將style.css指定為 CSS 之一,可以包含更多的內(nèi)容和 CSS 文件,并且內(nèi)容不限于 HTML 文件。上面的代碼會返回已清除樣式的數(shù)組。
除了 content 和 css 之外,還有更多配置項可以準確指定想要它做什么以及如何做。上面的例子可以用于任何普通 JavaScript 項目。要使用 PurgeCSS,就需要有一個單獨的 JavaScript 文件,其將運行一次以刪除未使用的樣式。
可以通過以下代碼讓清除的樣式替換當前樣式:
const { PurgeCSS } = require('purgecss');
const fs = require('fs');
(async () => {
const purgecss = await new PurgeCSS().purge({
content: ['index.html'],
css: ['style.css'],
});
fs.writeFileSync('style.css', purgecss[0].css);
})();
與JS庫/框架結合使用
PurgeCSS 與流行的 JavaScript 庫/框架是兼容的,如 React、Vue、Gatsby、Next.js、Nuxt.js 等。下面來看看如何將 PurgeCSS 與 React 和 Vue 一起使用。
React + PurgeCSS
首先需要安裝 PurgeCSS 及其依賴項:
npm i --save-dev @fullhuman/postcss-purgecss
打開 App.js 文件并粘貼以下代碼:
import "./App.css";
function App() {
return <div className="App"></div>;
}
export default App;
在上面的代碼中,我們創(chuàng)建了一個名為 App 的函數(shù)組件,并返回了一個類名為 App 的 div。App.css 保持不變,因此它包含以下未使用的 CSS 代碼:
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
打開 package.json 文件并在 script 下添加以下代碼:
"postbuild": "purgecss --css build/static/css/*.css --content build/index.html build/static/js/*.js --output build/static/css"
post 是一個前綴,可以添加到任何 npm 腳本中,并在運行主腳本時自動運行。在這個例子中,postbuild 在執(zhí)行構建腳本后運行。postbuild 執(zhí)行的命令包含三個選項。
- --css 選項:指定 PurgeCSS 應處理的 CSS 文件,它可以是文件名數(shù)組或全局變量。
- --content 選項:指定 PurgeCSS 應分析哪些內(nèi)容。
- --output 選項:指定應將純化的 CSS 文件寫入哪個目錄。默認情況下,它將結果放置在控制臺中。
本質(zhì)上,postbuild 執(zhí)行的命令執(zhí)行以下操作:
- 檢查 build/static/css 中的每個 CSS 文件。
- 匹配文件中使用的選擇器并刪除任何未使用的 CSS。
- 在 build/static/css 中輸出新的 CSS 文件。
現(xiàn)在,只需要運行 npm run build 來運行 React 應用的構建。要確認是否成功,可以打開 build/static/css 中的 CSS 文件。輸出類似于下面的代碼,僅包含使用的 CSS:
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
margin: 0;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, Courier New, monospace;
}
.App {
text-align: center;
}
@-webkit-keyframes App-logo-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(1turn);
transform: rotate(1turn);
}
}
@keyframes App-logo-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(1turn);
transform: rotate(1turn);
}
}
Vue + PurgeCSS
可以通過以下方式在 Vue 中安裝 PurgeCSS:
vue add @fullhuman/purgecss
這將生成一個 postcss.config.js 文件,在這個文件中已經(jīng)設置了適合 Vue 應用的PurgeCSS 配置。可以根據(jù)需要更改這些配置。
下面來更新一些應用的內(nèi)容,看看 PurgeCSS 在 Vue 中的工作原理。轉(zhuǎn)到 HelloWorld.vue 并用以下代碼替換其中的代碼:
<template>
<a href="#">Hello world</a>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String,
},
};
</script>
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
span {
color: red;
}
</style>
這里減少了內(nèi)容并添加了一些未使用的樣式。現(xiàn)在,在終端中運行 npm run build 來構建應用并查看最終構建的 CSS。最后,在 dist/css 目錄中打開 CSS 文件,就可以找到只包含已使用樣式的 CSS 輸出:
a[data-v-70cf4e96] {
color: #42b983;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
高級配置選項
上面只看到了三個配置選項:content、css 和 outline,下面來看看如何通過其他配置選項來自定義 PurgeCSS。
keyframes 和 fontfaces
在 PurgeCSS v2.0 之前,默認刪除未使用的字體和關鍵幀代碼。然而,當這些功能使用不當時,代碼就會崩潰。未使用的字體和關鍵幀代碼現(xiàn)在默認保持不變。可以通過將 keyframes 和 fontfaces 選項設置為 true 來更改此默認行為:
(async () => {
const purgecss = await new PurgeCSS().purge({
content: ['index.html'],
css: ['style.css'],
keyframes: true,
fontFaces: true,
});
console.log(purgecss);
})();
也可以在 purgecss.config.js 配置文件中修改這些配置項:
// purgecss.config.js
module.exports = {
content: ['index.html'],
css: ['style.css'],
keyframes: true,
fontFaces: true,
}
(async () => {
const purgecss = await new PurgeCSS().purge('./purgecss.config.js');
console.log(purgecss);
})();
content 和 css
可以直接傳入 content 和 css 的值,而無需鏈接一個文件:
// purgecss.config.js
module.exports = {
content: [
{
raw: '<html><body><p>Hello world</p></body></html>',
extension: 'html',
},
],
css: [
{
raw: 'p { color: red }',
},
],
};
extractors
在極少數(shù)情況下,PurgeCSS 可能無法刪除未使用的 CSS 或刪除已使用的 CSS。在這種情況下,必須使用自定義提取器。PurgeCSS 依賴提取器來獲取文件中使用的選擇器列表。
有些軟件包為特定擴展提供了提取器。例如,purgecss-from-js 特定于 .js 擴展名。使用特定的提取器進行擴展可以提供最佳的準確性:
// purgecss.config.js
import purgeJs from 'purgecss-from-js'
import purgeHtml from 'purgecss-from-html'
const options = {
content: ['index.html'],
css: ['style.css'],
extractors: [
{
extractor: purgeJs,
extensions: ['js']
},
{
extractor: purgeHtml,
extensions: ['html']
}
]
}
export default options
variables
默認情況下,不會刪除未使用的 CSS 變量。如果要刪除它們,則必須在 purgecss.config.js 文件中將變量指定為 true:
module.exports = {
content: ['index.html'],
css: ['style.css'],
variables: true,
}
safelist 和 comments
PurgeCSS 支持指定哪些選擇器可以安全地保留在最終的 CSS 中。可以通過兩種方式來完成此操作:PurgeCSS 的 safelist 選項或特殊的 CSS 特殊注釋。使用 safelist:
module.exports = {
content: ['index.html'],
css: ['style.css'],
safelist: ['random', 'button'],
}
在這種情況下,.random、#random、button、.button 和 #button 都將被忽略,不會被 PurgeCSS 刪除。其支持使用正則表達式:
module.exports = {
content: ['index.html'],
css: ['style.css'],
safelist: [/red$/, /^bg/],
}
在這種情況下,任何以 red 結尾(例如,bg-red、btn-red)或以 bg 開頭(例如,bg-blue、bg-red)的選擇器都不會被刪除。默認情況下,PurgeCSS 不會刪除注釋,僅刪除旨在自定義 PurgeCSS 行為的特殊注釋。
一組常見的特殊注釋用于指定哪些選擇器可以安全地保留在最終 CSS 中:
/* purgecss start ignore */
h1 {
color: pink;
font-size: 2rem;
}
/* purgecss end ignore */
相關鏈接
[1]GitHub: https://github.com/FullHuman/purgecss。