webpack&gulp集成簡介

webpack簡單介紹

webpack is a bundler for modules. The main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.摘自github webpack頁面。webpack以CommonJS規范在本地對js進行模塊化處理打包,不再需要引入requirejs或seajs。可以通過不同的loader來對其他格式的文件進行處理。接下來會介紹下如何使用gulp和webpack來處理前端代碼,并且會介紹一些集成過程中遇到的坑。文中最后把gulpfile.js和package.json里面的代碼貼出來,僅供參考。

gulp和webpack集成使用介紹

安裝完Nodejs環境后,把本文后面的package.json文件安裝,gulp要全局安裝(npm install gulp -g)。

  • 創建webpack對象
var webpack = require("webpack")
  • 創建gulp默認任務
//gulp --product
gulp.task('default', function() {
    isProduct = argv.product;
    isWatch = !isProduct;
    console.log('正在處理:' + (isProduct ? '線上' : '本地') + '環境');
    fse.emptydirSync('./dist');
    gulp.start('webpack');
});

本地開發(命令:gulp)和線上(命令:gulp --product)部署gulp命令分開,本地會做文件更改的監聽,并且不會壓縮。

ps:fse庫是對自帶的fs庫做了很好的擴展,推薦使用。

  • webpack任務配置

最全配置代碼參考gulpfile.js。

入口文件配置:

entry: {
            index: './index.js'
            common: [
                'jquery',
                'understore',
                'template',
                'store'
            ]
        }

該參數主要是配置入口文件,打包出來的文件就是以里面的key作為名字的文件(即bundle)。

==注意點:[]和字符串的區別,如果是字符串(比如:'./index,js'),那么該文件(index.js)是不能在其他模塊進行require的,如果既要作為入口文件又要在其他模塊require,那么需要用數組的方式配置,即['./index.js']。可以看下打包后的代碼,字符串的配置該文件代碼會在索引為0的地方,如果配置成數組,則位置為0的函數中是沒有自己代碼的,只是來執行其他模塊的代碼==

輸出路徑配置:

output: {
            path: './dist/',
            filename: '[name].js',
            publicPath: ''
        }

文件會被輸出到dist目錄下,文件名是以當前文件名做為輸出后的文件名。

別名配置:

resolve: {
            alias: {
                jquery: path.resolve('../global/lib/jquery.js'),
                template: path.resolve('../global/lib/template.js'),
                understore: path.resolve('../global/lib/underscore.js'),
                store: path.resolve('../global/lib/store.js')
            }
        }

配置完別名,就可以用別名來進行require了,不管是在webpack配置中,還是在js代碼中。比如,在entry中的common模塊就可以直接用understore,在打包時就會通過別名找到具體的路徑。==別名的值最好是絕對路徑,當時我們用相對路徑如果只是同一個目錄結構沒有問題,但是多個目錄結構的引用就會出現路徑解析錯誤。絕對路徑轉換使用path.resolve該方法即可==

webpack插件:

一些特殊功能可以通過webpack插件進行完成。

1)webpack內部全局變量

new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    template: 'template',
    store: 'store',
    _: 'understore'
})

配置完全局的變量,在js中就直接可以用,不需要再require。該全局不是掛載到window對象上,只對webpack打包出來的js有用。

2)模塊唯一插件
new webpack.optimize.DedupePlugin()

該插件會把相同的模塊合并,不推薦使用,最好自己做到模塊唯一性,如果打出來兩個相同的模塊,說明你的代碼潛藏出錯風險

3)css抽離插件
new ExtractTextPlugin("[name].css")

該插件會把css抽離出來作為單獨的css文件進行打包,如果不使用該插件,會把css打包到js中,然后以style標簽的形式,把css作為內聯樣式使用。

4)公共文件插件
new webpack.optimize.CommonsChunkPlugin('common', 'common.js')

該插件會把公共的模塊進行抽離到公共的js模塊里面,防止js重復引用打包。

5)壓縮插件

new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        },
        mangle: {
            except: ['$', 'm', 'webpackJsonpCallback']
        }
    })

該插件會把js進行壓縮,在線上環境進行使用。mangle該關鍵詞不需要混淆,因為在我們實踐過程中,壓縮后的代碼有很多地方報錯,故上面3個不混淆的值是根據我們自身項目來的。

sourcemap:

由于webpack會把所有的js都打包到一個js文件中,這樣就不方便開發人員debug,故需要進行sourcemap的配置

devtool: (isProduct ? false : 'source-map')

線上環境不需要sourcemap,加上source-map參數,會在打包的時候打出來map文件,chrome瀏覽器會解析sourcemap進行定位到相應的文件。

加載器loader:

1)js加載器

{
    test: /\.js[x]?$/,
    exclude: /node_modules/,
    loader: 'babel-loader',
    query: {
        compact: false
    }
}

js使用babel來進行加載,這樣就可以使用一些es6的特性來開發,IE8下面使用如下方案來進行解決轉換后的代碼不兼容問題。

==解決IE8 babel 轉換:我們把shim.js & sham.js,自己合并到一起吧==

<!--[if IE 8]> <script src='es5-shim-sham.js)'></script><![endif]-->

2)css、less、sass加載器

{
    test: /\.css$/,
    loader: ExtractTextPlugin.extract('style-loader', 'css-loader?-convertValues')
}, {
    test: /\.less$/,
    loader: ExtractTextPlugin.extract('style-loader', 'css-loader?-convertValues!less-loader')
}, {
    test: /\.scss$/,
    loader: ExtractTextPlugin.extract('style-loader', 'css-loader?-convertValues!sass-loader')
}

ExtractTextPlugin是抽離css的插件。css-loader是處理css,會把url(xxx.png)處理成require,然后通過對應后綴名的其他加載器進行處理。==如果是線上環境,css會進行壓縮,很多配置要進行調整如果直接采用默認的,轉換后的css會出現一些問題==

a)問題一,壓縮后字體文件不能處理。解決方法:把iconfont.css里面的注釋刪除掉即可
b)問題二,壓縮后的px單位會轉換成pc,pt。解決方法:在加載器里面加上-convertValues參數。
c)問題三,css require的優先級問題,按照常理是后require的css是后加載。但是在實踐過程中,(1)通過import引入的js模塊中引入的css是優先于require引入的js模塊中引入的css;(2)js中require的css名稱如果和js所在模塊的文件夾名字相同即使部分相同的話,優先級也會提高。

關于css加載器的參數可以參考cssnano。css-loader是根據cssnano對css進行處理的。

3)圖片字體文件加載器,file-loader

{
    test: /\.(png|jpg|gif|woff|woff2|ttf|eot|svg)$/,
    loader: "file-loader?name=[name]_[sha512:hash:base64:7].[ext]"
}

對一些圖片和字體資源進行加載,我們會把相關文件抽離出來進行名字加上hash值的前7位做了處理后的名字。

4)html加載器

{
    test: /\.html/,
    loader: "html-loader"
}

我們主要把模板文件建成一個Html,然后在Js引入,這樣該html就會以字符串格式的值賦給一變量,然后我們用arttemplate進行頁面渲染。

腳本文件

  • gulp腳本 gulpfile.js
var gulp = require('gulp'),
    argv = require('yargs').argv,
    fs = require('fs'),
    fse = require('fs-extra'),
    path = require('path'),
    util = require('util');
var webpack = require("webpack"),
    ExtractTextPlugin = require("extract-text-webpack-plugin");

var isWatch = true;
var isProduct = false;
var project = 'iwjw-pc';
//gulp --product
gulp.task('default', function() {
    isProduct = argv.product;
    isWatch = !isProduct;

    console.log('正在處理:' + (isProduct ? '線上' : '本地') + '環境');

    fse.emptydirSync('./dist');

    gulp.start('webpack');
});

//webpack靜態處理
gulp.task('webpack', function(callback) {
    var minfy = [];
    isProduct && minfy.push(new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        },
        mangle: {
            except: ['$', 'm', 'webpackJsonpCallback']
        }
    }));
    //webpack配置文件
    var config = {
        watch: isWatch,
        entry: {
            index: './index.js',
            common: [
                'jquery',
                'understore',
                'template',
                'store'
            ]
        },
        debug: true,

        devtool: (isProduct ? false : 'source-map'),

        output: {
            path: './dist/',
            filename: '[name].js',
            publicPath: ''
        },

        resolve: {
            alias: {
                jquery: path.resolve('../global/lib/jquery.js'),
                template: path.resolve('../global/lib/template.js'),
                understore: path.resolve('../global/lib/underscore.js'),
                store: path.resolve('../global/lib/store.js')
            }
        },


        plugins: [
            new webpack.ProvidePlugin({
                $: 'jquery',
                jQuery: 'jquery',
                template: 'template',
                store: 'store',
                _: 'understore'
            }),
            new webpack.optimize.DedupePlugin(),
            new ExtractTextPlugin("[name].css"),
            new webpack.optimize.CommonsChunkPlugin('common', 'common.js')
        ].concat(minfy),
        module: {
            loaders: [{
                test: /\.js[x]?$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                query: {
                    compact: false
                }
            }, {
                test: /\.css$/,
                loader: ExtractTextPlugin.extract('style-loader', 'css-loader?-convertValues')
            }, {
                test: /\.less$/,
                loader: ExtractTextPlugin.extract('style-loader', 'css-loader?-convertValues!less-loader')
            }, {
                test: /\.scss$/,
                loader: ExtractTextPlugin.extract('style-loader', 'css-loader?-convertValues!sass-loader')
            }, {
                test: /\.(png|jpg|gif|woff|woff2|ttf|eot|svg)$/,
                loader: "file-loader?name=[name]_[sha512:hash:base64:7].[ext]"
            }, {
                test: /\.html/,
                loader: "html-loader"
            }]
        }
    }; 
    webpack(config, function(err, stats) {
        console.log(stats.toString());
    });
});
gulp.task('sham', function(){
    gulp.src('../global/lib/es5-shim-sham.js').pipe(gulp.dest('./dist'));
})
  • pacakge.json
{
  "name": "iwfe",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/server"
  },
  "dependencies": {
    "babel-loader": "^5.3.2",
    "bundle-loader": "^0.5.4",
    "css-loader": "^0.16.0",
    "exports-loader": "^0.6.2",
    "extract-text-webpack-plugin": "^0.8.2",
    "file-loader": "~0.8.4",
    "fs-extra": "*",
    "html-loader": "^0.4.0",
    "imports-loader": "^0.6.5",
    "jquery": "~2.1.4",
    "sass-loader": "^3.1.2",
    "source-map-loader": "^0.1.5",
    "style-loader": "~0.12.3",
    "through2": "*",
    "url-loader": "~0.5.6",
    "webpack": "*",
    "webpack-dev-server": "^1.10.1",
    "yargs": "*",
    "gulp-zip": "*"
  },
  "devDependencies": {
    "gulp": "*",
    "gulp-util": "*"
  },
  "description": "前端靜態庫",
  "repository": {
    "type": "git",
    "url": "xxx"
  },
  "author": "jade",
  "license": "ISC"
}

參考文檔:

webpack github地址

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,208評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,746評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,666評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,477評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,960評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,200評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,726評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,617評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,807評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,049評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,425評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,674評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,432評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,769評論 2 372

推薦閱讀更多精彩內容

  • 在現在的前端開發中,前后端分離、模塊化開發、版本控制、文件合并與壓縮、mock數據等等一些原本后端的思想開始...
    Charlot閱讀 5,462評論 1 32
  • 無意中看到zhangwnag大佬分享的webpack教程感覺受益匪淺,特此分享以備自己日后查看,也希望更多的人看到...
    小小字符閱讀 8,206評論 7 35
  • 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 webpack介紹和使用 一、webpack介紹 1、由來 ...
    it筱竹閱讀 11,199評論 0 21
  • 最近在學習 Webpack,網上大多數入門教程都是基于 Webpack 1.x 版本的,我學習 Webpack 的...
    My_Oh_My閱讀 8,199評論 40 247
  • 昨天11月20日比特幣價格再創新高,達到了8028美元,即5.3萬人民幣。看到這個數據,我還是有點小興奮的,盡管我...
    蘇蘇日記閱讀 184評論 0 0