CleanCSS - 移除未使用的 CSS 代码
应用:CleanCSS
地址:https://dujun.eu.org/cleancss
功能:分析页面中引用的 CSS 文件,打包成单一的干净文件用于替换所有引用
适用:独立页面
一、缘起
我导航站用了开源项目WebStackPage,首次静态资源加载有 1.5M,一部分原因是它使用了第三方库,比如 Bootstrap。当然,第三方库只有少量代码实际被用到,所以我就想找个办法,把未使用的 CSS 代码移除,使得静态文件更小。
二、方案
很快就找到了这个网站https://unused-css.com/。它可以很好地实现我的需求,不过有一个小问题,它是收费的,最低 25 美元一个月。
Only paying users can download clean CSS files.
那怎么办呢?那就自己开发一个工具吧。
三、分析
清理 CSS 代码需要这么几步:
- 抓取页面 HTML 内容
- 找到页面引用的 CSS、JS 文件
- 分析 HTML、JS 文件中用到的样式
- 保留被用到的代码,打包成单一 CSS 文件
分别用到了下列工具:
(一) Puppeteer
使用 Puppeteer 抓取 HTML 原文和 CSS、JS 文件列表。示例代码如下:
const
puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
args: [
'--disable-gpu',
'--disable-dev-shm-usage',
'--disable-setuid-sandbox',
'--no-first-run',
'--no-sandbox',
'--no-zygote',
'--single-process'
]
});
const page = await browser.newPage();
await Promise.all([
page.coverage.startJSCoverage(),
page.coverage.startCSSCoverage(),
]);
await page.goto(fetchUrl, {'timeout': 30000, 'waitUntil': 'domcontentloaded'});
let html = await page.content();
const [jsCoverage, cssCoverage] = await Promise.all([
page.coverage.stopJSCoverage(),
page.coverage.stopCSSCoverage(),
]);
await browser.close();
console.log(JSON.stringify({html: html, js: jsCoverage, css: cssCoverage}));
})();
(二)purifycss
使用 purifycss 移除未使用的 CSS 代码。示例如下:
purifycss src/css/main.css src/css/bootstrap.css src/js/main.js --info --out src/dist/index.css
(三)csso
最后使用 csso 压缩。示例代码如下:
gulp.task('css', () =>
gulp.src(sourceFile)
.pipe(stylelint({
reporters: [
{formatter: 'string', console: true}
],
failAfterError: false
}))
.pipe(autoprefixer( //增加浏览器兼容前缀
{
overrideBrowserslist: ['> 5%', 'not dead']
}))
.pipe(cssMediaGroup())
.pipe(csso()) //压缩优化
.pipe(gulp.dest(targetDir)));
四、成果
以分析十年之约页面为例:
五、后记
(一)只支持明文调用
只能支持明文 CSS 代码调用的解析,例如:
$e.addClass('myClass');
不支持字面量表达式等调用,例如:
$e.addClass('my' + 'Class');
(二)执行开销较大
服务器配置低,执行较慢,需要耐心等待。