基於gulp+webpack構建基礎

為什麼要使用webpack?

1.問題

我們都知道現在web系統正變得越來越龐大,因此所需的js腳本量也會相應的增加。為了便於代碼的維護,所以出現了js模塊化開發理念。

2.如何實現js的模塊化

js模塊化概念剛提出來時,在前端是藉助於前端框架來實現的。比如requirejs,seajs等等很多;使用了框架就需要按照框架的約束來書寫js;requirejs需要要求的語法是amd規範,seajs要求的是cmd規範;在node上則是commonjs規範。但是藉助前端框架來實現js的模塊化都是有缺點的。

3.前端框架實現js模塊化的弊端

當我們在使用前端模塊化框架時,我們覺得用起來很爽;但是作為一名優秀的前端工程師肯定會經不住誘惑去探究這些框架背後的原理。這些框架總結起來就是通過,模塊依賴分析、模塊載入,模塊存儲,模塊的路徑解析這些;關鍵在於這些工作是在用戶訪問頁面的時候線上完成的。比我們不使用模塊化框架的項目的速度還要慢。而且當項目所需的js模塊越來越多,就需要發送更多的http請求去載入這些模塊。性能優化規則有一條就是要減少http請求,於是requirejs有一款優化工具r.js,該工具會把所有的js文件整合成一個js文件。在小項目中還可以,但是如果js腳本實在是太多了,最終導致整合之後的js代碼量上萬行甚至更多。如果頁面的主要內容是通過ajax來載入並展示,那麼用戶將會等很長時間才能看到頁面的主要內容。正在認真閱讀的你會希望出現一種擇中的方案來解決這個問題。

4.webpack的模塊化實現

webpack的出現非常人性化的解決了上述提到的問題(第3點)。在webpack構建的項目中,我們可以使用amd,cmd,commonjs三種模塊化規範中的任意一種來書寫js。前端模塊化框架和webpack實現模塊化都少不了依賴分析,前者是線上完成依賴分析,而webpack是預先完成的。也就是在我們的項目發布之前就已經被webpack跑一遍了,通過webpack產生出了新的資源。真正要上線的項目就是新產生的資源。這樣就避免了在線上運行js模塊化框架去分析依賴等一系列步驟。還有一點,webpack可以把多個頁面共同依賴的模塊提取出來整合在一起。還可以通過require.ensure 語法來做到按需載入,從而避免了所有js整合成一個的問題,使得每個頁面更加的純凈,也充分的利用了緩存來提升性能。

栗子(該例子結合了gulp,現在先關注webpack的模塊化實現,待會兒會總結gulp):

這個例子的js之間的依賴關係以及通過webpack構建之後的產出的關係

項目目錄:

webpack.config.js:

var webpack = require(webpack),n CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");nmodule.exports = {n entry: {n index1: ./src/js/module1, //因為有2個入口js,所以寫兩個路徑n index2: ./src/js/module2n },n output: {n filename: js/[name].js,n publicPath:dist/ n },n plugins: [n new CommonsChunkPlugin(common.js)//提取多個js模塊共同依賴的模塊,命名為common.jsn ]n}n

//module1.jsndefine([./module3], function (module3) {n console.log("module1");n});nn//module2.jsndefine([ ./module3,./module4,./module5], function (module3, module4,module5) {n console.log("module2");n});nn//module3.jsndefine(function () {n console.log("module3");n});nn//module4.jsndefine(function () {n console.log("module4");n});nn//ndefine(function () {n console.log("module5");n});n

<!DOCTYPE html>n<html>n<head>nt<title>index1</title>n</head>n<body>n <script src="dist/common.js"></script>n <script src="dist/js/index1.js"></script>n</body>n</html>n

dist目錄下的資源為通過webpack構建之後的資源。

index1.js:

<!DOCTYPE html>n<html>n<head>n <title>index1</title>n</head>n<body>n <script src="dist/common.js"></script>n <script src="dist/js/index1.js"></script>n</body>n</html>n

index2.js:

<!DOCTYPE html>n<html>n<head>n <title>index2</title>n</head>n<body>n <script src="dist/common.js"></script>n <script src="dist/js/index2.js"></script>n</body>n</html>n

產出的js文件已經包含了個模塊之間的依賴關係,common.js是index1.js和index2.js共用的文件。訪問index1.html和index2.html的時候就不用在線分析這種關係,webpack已經減輕了許多線上工作。

還有一個關於js模塊比較常用的語法require.ensure([],function(){});它可以做到按需加在相應的js腳本。

現在需要更改一些文件來演示require.ensure

webpack.config.js(新增了chunkFilename行):

var webpack = require(webpack),n CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");nmodule.exports = {n entry: {n index1: ./src/js/module1, //因為有2個入口js,所以寫兩個路徑n index2: ./src/js/module2n },n output: {n filename: js/[name].js,n chunkFilename:js/chunk/[name]_chunk.js, //支持require.ensuren publicPath:dist/ n },n plugins: [n new CommonsChunkPlugin(common.js)//提取多個js模塊共同依賴的模塊,命名為common.jsn ]n}n

module2.js(新增了require.ensure的使用):

define([ ./module3,./module4,./module5], function (module3, module4,module5) {n console.log("module2");n});nnrequire.ensure([],function(require){ntvar chunk=require(./chunk);ntconsole.log(chunk.name);n});n

gulpfile.js:

var gulp = require(gulp),n webpack = require(gulp-webpack);nngulp.task(default, [watch_module, handle_js]);ngulp.task(watch_module, function() {n var path = [src/js/*];n gulp.watch(path, function(event) {n gulp.src(event.path)n .pipe(webpack(require(./webpack.config.js)))n .pipe(gulp.dest(dist));n });n});nngulp.task(handle_js, function() {nn gulp.src(src/js/*)n .pipe(webpack(require(./webpack.config.js)))n .pipe(gulp.dest(dist));n});n

最終項目目錄:

可見產出了dist/js/chunk/2_chunk.js

當然webpack還可以做許多事情如載入html模板,代碼壓縮,編譯less,sass,es6......,不過這些通過gulp能夠非常容易的做到而且webpack最強大的功能就是js的模塊化實現。其他的可以交給gulp來做。

為什麼結合gulp

首先貼一個自己查閱的gulp簡易教程github.com/nimojs/gulp-

webpack最擅長的是js的模塊化功能,在公司項目需要發布到開發機,而且gulp可以很容易的完成代碼壓縮,md5,產出文件的流向,文件監聽自動發布等功能。gulp是一個node項目,可擴展性很強,所以根據團隊的需要,直接使用node開發適合自己團隊的功能函數。gulp的命令也比較簡單,可自定義,像fis一樣更加便於開發者理解命令的含義。

本文是自己在實現第一個需求的一些總結,著重總結了一下模塊化。實習生一名,水平有限,各位大牛見笑了。


推薦閱讀:

為何我覺得gulp不是個好東西
如何自己開發gulp插件?
有沒有好的gulp+webpack的例子啊?求指教,分開來都是會用的,但是結合起來就有些懵。。
前端框架可以直接使用,為何需要nodejs/gulp等工具?

TAG:webpack | gulp | 前端入门 |