高效壓縮CSS文件束的體積
前言
今日早讀文章由 @Asterisk 翻譯投稿分享。
正文從這開始~
今年年初我離開了資訊公司並開始搭建GO2CINEMA 站——一個英國的貓眼電影。我做了一系列優秀的工作來讓它更快更簡單更安全。而我的習慣是,追求極致的渲染優化。
我用ūsus(https://github.com/gajus/usus) 解決了HTML的預渲染,ūsus用單頁面HTML和內聯CSS來渲染頁面,而我不喜歡內聯70kb 的CSS在每個HTML文檔里,尤其是裡面大部分是CSS的選擇器類名。
就像谷歌做的那樣
你是否曾經瞄過一眼谷歌的頁面代碼,你第一件注意到的事就是CSS的選擇器名不會超過一對單詞的長度。
但是如何處理呢?
CSS壓縮工具的缺點
有一點是壓縮工具沒法做到的 改變選擇器的名字,這使得CSS的壓縮器沒法控制HTML的輸出。與此同時,CSS的名字會很長,如果你使用CSS模塊化開發,你的CSS模塊很有可能包括了 樣式表文件的名字、本地用於識別的獨立名稱和一串隨機哈希。css載入器的配置會修飾類名模板的名稱,舉個例子[name]___[local]___[hash:base64:5]。
因此,一個典型的類名會看起來像這樣:.MovieView___movie-title___yvKVV ;如果你很喜歡詳細描述類名,它有可能會變得更長,舉個例子.MovieView___movie-description-with-summary-paragraph___yvKVV .
在打包的時候對CSS的類名重命名
而好消息是,如果你用webpack和babel-plugin-react-css-modules,你可以在打包的時候用css-loader getLocalIdent (https://github.com/webpack-contrib/css-loader)或者babel-plugin-react-css-modules generateScopedName(https://github.com/gajus/babel-plugin-react-css-modules#configuration)重命名類名。
//webpack.configuration.js
/**
* @file Webpack configuration.
*/
constpath=require( path );
constgenerateScopedName=(localName,resourcePath)=>{
constcomponentName=resourcePath.split( / ).slice(-2,-1);
returncomponentName+ _ +localName;
};
module.exports={
module:{
rules:[
{
include:path.resolve(__dirname, ../app ),
loader: babel-loader ,
options:{
babelrc:false,
extends:path.resolve(__dirname, ../app/webpack.production.babelrc ),
plugins:[
[
react-css-modules ,
{
context:common.context,
filetypes:{
.scss :{
syntax: postcss-scss
}
},
generateScopedName,
webpackHotModuleReloading:false
}
]
]
},
test:/.js$/
},
{
test:/.scss$/,
use:[
{
loader: css-loader ,
options:{
camelCase:true,
getLocalIdent:(context,localIdentName,localName)=>{
returngenerateScopedName(localName,context.resourcePath);
},
importLoaders:1,
minimize:true,
modules:true
}
},
resolve-url-loader
]
}
]
},
output:{
filename: [name].[chunkhash].js ,
path:path.join(__dirname, ./.dist ),
publicPath: /static/
},
stats: minimal
};
縮短命名
通過使用babel-plugin-react-css-modules 和 css-loader的相同邏輯來命名,我們可以按我們自己的想法隨意改別類名,甚至是隨機哈希。而更進一步,我想要更短的選擇器類名來直接代替隨機哈希。為了改變類名,我創建了一個類名入口然後用incstr(https://github.com/grabantot/incstr)來改寫每個通過這個入口的不斷增加的 ID。
//createUniqueIdGenerator.js
constincstr=require( incstr );
constcreateUniqueIdGenerator=()=>{
constindex={};
constgenerateNextId=incstr.idGenerator({
// Removed "d" letter to avoid accidental "ad" construct.
// @see https://medium.com/@mbrevda/just-make-sure-ad-isnt-being-used-as-a-class-name-prefix-or-you-might-suffer-the-wrath-of-the-558d65502793
alphabet: abcefghijklmnopqrstuvwxyz0123456789
});
return(name)=>{
if(index[name]){
returnindex[name];
}
letnextId;
do{
// Class name cannot start with a number.
nextId=generateNextId();
}while(/^[0-9]/.test(nextId));
index[name]=generateNextId();
returnindex[name];
};
};
constuniqueIdGenerator=createUniqueIdGenerator();
constgenerateScopedName=(localName,resourcePath)=>{
constcomponentName=resourcePath.split( / ).slice(-2,-1);
returnuniqueIdGenerator(componentName)+ _ +uniqueIdGenerator(localName);
};
這樣就能改造出既短又唯一的類名。現在.a_a, .b_a 諸如此類的類名會代替
.MovieView___movie-title___yvKVV 和 .MovieView___movie-description-with-summary-paragraph___yvKVV
這使得GO2CINEMA的css文件束從140kb壓縮到53kb
使用作用域隔離進一步壓縮文件束體積
我會加下劃線_在CSS類名里去分割組件名和識別名稱——這種區分方法有助於壓縮。
csso(CSS壓縮工具)有作用域設置。作用域里定義了一個類名列表用於做一些專門的標記,即不同作用域的選擇器不會選中污染同一個元素,這使得優化方案能更規範地修改規則。利用這個,使用csso-webpack-plugin(https://github.com/zoobestik/csso-webpack-plugin)來後期處理CSS的文件束。
//getScopes.js
constgetScopes=(ast)=>{
constscopes={};
constgetModuleID=(className)=>{
consttokens=className.split( _ )[];
if(tokens.length!==2){
return default ;
}
returntokens[];
};
csso.syntax.walk(ast,node=>{
if(node.type=== ClassSelector ){
constmoduleId=getModuleID(node.name);
if(moduleId){
if(!scopes[moduleId]){
scopes[moduleId]=[];
}
if(!scopes[moduleId].includes(node.name)){
scopes[moduleId].push(node.name);
}
}
}
});
returnObject.values(scopes);
};
是否值得
第一個爭議是這種壓縮本身壓縮演算法就可以幫你做到。GO2CINEMA的CSS文件束壓縮使用的是Brotli演算法,比起原來的長類名的文件束只節省了1kb的體積。另一方面,設置這種壓縮只是一次性投資並且這樣減少的文檔體積需要被解析。它有另一種好處,可以有效阻止那些通過CSS類名來掃描廣告的反廣告屏蔽插件。
關於本文
譯者:@Asterisk
作者:@Gajus Kuizinas
原文:https://medium.freecodecamp.org/reducing-css-bundle-size-70-by-cutting-the-class-names-and-using-scope-isolation-625440de600b
點擊展開全文
※深入PostCSS Web設計
※【第1006期】ECMAScript 6 新特性
※從移動端click到搖一搖
※你不應該錯過的前端技術會議
※Nodejs cluster模塊深入探究
TAG:前端早讀課 |
※七牛雲CDN鏡像存儲加快圖片/CSS/JS文件訪問速度,支持申請免費SSL
※IBM存儲大舉強化文件存儲軟體和NVMeoF支持
※PHP 生成 CSV 文件
※如何在 Linux 中壓縮和解壓縮文件
※文件存儲CFS
※利用MATLAB批量對文件重命名
※ASP 引用文件
※CSV配置文件的優化策略
※超全實用簡約的一套素材包PSD和Sketch源文件下載
※JSP 文件上傳
※GMP文件體系需要不斷的完善
※在CDR軟體中導入 AI、PS和PDF 文件的方法
※ISO鏡像文件中發現惡意軟體
※Excel文件加圖片後體積爆表?一招壓縮二十倍
※Finder新功能:對桌面文件進行高效整合
※Excel文件加圖片後體積爆表?一招壓縮到5%
※域滲透——獲得域控伺服器的NTDS.dit文件
※SSM框架整合裡面的一些配置文件
※WinRAR漏洞曝光:可植入惡意文件 需儘快升級
※ZStack無縫融合阿里雲NAS模塊,文件存儲服務再升級!