歡迎光臨
每天分享高質量文章

What、Why、How?解讀Webpack官方檔案

作者: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


贊(0)

分享創造快樂