webpack是什么?
webpack將靜態(tài)資源稱之為模塊。
webpack是一個模塊打包工具,可以兼容多種js書寫規(guī)范,且可以處理模塊間的依賴關(guān)系,具有更強(qiáng)大的js模塊化功能。
webpack采用不同的loader加載不同的資源文件,打包生成多個js文件,也可以根據(jù)設(shè)置生成獨立的圖片、CSS文件等。
webpack的作用
1、解決項目中資源的多樣性和依賴性;
2、處理js模塊規(guī)范復(fù)雜化+AMD、CommonJS、UMD、ES6等;使用requireJS主要用來處理AMD規(guī)范的js文件,若使用CommonJS規(guī)范的js庫文件,需要進(jìn)行AMD規(guī)范的封裝,才能正常使用。browserify主要處理CommonJS規(guī)范的文件。
3、解決開發(fā)與上線文件不一致性。
webpack特性
webpack具有requireJS和browserify的功能,但仍具有很多自己的新特性。
1、對CommonJS、AMD、ES6的語法做了兼容;
2、對js、css、圖片等資源都支持打包;
3、串聯(lián)式模塊加載器以及插件機(jī)制,讓其具有更好的靈活性和擴(kuò)展性;
4、有獨立的配置文件webpack.conf.js;
5、可以將代碼切割成不同的chunk,實現(xiàn)按需加載,降低了初始化時間。
6、支持SourceUrls和SourceMaps,易于調(diào)試;
7、具有強(qiáng)大的Plugin接口,大多是內(nèi)部插件,使用起來比較靈活。
8、webpack使用異步IO并具有多級緩存。這使得webpack很快且在增量編譯上更加快。
webpack的安裝
可全局npm模塊安裝,也可以在當(dāng)前項目中安裝
npm install -g webpack
npm install --save-dev webpack
webpack的使用
1、命令行使用:webpack <entry.js> <result.js> 其中entry.js是入口文件,result.js是打包后的輸出文件
2、node.js API使用:
var webpack = require('webpack');
webpack({
//configuration
}, function(err, stats){});
3、默認(rèn)使用當(dāng)前目錄的webpack.config.js作為配置文件。如果要指定另外的配置文件,可以執(zhí)行:
webpack --config webpack.custom.config.js
webpack常用命令
webpack的使用和browserify有些類似,下面列舉幾個常用命令:
1、webpack 最基本的啟動webpack命令
2、webpack -w 提供watch方法,實時進(jìn)行打包更新
3、webpack -p 對打包后的文件進(jìn)行壓縮
4、webpack -d 提供SourceMaps,方便調(diào)試
5、webpack --colors 輸出結(jié)果帶彩色,比如:會用紅色顯示耗時較長的步驟
6、webpack --profile 輸出性能數(shù)據(jù),可以看到每一步的耗時
7、webpack --display-modules 默認(rèn)情況下 node_modules 下的模塊會被隱藏,加上這個參數(shù)可以顯示這些被隱藏的模塊
前面的四個命令比較基礎(chǔ),使用頻率會比較大,后面的命令主要是用來定位打包時間較長的原因,方便改進(jìn)配置文件,提高打包效率。
webpack的配置文件
項目中的靜態(tài)文件較多,使用配置文件進(jìn)行打包會方便很多。最簡單的配置文件webpack.config.js如下所示:
module.exports = {
entry:[
'./entry.js',
...
],
output: {
path: __dirname + '/output/',
publicPath: "/output/",
filename: 'result.js'
}
};
其中entry參數(shù)定義了打包后的入口文件,數(shù)組中的所有文件會打包生成一個filename文件
output參數(shù)定義了輸出文件的位置及名字,其中參數(shù)path是指文件的絕對路徑,publicPath是指訪問路徑,filename是指輸出的文件名。
開發(fā)中需要將多個頁面的公用模塊獨立打包,從而可以利用瀏覽器緩存機(jī)制來提高頁面加載效率,減少頁面初次加載時間,只有當(dāng)某功能被用到時,才去動態(tài)的加載。這就需要使用webpack中的CommonsChunkPlugin插件。具體配置如下:
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
module.exports = {
entry: { a: "./a", b: "./b" },
output: { filename: "[name].js" },
plugins: [ new CommonsChunkPlugin("common.js") ]
}
在文件中根據(jù)下面的方式引用即可。
<script src="common.js"></script>
<script src="a.js"></script>
<script src="b.js"></script>
webpack模塊加載器
在webpack中JavaScript,CSS,LESS,TypeScript,JSX,CoffeeScript,圖片等靜態(tài)文件都是模塊,不同模塊的加載是通過模塊加載器(webpack-loader)來統(tǒng)一管理的。loaders之間是可以串聯(lián)的,一個加載器的輸出可以作為下一個加載器的輸入,最終返回到JavaScript上。loader的配置可以寫在配置文件中,通過正則表達(dá)式的方式對文件進(jìn)行匹配,具體可參見下面的示例:
module: {
loaders: [{
test: /\.less/,
loader: 'style-loader!css-loader!less-loader'
}, {
test: /\.(png|jpg)$/,
loader: 'url-loader?limit=10000&name=build/[name].[ext]'
}]
}
loader也支持在js文件中通過require的方式進(jìn)行加載,只需要在require資源path的前面指定loader,用!來串聯(lián)不同的loader和資源即可。
require(“style!css!less!./mystyles.less”);
css文件獨立打包
在webpack中編寫js文件時,可以通過require的方式引入其他的靜態(tài)資源,可通過loader對文件自動解析并打包文件。通常會將js文件打包合并,css文件會在頁面的header中嵌入style的方式載入頁面。但開發(fā)過程中我們并不想將樣式打在腳本中,最好可以獨立生成css文件,以外鏈的形式加載。這時extract-text-webpack-plugin插件可以幫我們達(dá)到想要的效果。需要使用npm的方式加載插件,然后參見下面的配置,就可以將js中的css文件提取,并以指定的文件名來進(jìn)行加載。
npm install extract-text-webpack-plugin –save-dev
plugins: [
new ExtractTextPlugin('styles.css')
]
圖片打包
webpack中對于圖片的處理,可以通過url-loader來實現(xiàn)圖片的壓縮。
div.img{
background: url(../image/xxx.jpg)
}
//或者
var img = document.createElement("img");
img.src = require("../image/xxx.jpg");
document.body.appendChild(img);
針對上面的兩種使用方式,loader可以自動識別并處理。根據(jù)loader中的設(shè)置,webpack會將小于指定大小的文件轉(zhuǎn)化成 base64 格式的 dataUrl,其他圖片會做適當(dāng)?shù)膲嚎s并存放在指定目錄中。
module: {
{
test: /\.(png|jpg)$/,
loader: 'url-loader?limit=10000&name=build/[name].[ext]'
}]
}
對于上面的配置,如果圖片資源小于10kb就會轉(zhuǎn)化成 base64 格式的 dataUrl,其他的圖片會存放在build/文件夾下。
webpack-dev-server 靜態(tài)資源服務(wù)器
webpack除了可以對模塊進(jìn)行打包,還提供了一個開發(fā)服務(wù)器。它的特點是:
- 基于Node.js Express框架的輕量開發(fā)服務(wù)器
- 靜態(tài)資源Web服務(wù)器
- 開發(fā)中會監(jiān)聽文件的變化在內(nèi)存中實時打包
webpack-dev-server需要單獨安裝,命令如下:
npm install -g webpack-dev-server
可以使用webpack-dev-server直接啟動,也可以增加參數(shù)來獲取更多的功能,具體配置可以參見官方文檔。默認(rèn)啟動端口8080,通過localhost:8080/webpack-dev-server/可以訪問頁面,文件修改后保存時會在頁面頭部看到sever的狀態(tài)變化,并且會進(jìn)行熱替換,實現(xiàn)頁面的自動刷新。
雙服務(wù)器模式
項目開發(fā)中,僅有一臺靜態(tài)服務(wù)器是不能滿足需求的,我們需要另啟一臺web服務(wù)器,且將靜態(tài)服務(wù)器集成到web服務(wù)器中,就可以使用webpack的打包和加載功能。我們只需要修改一下配置文件就可以實現(xiàn)服務(wù)器的集成。
entry: [
'./src/page/main.js',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://127.0.0.1:8080'
]
output: {
path: __dirname,
filename: '[name].js',
publicPath: "http://127.0.0.1:8080/assets/"
}
plugins: [
new webpack.HotModuleReplacementPlugin()
]
如果在開發(fā)中啟動兩個服務(wù)器并不是一個很好地選擇,webpack提供了一個中間件webpack-dev-middleware,但其只能在生產(chǎn)環(huán)境中使用,可以實現(xiàn)在內(nèi)存中實時打包生成虛擬文件,供瀏覽器訪問以及調(diào)試。使用方式如下:
var webpackDevMiddleware = require("webpack-dev-middleware");
var webpack = require("webpack");
var compiler = webpack({
// configuration
output: { path: '/' }
});
app.use(webpackDevMiddleware(compiler, {
// options
}));