基於webpack的前端工程化開發解決方案探索(二):程式碼分割與圖片載入

大魔王薩格拉斯發表於2015-12-04

  今天我們繼續來進行webpack工程化開發的探索!

  首先來驗證上一篇文章   基於webpack的前端工程化開發解決方案探索(一):動態生成HTML  中的遺留問題:webpack將如何處理按需載入的資源,還能繼續通過AJAX進行非同步載入嗎?

  

  1. require.ensure

  在上一章我們已經知道通過require引入的資源,可以通過外掛讓webpack將其獨立成為單獨的檔案,然後向HTML中自動寫入路徑。那對於require.ensure情況又會是怎樣的情況呢?

  我們都知道webpack通過require.ensure來對我們的程式碼進行分割,將按需載入的程式碼單獨放在的塊檔案chunk中,然後在合適的時候非同步載入進入文件中。

  在webpack中引入的提取檔案外掛,是否影響這一功能呢?

  

   同樣的,這次我們對上次的專案進行了改動,具體程式碼可以檢視: https://github.com/xiaoyunchen/webpack

  

   首先,我們在JS下新增了一個components資料夾,用於存放自定義的元件,然後定義了一個dialog元件(dialog的實現請參考之前的文章,本章將對本部分進行簡化處理)。

  

  在dialog元件中我們定義了dialog所需的HTML模板,CSS樣式檔案,以及入口檔案Index.js(如果模組邏輯層次很複雜的話,這裡還可以再新建兩個關於模板和樣式的子目錄)

  我們稍微看下index.js的內容:

 1 (function(){
 2     //載入模組CSS
 3     require('./dialog.css');
 4     //載入模板
 5     var html=require('./dialog.html');
 6     
 7     module.exports=function(text){
 8         $('body').append(html);
 9         $('.dialog:last-child').html(text);
10     };
11     
12 })();

  這裡只是出於演示使用,所以實現的功能與邏輯比較簡單。就是引入了所需的模板和樣式檔案,然後匯出一個方法,改方法將會向body插入一個元素。

  OK,我們再來看下page目錄下index.js這個入口檔案的變動:

 1 //引入CSS
 2 require("../../css/lib/reset.css");
 3 require("../../css/common/global.css");
 4 require("../../css/page/index.css");
 5 
 6 //增加事件
 7 $('#btn').click(function(){
 8     require.ensure(['../components/dialog/index.js'],function(require){
 9         var Dialog=require('../components/dialog/index.js');
10         new Dialog(new Date()-0);
11     });
12 });

  第7行,為頁面的一個按鈕新增了點選事件,點選後載入dialog元件,然後生成一個dialog例項。

  

  再來看看webpack配置中新增了什麼內容:

  

  可以看出配置檔案並沒有太大的變化,這裡主要是:

  18行:增加了HTML載入器,用於載入HTML模板

  22行:引入全域性jq,方便其他JS呼叫

  

  在專案根目錄下執行 webpack 打包命令後,可以看到dist/js下多了1.chunk.js檔案。其實看到這裡大家也就放心了,webpack的確正確處理了這種按需載入的關係。

  

  然後執行dist/view/index.html,開啟控制檯觀察資源載入。

  一開始並沒有載入dialog元件,點選按鈕後,瀏覽器開始非同步載入dialog元件,然後生成對應的HTML.

  

  這裡有個問題需要單獨說明下,require.ensure 被webpack編譯後在執行的時候會自動判斷該模組已經下載,如果已經下載就不會再重複請求。

 

 

  2. 圖片載入

  藉助於url-loader這個載入器,在webpack中我們可以比較優雅的處理圖片載入的問題。所謂的比較優雅,是指:

  1. webpack可以將所用到的圖片自動拷貝到輸出目錄下,同樣可以為其新增hash版本號

  2. 對於比較檔案比較小的圖片,webpack可以將其自動轉換了BASE64字串進行儲存,減少一次HTTP請求

  接下來我們來做下演示:

    

  我們在dialog元件目錄下增加一張圖片(圖片大小15k左右),然後修改了dialog元件的模板,在其中引入了該張圖片。這樣每次我們點選按鈕的時候,瀏覽器都會顯示這張圖。

  

  另外我們在 global.css進行修改,為body新增一張背景圖片,由於這個圖很小(1KB),所以我們將背景圖設定為重複。

1 body{
2     font: "微軟雅黑";
3     background: url(../../img/mask.png) repeat scroll 0 0;
4 }

  最後,我們在webpack配置檔案中,為圖片引入url-loader載入器,同時為其指定存放路徑和檔名:

1 module: {
2         loaders: [    //載入器
3             {test: /\.css$/, loader:ExtractTextPlugin.extract("style", "css") },
4             {test: /\.html$/, loader: "html" },
5             {test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192&name=./img/[hash].[ext]'}
6         ]
7     }

  生成的圖片存放在dist/img下,然後為了混淆,我們將圖片檔名設定為其hash值。

  同時我們配置了limit引數,當圖片大小小於這個值的時候,webpack都將會轉換為base64字串進行儲存。

 

  然後在專案根目錄下執行 webpack 命令進行打包,然後執行生成index.html檔案:

  

  點選ADD按鈕後瀏覽器才發起非同步請求,載入了dialog元件以及我們所引入的圖片資源,同時圖片名稱已經被設定為hash值。

  再來看看樣式中引入的圖片:

  

    可以看到這個背景圖已經轉換成BASE64字串寫入css檔案中,所以這裡就減少了一次圖片請求。這是一種比較常用的優化頁面效能的方式。

  

    上面說到webpack的這種處理方式是一種比較優雅的處理方式,那又有哪些地方不夠完善呢?

    1. 上面寫入模板中的圖片webpack可以幫我們處理,但是src/view目錄下的用於生成最終HTML的模板,webpack並不會對其中所引入的圖片進行提取處理,導致圖片路徑不對。

    2. 這裡只是對圖片進行了提取,其實並未對圖片進行任何優化處理,比如合併小圖示,限制圖片質量避免圖片過大等。

    當然了,這些都是屬於額外需求,已經有些超出了webpack所承載的功能範疇。實際專案中如果出現上述需求的話,個人建議是單獨安裝grunt,然後呼叫grunt外掛來完成相關任務。

    

相關文章