作者:Tgor的部落格
網址:http://web.jobbole.com/83330/
What is Webpack?
Webpack具有Grunt、Gulp對於靜態資源自動化構建的能力,但更重要的是,Webpack彌補了requireJS在模組化方面的缺陷,同時相容AMD與CMD的模組載入規範,具有更強大的JS模組化的功能。
因此我理解的Webpack,就是一個更出色的前端自動化構建工具、模組化工具、資源管理工具。
webpack is a module bundler. webpack takes modules with dependencies and generates static assets representing those modules.
Why Webpack?
為什麼選擇Webpack,兩點原因。
1、前端需要模組化:JS模組化不僅僅為了提高程式碼復用性,更是為了讓資源檔案更合理地進行快取;
2、AMD與CMD規範日漸衰弱:原因?ES6帶來了很強的模組化語法糖。雖然ES6的更多語法糖讓JS可能失去了簡單的優勢,在一些技術社群還偶爾看到一些反ES6的文章,但感覺ES6仍然是未來發展的趨勢;
module DBLayer {
export function query(s) { … }
export function connection(..args) { … }
}
import DBLayer.*;
module CanvasLib = require(‘http://../canvas.js’);
import CanvasLib.{Triangle, rotate};
參考使用簡單的JavaScript,我們為什麼應該抵制ES6例子。
當然,ES6,我覺得還是未來的事情,尤其是在China地盤要全面普及支援ES6的高階瀏覽器,真的比證明你媽是你媽還要困難。
所以,我認為,AMD跟CMD慢慢過時的原因,是模組化前端專案的釋出打包問題,requireJS跟seaJS都沒有一個很好的解決方案。下麵配置檔案是,我曾經做過的一個backbone的專案以requireJS做模組化載入。專案初始階段還好,當隨著專案深入,模組切分得越細,最後釋出上線的時候,頁面對於JS的請求數量竟然多達20個以上。大量的HTTPRequest造成的後果,不用多想,大家都知道。
require.config({
//baseUrl: “scripts/vendor”,
paths: {
underscore: ‘../vendor/underscore.min’,
zepto: ‘../vendor/zepto.min’,
backbone: ‘../vendor/backbone.min’,
domReady: ‘../vendor/domReady’,
template: ‘../vendor/template’,
iscroll: ‘../vendor/iscroll/iscroll’,
common: ‘../common/common’
},
shim: {
underscore: {
exports: ‘_’
},
zepto: {
exports: ‘$’
},
backbone: {
deps: [‘underscore’, ‘zepto’],
exports: ‘Backbone’
}
},
waitSeconds: 0
});
require([
‘zepto’,
‘underscore’,
‘backbone’,
‘domReady’,
‘common’,
‘../controller/homeCtrl’,
‘../controller/fadeCtrl’,
‘../controller/mockCtrl’
],
function ($, _, backbone, domReady, common, homeCtrl, fadeCtrl, mockCtrl) {…}
為瞭解決這個問題,引入的RequireJS的最佳化方案:r.js Optimizer。詳情:前端最佳化:RequireJS Optimizer 的使用和配置方法。
({
name: “ptMain”,
optimize: “uglify”,//uglify
`out: “../build/ptMain-build.js”,`
removeCombined: true,
paths: {
underscore: ‘../vendor/underscore.min’,
zepto: ‘../vendor/zepto.min’,
backbone: ‘../vendor/backbone.min’,
domReady: ‘../vendor/domReady’,
iscroll: ‘../vendor/iscroll/iscroll.min’
},
shim: {
underscore: {
exports: ‘_’
},
zepto: {
exports: ‘$’
},
backbone: {
deps: [‘underscore’, ‘zepto’],
exports: ‘Backbone’
}
}
});
r.js同樣可以對各個js進行壓縮混淆最佳化,並最終在out配置中合併成一個JS檔案,然後在頁面中呼叫。就是說,不管三七二十一,每個頁面對應取用的JS,都會被打包成一個JS,但這樣的話,一個站點中多個頁面之間公用的JS模組就無法快取起來了。
說這麼多,其實就是說,Webpack把以上兩個問題解決了。
模組化
所有資源都是模組
大家可以回頭看下Webpack官方實體圖,有一點不知道大家是否註意到:Webpack處理後,輸出的靜態檔案只剩下js與png,而css、less、jade其他的檔案都合併到了js中。在Webpack當中,所有資源的都是模組,模組都需要透過AMD或者CMD規範載入,就像css樣式檔案,不再在HTML中以 標簽載入。
content.js
module.exports = “It works from content.js.”;
entry.js
//樣式檔案同樣以模組方式引入
require(“!style!css!./style.css”);
//以CMD引入content.js
var content = require(“./content.js”);
function a() {
document.write(content);
};
a();
style.css
body {
background-color: yellow;
}
webpack.config.js
module.exports = {
entry: “./entry.js”,
output: {
path: __dirname,
//打包輸出檔案
filename: “bundle.js”
},
module: {
//loaders引入載入器
loaders: [
{ test: /\.css$/, loader: “style!css” }
]
}
};
bundle.js
/***/ function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(3)();
// imports
// module
exports.push([module.id, “body {\r\n background-color: yellow;\r\n}\r\n”, “”]);
// exports
/***/ },
打包好的bundle,包含了樣式表在內的靜態資源,而index頁面下載bundle後,會將樣式還原到DOM當中。如下圖。
index.html