grunt-uncss Built with Grunt

NPM version
Build Status
Dependency Status
devDependency Status

一个用于从项目中移除未使用的CSS的Grunt插件。可以跨多个文件工作,以及支持通过PhantomJS动态注入CSS。

预览

让一个使用Bootstrap的多页面项目的CSS从>120KB降到11KB。

deme

入门

这个插件需要Grunt ~0.4.0支持。

如果在此之前你还没用过Grunt,务必先看以下新手入门指南,它解释了如何创建一个Gruntfile以及安装和使用Grunt插件。一旦你熟悉了这个过程,你可以使用这个命令来安装这个插件:

  1. npm install grunt-uncss --save-dev

安装好这个插件之后,你还需要在Gruntfile中加入这行JavaScript来启用这个插件。

  1. grunt.loadNpmTasks('grunt-uncss');

Uncss任务

要使用grunt uncss命令运行这个任务。

任务目标,文件和选项可以按照配置任务指南来指定。

使用uncss时可以从项目中移除未使用的CSS。

用法

可以通过为你的干净的CSS文件指定一个目标(文件)来使用grunt-uncss任务。下面以dist/css/tidy.css为例。

意思就是指定一个目标文件,最后移除未使用的CSS之后生成的干净的文件就会放到指定的这个文件中。

在目标文件旁边,指定你想扫描使用了那些选择器的HTML文件。下面以我项检查的app/index.htmlapp/about.html为例。

意思就是说,你要检查哪些html使用了哪些CSS,然后让生成的CSS只包含这些页面中使用到的CSS。

  1. uncss: {
  2. dist: {
  3. files: {
  4. 'dist/css/tidy.css': ['app/index.html', 'app/about.html']
  5. }
  6. }
  7. }

然后你就可以使用一个诸如processhtml的处理程序来重写你的样式表为tidy.css,使用一个像这样的块就行了:

意思就是用生成的文件,替换html中的旧样式引用

  1. <!-- build:css css/tidy.css -->
  2. <link rel="stylesheet" href="css/normalize.css">
  3. <link rel="stylesheet" href="css/main.css">
  4. <link rel="stylesheet" href="css/bootstrap.css">
  5. <!-- /build -->

一些其他的配置长这个样子:

  1. processhtml: {
  2. dist: {
  3. files: {
  4. 'dist/index.html': ['app/index.html'],
  5. 'dist/about.html': ['app/about.html']
  6. }
  7. }
  8. }

选项(Options)

一个使用了所有支持的选项的示例:

  1. uncss: {
  2. dist: {
  3. options: {
  4. ignore : ['#added_at_runtime', /test\-[0-9]+/],
  5. media : ['(min-width: 700px) handheld and (orientation: landscape)'],
  6. csspath : '../public/css/',
  7. raw : 'h1 { color: green }',
  8. stylesheets : ['lib/bootstrap/dist/css/bootstrap.css', 'src/public/css/main.css'],
  9. ignoreSheets : [/fonts.googleapis/],
  10. urls : ['http://localhost:3000/mypage', '...'], // 已过时
  11. timeout : 1000,
  12. htmlroot : 'public',
  13. report : 'min'
  14. },
  15. files: {
  16. 'dist/css/tidy.css': ['app/index.html', 'app/about.html']
  17. }
  18. }
  19. }

这些选项都做些什么?

  • ignore (Array - 数组): 提供一个不应该使用UnCSS移除的选择器列表。例如,添加给用户与页面交互的样式(hoverclick),因为这些暂时不能让UnCSS探测到。可以使用字面量模式和正则表达式匹配模式。

  • media (Array - 数组): 默认情况下UnCSS值处理带”all”, “screen”的媒体查询样式和那些没指定这些参数的。使用这个选项可以指定要包含进来的其他媒体查询标识。

  • csspath (String - 字符串): 相对于HTML文件的CSS的相对路径。默认情况下,UnCSS使用指定的<link rel="stylesheet" href="path/to/file.css">路径。

  • raw (String - 字符串): 给这个任务提供一个原生的CSS字符串,这个字符串会添加到现有的样式表选项中;当你的CSS还没写入磁盘时这个选项有利于让脚本使用。(原文没理解透,这个翻译不准确)

译注:就是说,使用这个选项硬编码一些CSS规则,最后会插入到输出的CSS文件的底部,放到底部可以继承上面的规则。PS:不支持非标准样式定义语法字符串。- 感谢Grunt群@飘渺大神提供测试信息。

  • stylesheets (Array - 数组): 使用这些指定的样式表,而不是从HTML文件中提取的那些。

  • ignoreSheets (Array - 数组): 不包含指定的样式表。

  • urls (Array - 数组): 使用Phantom加载的URL数组(on top of the files already passed if any)。

没用过,不了解括号里这句怎么翻译。

  • timeout (Number - 数字): 指定花多长时间等待JS先加载完成。

  • htmlroot (String - 字符串): 项目的根目录。比如你在本地文件上运行UnCSS时,有绝对路径形式的样式表,比如:href="/css/style.css",这个选项就很有用啦。

  • report (‘min’/‘gzip’): 指定是否只打印出(输出)压缩结果或者报告压缩和gzip结果,但是这是在使用maxmin的情况下。

用例

  1. // 跨多个文件移除未使用的CSS
  2. uncss: {
  3. dist: {
  4. files: {
  5. 'dist/css/tidy.css': ['app/index.html', 'app/about.html']
  6. }
  7. }
  8. }
  1. // 跨多个文件移除未使用的CSS,同时忽略指定的选择器
  2. uncss: {
  3. dist: {
  4. files: {
  5. 'dist/css/tidy.css': ['app/index.html', 'app/about.html']
  6. }
  7. },
  8. options: {
  9. ignore: ['#added_at_runtime', '.created_by_jQuery']
  10. }
  11. },
  12. options: {
  13. ignore: ['#added_at_runtime', '.created_by_jQuery']
  14. }
  15. }

测试项目

test/app目录下面包含了一个测试项目,你可以在使用npm install安装依赖之后通过运行grunt命令来构建它。它还包含了一个获取构建前后CSS尺寸信息的grunt compare_size任务:

grunt-uncss - 一个用于从项目中移除未使用的CSS的Grunt插件 - 图7

问题

Bootstrap, TopCoat 等等这类用于界面库相当多,然而许多开发者都只会适应它们所提供的少于10%的CSS(大部分情况下,都不会完全使用到)。 其结果可想而知,它们会以生成大量冗余的样式而告终,这会显著增加页面的加载时间并且影响你的心情。

grunt-uncss 基于选择器检测,视图帮助大家生成只在项目中使用到的CSS。

一些研究成果和替代解决方案

过去,为视图解决未使用的CSS的问题已经付出了很多努力。Opera创建了ucss@aandand创建了https://github.com/aanand/deadweight,Brian Le Roux创建了CSS Slap Chop,还有一系列静心制作的客户端解决方案,比如Helium-CSS
CSSESS以及基于Python的mincss

不幸地是,大多数这些解决方案实际上并不会生成你真正想要的 - 精简构建出只包含你项目中用到的CSS规则。最近发现一个名为uncss的项目尝试解决这一问题,然后我就着手分享一些开发者们在这个领域需要解决的一些问题,然后构建了一个Grunt任务来让它用起来更容易。

非常感谢Giacomo Martino的为这一任务使用的Node模块提供的帮助。

相关报道

局限性(Limitations)

请注意uncss模块中使用的CSS解析器目前无法处理复杂的选择器。比如[data-section=''] > section > [data-section-title] a。这意味着在使用这个插件构建时可能会碰到诸如TypeError: Cannot convert undefined or null to object这样的异常。如果碰到这种情况,尽量考虑把这些复杂的选择器移到单独的文件中,然后不要用这个插件来检测它们。

我们也在积极的寻找和改善CSS解析器,一旦解决这一问题,我们会在这里发布公告。

License

(C) Addy Osmani 2014, released under the MIT license