dataurize - CSS Sprites 的替代作法

此篇文章最近更新時間為2010-12-23 12:01:39 目前共有8篇留言

關於作者 - JosephJ

任職於 Faria。喜好戶外運動、2008 年 5 月完成「跑步環島」。對於新技術跟程式碼有著強烈的偏執狂。

CSS Sprites & Web Performance

CSS Sprites 已經變成網站追求效能優化的重要解決方案之一:把許多小的圖檔合為一大張圖、然後再用 CSS 定位(background-position)的方式顯示。如此可以減低許多的 Request,像 Yahoo! 奇摩首頁即用了許多。(例如:http://l.yimg.com/f/i/tw/hp/spirit/sprite_icos_100812v2.png)。

CSS Sprite 的缺點

但是我玩了一陣子後,覺得這真的不是人幹的,CSS Sprites 技術的應用太過於手工。想想每當有新的圖檔要加入時:你得用影像處理軟體打開你的 Sprite 圖檔、把圖片放入、得注意有沒有影響到原本的長與寬(有時定位會用 100%)、得注意間距是否夠多(以免出包)、圖片處理完後得寫程式定位... 這還不打緊,若是修改某張圖片的話,要在一大張圖中找到你要的小圖就是一個問題,而且若尺寸不同搞不好還會影響到其他圖片。真的是讓人很 Orz 的一個技術。

思考 Sprites 的改進方式

也因此我一直在思考是不是可以用工程與自動化的角度來做 CSS Sprite,第一個想到的就是在 Deploy 時(不牽扯原始檔)將所有 CSS 的圖檔合併成一個,自動加上定位與大小等 CSS 屬性。這樣的作法或許可行,但當時後端的技術能力還不太夠,且加上得強制規定大家背景圖檔的作法、彈性相當差,所以最後就不了了之... (對不起無名小站的同事們 XD)

一線曙光:Data URIs 與 IE MHTML

陸續一直有聽到 DataURI 將圖檔轉為 Base64 編碼的作法,好處是它就是一串編碼的長文字、完全不需要任何 Request,小缺點是編碼過後的文字通常比圖檔原有的檔案大小大 2 至 3 倍,不過別忘了網站文字檔大多支援 GZip。 Nicholas Zakas 大大證實 (Data URIs make CSS sprites obsolete) 經過 GZip 後、因為是文字、省的其實比較多!

雖然 IE 8 以前的版本不支援 DataURI,但是也有類似的技術叫 MHTML 可支援。當時我就很開心,或許未來真的可以不再把寶貴的時間浪費在 CSS Sprites!但... 最令人傻眼的就是翻遍所有美國的相關文章就是 MHTML 在一些情況下有缺陷 (Data URIs, MHTML and IE7/Win7/Vista blues)!沒想到救星出現了,而且是前陣子去北京百度認識的 aoao 的一篇文章:MHTML在ie7/vista bug 解决方案,拯救了我!其實根本只是其他人分隔符號未按照標準所導致 XD

著手開發新工具 dataurize:

當下確定可行之後,我就請同事們不要再用 CSS Sprites 的方式來做開發。最近終於有時間,花了兩天做了一個新工具,取名為 dataurize (github.com/josephj/dataurize) 又替公司開發流程補上一塊拼圖 :D 我的作法是寫一個 Shell Script,準備運用在 Deploy 時,把最小化後 CSS 中的所有背景圖檔抽出,塞入 DataURI,另外也把 MHTML 所需要的 Code 一起塞入到同一個檔案之中

Usage: dataurize $input $base [options]

    -o
    --output=$output    Assign an output file. By default it overwrites your original file.
    --print              Print output directly instead of generating or overwriting a file.
                         By default, this option is disabled.
    --separate=$output  Separate MHTML to a single file. By default, this option is disabled.
    --no-mhtml           Don't enable MHTML. Use this option if you don't want to use MHTML for legend IE.
                         It however doesn't hurt browser compatibility by adding *background-image().
                         By default, this option is disabled.
    --size-limit=$bytes It might still damage website performance if you transform an image with large file size.
                         The default file size is 1024 bytes.
    -h
    --help               Show this help.

Sample: dataurize foo.css http://bar.com/ --output=foo2.css

輸出的檔案會像這樣子,MHTML, Data URIs 全部混在一起:

你可以想像,這個 CSS 檔案將會變得非常的大,Nicholas Zakas 所講整理流量會變小其實只有 Data URIs 的部份,而不是像我 MHTML 也同樣在一個檔案中。

實際用在專案上的心得感想

光把想法實作出來很簡單,但如果不能用在專案上,那麼他終究還是個屁 XD

Case 1 - 圖檔簡單的情況

第一個使用的專案是圖檔簡單,大多小於 1KB 的情況,先看看經過 dataurize 前吧!

normal

50 個 Request 量實在太多了,過去我們一定得經過 CSS Sprites 做,但現在只要執行 dataurize 就可以得到下面的結果:

after

一個指令下去後,雖然檔案總傳輸量沒有減少太多,但圖檔 Requset 從 50 個變為 11 個就是非常大的改善!仔細看看 onload 與下載時間更是飛快許多,因為圖檔越少、被 Block 的機率也就越低、使用者體驗也將更好。

Case 2 : 圖檔複雜的情況

世事豈能盡如人意?我們的網站有許多需要大量 PNG 24 的情況!

case2

有許多超過 10K 的圖檔,如果全部都轉 Data URIs 加 MHTML 的話,由於 base64 編碼的加倍效果、再加上 MHTML 會乘以 2,用先前的作法轉,這一頁的 CSS 將會超過 1MB 以上,不可能接受!(抱歉,慘況當時忘記做截圖了 XD)

所以我就在程式中多放了一個 --size-limit 的 option,預設為 2KB,針對超過限制的圖檔一律不處理,還是以傳統 Reqeust 的方式下載!處理的結果看起來 much better!!

$ dataurize [本機來源 CSS 檔案] [有 http:// 開頭的 Base 路徑] --output=[輸出的 CSS 檔案] --size-limit=2048
case2-after

結語

目前已經將此工具套用在 deploy 流程上,這代表著我們的前端工程師不需要為了 Performance 做任何圖片處理的工,在 deploy 之後就可以取得最佳化的程式!節省工作時間多去喝下午茶才是王道啊

一些注意事項

  • Script 也支援將 MHTML 分開輸出到另一個檔案 (--separate=),也可以讓 IE 8+ 與其他瀏覽器效能加速更多
  • IE 6, 7, 8 都已經成功可用了。當然 Chrome, Firefox, Opera 也都 ok!
  • Nicolas Zakas 的 CSSEmbed 是我當初覺得可用的,但是實際用過發現它只能二擇一,而我的需求是 DataURI + MHTML 一起寫,且加上不懂 Java,就直接自己寫了 PHP。
  • Stoyan 的 DataSprites 在 IE 的問題還沒有修改掉,而且也沒有一些依專案需求所製作的 Options。
  • 我還會持續地修改此篇文章,也會有一些範例佐證,目前想要用的人可能只能先從 GitHub clone 下來玩玩啦! https://github.com/josephj/dataurize
  • 我蒐集的一些 DataURI 與 MHTML 的相關連結:http://www.delicious.com/josephj/datauri?sort=userdate&order=desc
  • 2010/12/28 新增 dataurize 的 Web 介面,方便大家直接試用:http://josephj.com/lab/dataurize/web/demo.php


Comments

  1. 网络推广方案 2011-08-02 14:25:42
    很棒呀,好家伙!
  2. lizn 2011-01-28 17:37:04
    腾讯的大神。。
  3. clayliao 2010-12-24 16:31:26
    好文! 大推!
  4. josephj 2010-12-24 15:05:57
    看完大家的 feedback 之後,真的是覺得自己是井底之蛙
    有這麼多好用的工具我卻不知道,以下只是花了 10 分鐘把幾個網站瀏覽一下的感想
    不對的地方請各位指正

    大家講的所有東西最能吸引我的就是 CSSGaga (ytzong 真牛啊!)
    唯一的可惜之處就是他是軟體,跟我那時去北京看到的感覺相近
    有非常多好用的概念、工具,多以軟體的方式呈現
    或許是產業流程不同所導致,對岸的前端朋友說他們碰不到服務器
    但這樣就會有手工的成份存在了

    Lemonade 的作法看了一下會有限制(例如要設定寬與高 + overflow:hidden)
    另外 RoR 不是我們的開發環境
    為了 sprite 做 on-the-fly 的 performance 也不佳
    我們有 CDN 的優勢也不知道該如何整合

    Compass 牽涉到 CSS 開發行為的改變
    我會希望不要改變原始碼的作法

    以上為個人淺見,但是覺得這三個工具都很棒
    又觸發了一些其他的想法,我會再花時間深入研究的
    感謝大家啊!!!
  5. hlb 2010-12-24 13:41:41
    補一下連結:http://beta.compass-style.org/help/tutorials/spriting/

    另外 Compass 也有 DataURI 的功能 http://compass-style.org/docs/reference/compass/helpers/inline-data/ ,不過沒有產出 MHTML 的功能,要來幫忙補一下嗎 :P
  6. hlb 2010-12-24 13:33:06
    新版 Compass 內建 Lemonade 的功能,所以也不用另外有套件 :P
  7. ytzong 2010-12-24 12:47:35
    CssGaga http://www.99css.com/?p=542
    集成了DataURI MHTML还有AutoSprite,可以试下:)
  8. tka 2010-12-24 12:11:48
    請問有考慮過 compass + Lemonade (http://www.hagenburger.net/BLOG/Lemonade-CSS-Sprites-for-Sass-Compass.html)的或是其他的作法嗎?

    如果有的話, 再請問不採用的原因是?
暱稱: 必填。
Email: 非必填。若填寫為不公開欄位,僅供站長參考聯繫。
內容: 必填。限 255 個字元以內。
驗證碼:
送出

Facebook Comment