設計更快的網頁(二):圖片替換

2018-11-09 22:00:00

歡迎回到我們為了構建更快網頁所寫的系列文章。上一篇討論了只通過圖片壓縮實現這個目標的方法。這個例子從一開始有 1.2MB 的“瀏覽器脂肪”,然後它減輕到了 488.9KB 的大小。但這還不夠快!那麼本文繼續來給瀏覽器“減肥”。你可能在這個過程中會認為我們所做的事情有點瘋狂,但一旦完成,你就會明白為什麼要這麼做了。

準備工作

本文再次從對網頁的分析開始。使用 Firefox 內建的截圖功能來對整個頁面進行截圖。你還需要用 sudo 來安裝 Inkscape:

$ sudo dnf install inkscape

如果你想了解 Inkscape 的用法,Fedora 雜誌上有幾篇現成的文章。本文僅會介紹一些基本的 SVG 優化方法以供 Web 使用。

分析

我們再來用 getfedora.org 的網頁來舉例。

Getfedora 的頁面,對其中的圖片做了標記

這次分析以圖形方式完成更好,這也就是它從螢幕截圖開始的原因。上面的截圖示記了頁面中的所有圖形元素。Fedora 網站團隊已經針對兩種情況措施(也有可能是四種,這樣更好)來替換影象了。社交媒體的圖示變成了字型的字形,而語言選擇器變成了 SVG.

我們有幾個可以替換的選擇:

  • CSS3
  • 字型
  • SVG
  • HTML5 Canvas

HTML5 Canvas

簡單來說,HTML5 Canvas 是一種 HTML 元素,它允許你藉助指令碼語言(通常是 JavaScript)在上面繪圖,不過它現在還沒有被廣泛使用。因為它可以使用指令碼語言來繪製,所以這個元素也可以用來做動畫。這裡有一些使用 HTML Canvas 實現的範例,比如三角形模式動態波浪字型動畫。不過,在這種情況下,似乎這也不是最好的選擇。

CSS3

使用層疊式樣式表,你可以繪製圖形,甚至可以讓它們動起來。CSS 常被用來繪製按鈕等元素。然而,使用 CSS 繪製的更複雜的圖形通常只能在技術演示頁面中看到。這是因為使用視覺來製作圖形依然要比使用程式碼來的更快一些。

字型

另外一種方式是使用字型來裝飾網頁,Fontawesome 在這方面很流行。比如,在這個例子中你可以使用字型來替換“Flavor”和“Spin”的圖示。這種方法有一個負面影響,但解決起來很容易,我們會在本系列的下一部分中來介紹。

SVG

這種圖形格式已經存在了很長時間,而且它總是在瀏覽器中被使用。有很長一段時間並非所有瀏覽器都支援它,不過現在這已經成為歷史了。所以,本例中圖形替換的最佳方法是使用 SVG.

為網頁優化 SVG

優化 SVG 以供網際網路使用,需要幾個步驟。

SVG 是一種 XML 方言。它用節點來描述圓形、矩形或文字路徑等元件。每個節點都是一個 XML 元素。為了保證程式碼簡潔,SVG 應該包含儘可能少的元素。

我們選用的 SVG 範例是帶有一個咖啡杯的圓形圖示。你有三種選項來用 SVG 描述它。

一個圓形元素,上面有一個咖啡杯

<circlestyle="opacity:1;fill:#717d82;fill-opacity:1;stroke:none;stroke-width:9.51950836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"id="path36"cx="68.414307"cy="130.71523"r="3.7620001" />

一個圓形路徑,上面有一個咖啡杯

<pathstyle="opacity:1;fill:#717d82;fill-opacity:1;stroke:none;stroke-width:1.60968435;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"d="m 68.414044,126.95318 a 3.7618673,3.7618673 0 0 0 -3.76153,3.76204 3.7618673,3.7618673 0 0 0 3.76153,3.76205 3.7618673,3.7618673 0 0 0 3.76206,-3.76205 3.7618673,3.7618673 0 0 0 -3.76206,-3.76204 z"id="path20" />

單一路徑

<pathstyle="opacity:1;fill:#717d82;fill-opacity:1;stroke:none;stroke-width:1.60968435;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"d="m 68.414044,126.95318 a 3.7618673,3.7618673 0 0 0 -3.76153,3.76204 3.7618673,3.7618673 0 0 0 3.76153,3.76205 3.7618673,3.7618673 0 0 0 3.76206,-3.76205 3.7618673,3.7618673 0 0 0 -3.76206,-3.76204 z m -1.21542,0.92656 h 2.40554 c 0.0913,0.21025 0.18256,0.42071 0.27387,0.63097 h 0.47284 v 0.60099 h -0.17984 l -0.1664,1.05989 h 0.24961 l -0.34779,1.96267 -0.21238,-0.003 -0.22326,1.41955 h -2.12492 l -0.22429,-1.41955 -0.22479,0.003 -0.34829,-1.96267 h 0.26304 l -0.16692,-1.05989 h -0.1669 v -0.60099 h 0.44752 c 0.0913,-0.21026 0.18206,-0.42072 0.27336,-0.63097 z m 0.12608,0.19068 c -0.0614,0.14155 -0.12351,0.28323 -0.185,0.42478 h 2.52336 c -0.0614,-0.14155 -0.12248,-0.28323 -0.18397,-0.42478 z m -0.65524,0.63097 v 0.21911 l 0.0594,5.2e-4 h 3.35844 l 0.0724,-5.2e-4 v -0.21911 z m 0.16846,0.41083 0.1669,1.05937 h 2.80603 l 0.16693,-1.05937 -1.57046,0.008 z m -0.061,1.25057 0.27956,1.5782 1.34411,-0.0145 1.34567,0.0145 0.28059,-1.5782 z m 1.62367,1.75441 -1.08519,0.0124 0.19325,1.2299 h 1.79835 l 0.19328,-1.2299 z"id="path2714"inkscape:connector-curvature="0" />

你應該可以看出,程式碼變得越來越複雜,需要更多的字元來描述它。當然,檔案中包含更多的字元,就會導致更大的尺寸。

節點清理

如果你在 Inkscape 中開啟了範例 SVG 按下 F2,就會啟用一個節點工具。你應該看到這樣的介面:

Inkscape - 激活節點工具

這個例子中有五個不必要的節點——就是直線中間的那些。要刪除它們,你可以使用已啟用的節點工具依次選中它們,並按下 Del 鍵。然後,選中這條線的定義節點,並使用工具列的工具把它們重新做成角。

Inkscape - 將節點變成角的工具

如果不修復這些角,我們還有方法可以定義這條曲線,這條曲線會被儲存,也就會增加檔案體積。你可以手動清理這些節點,因為它無法有效的自動完成。現在,你已經為下一階段做好了準備。

使用“另存為”功能,並選擇“優化的 SVG”。這會彈出一個視窗,你可以在裡面選擇移除或保留哪些成分。

Inkscape - “另存為”“優化的 SVG”

雖然這個 SVG 範例很小,但它還是從 3.2KB 減小到了 920 位元組,不到原有的三分之一。

回到 getfedora 的頁面:頁面主要部分的背景中的灰色沃羅諾伊圖,在經過本系列第一篇文章中的優化處理之後,從原先的 211.12 KB 減小到了 164.1 KB.

頁面中匯出的原始 SVG 有 1.9 MB 大小。經過這些 SVG 優化步驟後,它只有 500.4 KB 了。太大了?好吧,現在的藍色背景的體積是 564.98 KB。SVG 和 PNG 之間只有很小的差別。

壓縮檔案

$ ls -lhinsgesamt 928K-rw-r--r--. 1 user user 161K 19. Feb 19:44 grey-pattern.png-rw-rw-r--. 1 user user 160K 18. Feb 12:23 grey-pattern.png.gz-rw-r--r--. 1 user user 489K 19. Feb 19:43 greyscale-pattern-opti.svg-rw-rw-r--. 1 user user 112K 19. Feb 19:05 greyscale-pattern-opti.svg.gz

這是我為視覺化這個主題所做的一個小測試的輸出。你可能應該看到光柵圖形——PNG——已經被壓縮,不能再被壓縮了。而 SVG,它是一個 XML 檔案正相反。它是文字檔案,所以可被壓縮至原來的四分之一不到。因此,現在它的體積要比 PNG 小 50 KB 左右。

現代瀏覽器可以以原生方式處理壓縮檔案。所以,許多 Web 伺服器都開啟了 mod_deflate (Apache) 和 gzip (Nginx) 模式。這樣我們就可以在傳輸過程中節省空間。你可以在這兒看看你的伺服器是不是啟用了它。

生產工具

首先,沒有人希望每次都要用 Inkscape 來優化 SVG. 你可以在命令列中脫離 GUI 來執行 Inkscape,但你找不到選項來將 Inkscape SVG 轉換成優化的 SVG. 用這種方式只能匯出光柵影象。但是我們替代品:

  • SVGO (看起來開發過程已經不活躍了)
  • Scour

本例中我們使用 scour 來進行優化。先來安裝它:

$ sudo dnf install scour

要想自動優化 SVG 檔案,請執行 scour,就像這樣:

[user@localhost ]$ scour INPUT.svg OUTPUT.svg -p 3 --create-groups --renderer-workaround --strip-xml-prolog --remove-descriptive-elements --enable-comment-stripping --disable-embed-rasters --no-line-breaks --enable-id-stripping --shorten-ids

這就是第二部分的結尾了。在這部分中你應該學會了如何將光柵影象替換成 SVG,並對它進行優化以供使用。請繼續關注 Feroda 雜誌,第三篇即將出爐。