postcss-lazysprite: 一種生成CSS 雪碧圖的懶惰姿式

本文原文連接:https://devework.com/postcss-...,轉載請註明原始來源,謝謝!javascript

411939171020170422.png

postcss-lazysprite 是一個基於PostCSS 開發的用於生成雪碧圖圖片及其CSS 的插件,通過半年持續迭代,現已穩定用在微信旗下兩款產品的Web 業務中。其與市面上的雪碧圖插件不一樣在於生成雪碧圖的「懶惰」姿式。css

前言

前端界,伴隨着雪碧圖這個概念出現,自動化工具產生雪碧圖這類工具就層出不窮。不管是早期GUI 工具,仍是如今流行的配合Gulp/Grunt/Webpack 這類構建工具而產生的雪碧圖插件。總之是百花齊放,長江後浪推前浪。html

根據輸入方式的不一樣,如今市面上基於Node.js 的雪碧圖構建工具通常可分爲以下兩種(若有不實,望予以指出):前端

一種是如今國外常見的基於spritesmith 的各種經過構建工具註冊任務進行合併產生雪碧圖的插件,如gulp-sprite、css-sprite、sprity 等。java

// 本段代碼來自sprity 的sample
gulp.task('sprites', function () {
  return sprity.src({
    src: './src/images/**/*.{png,jpg}',
    style: './sprite.css',
    processor: 'sass',
  })
  .pipe(gulpif('*.png', gulp.dest('./dist/img/'), gulp.dest('./dist/css/')))
});

另外一種是國內以cssgaga、gulp-tmtsprite 爲表明的,在開發階段是寫單個小圖的CSS 樣式,而後也是經過構建工具的註冊任務進行合併產生雪碧圖的插件。git

// 本段代碼來自gulp-tmtsprite 的sample
// Input
.icon-test {
    width: 32px;
    height: 32px;
    background-image: url(../slice/test.png);
}

// Output
.icon-test {
    background-image: url(../sprite/style-index.png);
}
 
@media only screen and (-webkit-min-device-pixel-ratio: 2), 
only screen and (min--moz-device-pixel-ratio: 2), 
only screen and (-webkit-min-device-pixel-ratio: 2.5), 
only screen and (min-resolution: 240dpi) {
.icon-test { 
    background-image:url("../sprite/style-index@2x.png");
    background-position: -36px -66px;
    background-size: 32px;
}
}

對比與不一樣

各種工具自己有其合理存在的理由與最適合的使用場景,去褒貶來陪襯我這個插件並非本文的目的。如上面介紹的兩種類型的插件,一種是將雪碧圖合成從常規的寫CSS 行爲中抽離出來,一種是後編譯的雪碧圖合成,其使用場景各不相同。本文介紹的postcss-lazysprite,在於解決的場景是:我想在開發階段就生成雪碧圖並用上其CSS,同時我又想很方便地產生,用起來越簡單越好。所謂lazysprite,就是期許一種「懶惰」的方式去生成雪碧圖。github

postcss-lazysprite 用起來就是那麼簡單,通過配置後,你只須要這樣寫:web

/* ./src/css/index.css */
@lazysprite "filetype";

輸出的天然是完整的雪碧圖以及相應CSS:npm

/* ./dist/css/index.css */
.icon-filetype-doc {
    background-image: url(../sprites/filetype.3f1f178013.png);
    background-position: 0 0;
    width: 80px;
    height: 80px;
}

@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio:2), only screen and (-o-min-device-pixel-ratio:2/1), only screen and (min-device-pixel-ratio:2), only screen and (min-resolution:2dppx), only screen and (min-resolution:192dpi) {
    .icon-filetype-doc {
        background-image: url(../sprites/filetype@2x.cbed5ca6a9.png);
        background-position: 0 0;
        background-size: 170px 170px;
    }
}

假設後面要新增圖片到filetype 文件夾,那麼直接丟進去就能自動從新合併並更新CSS;若是要新建一個與filetype 同級的文件夾(如logos),那麼在須要的位置@lazysprite "logos";便可。一切就是那麼簡單,所謂lazy,便是如此。gulp

若是你有用過Sass 框架Compass 的話,你會以爲跟Compass 的雪碧圖產生方式是如此相似。是的,這個插件就是沿用了Compass 的雪碧圖思路,甚至這個插件的的底層就是spritesmith 驅動的,而我在寫這個插件的時候參考了postcss-sprite 的寫法——整個插件實際上是在前端開源環境下,結合自身的需求而來的產物。

介紹

可能有讀者看到這裏還不是很清楚postcss-sprite 的運做方式。這裏以Gulp 構建流爲例,講述下其運做方式。

假設你的項目目錄以下:

.
├── gulpfile.js
├── dist
└── src
    ├── css
    │   └── index.css
    ├── html
    │   └── index.html
    └── slice
        └── filetype
            ├── doc.png
            ├── doc@2x.png
            ├── pdf.png
            └── pdf@2x.png

src 是放編譯前的CSS(如今通常是Sass 或Less 的源文件)以及雪碧圖源圖(即單個小圖);dist則是編譯後 CSS 及產生的雪碧圖圖片及其CSS。

而後在gulpfile.js 配置以下:

var gulp = require('gulp');
var postcss = require('gulp-postcss');
var lazysprite = require('postcss-lazysprite');

gulp.task('css', function () {
    return gulp.src('./src/css/**/*.css')
        .pipe(postcss([lazysprite({
            imagePath:'./src/slice',
            stylesheetInput: './src/css',
            stylesheetRelative: './dist/css',
            spritePath: './dist/slice',
            smartUpdate: true,
            nameSpace: 'icon-'
        })]))
        .pipe(gulp.dest('./test/dist/css'));
});

上面的每一個option 解釋下:

imagePath:雪碧圖小圖所在目錄;
stylesheetInput:CSS 文件所在的目錄,通常與gulp.src的路徑相關;
stylesheetRelative:爲了在生成的CSS 中構造相對路徑而引入,通常與gulp.dest的路徑相關;
spritePath:生成的雪碧圖放置的目錄;
smartUpdate: 是否啓用智能更新機制,關於smartUpdate,請見下一章節的介紹。
nameSpace:CSS 的命名空間。

注意下你的gulp css任務通常是gulp.watch以及默認任務的一部分。

而後你在src/css/index.css裏面寫下這段話:

@lazysprite "filetype";

輸出內容見上一章節相同部分,就不重複了。

filetype便是在spritePath: './dist/slice'定義的目錄下的子目錄,這個目錄下的全部雪碧圖小圖會合成爲一張雪碧圖,圖片名稱默認是以filetype.png命名。

同時filetype也會做爲生成的小圖對應CSS class 的一部分。CSS class 的構成便是「命名空間+目錄名+小圖片名」。如doc.png生成的對應類名爲.icon-filetype-doc——而後你在HTML 中引入CSS 文件,經過<i class="icon-filetype-doc"></i>用便可。

postcss-lazysprite 雖然是站在巨人的肩膀上的產物,但其仍是有很多亮點值得一說。

亮點

  • 支持 Retina 不是什麼新鮮事,但postcss-lazysprite 支持@2x, @3x, _2x, _3x這四種後綴的 Retina 圖片,並且'@'與'_'的命名徹底能夠混用。

  • 檢測到非標準 Retina 圖片會予以提示,如@2x 圖片非偶數尺寸的時候。

  • 支持Source Map,這個很少說,之因此是基於 Postcss 開發,就是爲了能支持Source Map。

  • 支持:hover、:active 這類場景,即一些如鼠標 hover 上去須要變logo 的場景。

  • 採用緩存方式以及SmartUpdate 以提高運行時候的性能。如本文開頭所言,postcss-lazysprite 目標是開發階段就能用上雪碧圖,因此緩存機制很重要,總不能在開發階段每保存一次 CSS 就從新走一遍「遍歷全部圖片並生成雪碧圖」的流程。因此只要在開發階段沒有動過圖片或修改@lazysprite 的代碼,除開發階段第一次啓動 Gulp 任務的時候,其它時間均不會重複運行相關流程。另外在配置了SmartUpdate後,會將生成的圖片文件名加入 hash,這樣下一次啓動 Gulp 任務的時候,只要源圖片沒有變化,也不會重複雪碧圖流程。

更多

npm 安裝:

npm i postcss-lazysprite -S

插件自己擁有近十個 opiton 方便用戶根據實際需求自定義相關細節,請參考 README 。

postcss-lazysprite 託管到 Github 上:https://github.com/Jeff2Ma/postcss-lazysprite,歡迎前往提 issues 或參與開發。固然,歡迎先送個star ~

相關文章:

從0到1:PostCSS 插件開發最佳實踐

PostCSS 插件postcss-lazyimagecss:自動填寫width / height 屬性

本文原文連接:https://devework.com/postcss-...,轉載請註明原始來源,謝謝!

相關文章
相關標籤/搜索