轉載自:http://www.jb51.net/article/117490.htmcss
本篇主要介紹:如何自動構建入口文件,並生成對應的output;公共js庫如何單獨打包。html
多入口文件,自動掃描入口。同時支持SPA和多頁面型的項目html5
公共js庫如何單獨打包。node
基礎結構和準備工做jquery
如下示例基於上一篇進行改進,上一篇項目源碼webpack
目錄結構說明git
1
2
3
4
5
6
7
8
9
10
11
12
13
|
.
├── package.json # 項目配置
├── src # 源碼目錄
│ ├── pageA.html # 入口文件a
│ ├── pageB.html # 入口文件b
│ ├── css/ # css資源
│ ├── img/ # 圖片資源
│ ├── js # js&jsx資源
│ │ ├── pageA.js # a頁面入口
│ │ ├── pageB.js # b頁面入口
│ │ ├── lib/ # 沒有存放在npm的第三方庫或者下載存放到本地的基礎庫,如jQuery、Zepto、avalon
│ ├── pathmap.json # 手動配置某些模塊的路徑,能夠加快webpack的編譯速度
├── webpack.config.js # webpack配置入口
|
一:自動構建入口github
官方多入口示例web
webpack默認支持多入口,官方也有多入口的示例。配件文件webpack.config.js以下npm
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//已簡化
var
path = require(
"path"
);
module.exports = {
entry: {
pageA:
"./pageA"
,
pageB:
"./pageB"
},
output: {
path: path.join(__dirname,
"js"
),
filename:
"[name].bundle.js"
,
chunkFilename:
"[id].chunk.js"
}
}
|
每新增一個頁面就須要在webpack.config.js的entry 中增長一個 pageC:"./pageC",頁面少還好,頁面一多,就有點麻煩了,並且配置文件,儘量不改動。那麼如何支持不修改配置呢?
自動構建入口函數
entry其實是一個map對象,結構以下{filename:filepath},那麼咱們能夠根據文件名匹配,很容易構造自動掃描器:
npm 中有一個用於文件名匹配的 glob模塊,經過glob很容易遍歷出src/js目錄下的全部js文件:
安裝glob模塊
1
|
$ npm
install
glob --save-dev
|
修改webpack.config.js 配置,新增entries函數,修改entry:entries(),修改output的filename爲"[name].js"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
//引入glob
var
glob = require(
'glob'
)
//entries函數
var
entries=
function
() {
var
jsDir = path.resolve(srcDir,
'js'
)
var
entryFiles = glob.sync(jsDir +
'/*.{js,jsx}'
)
var
map = {};
for
(
var
i = 0; i < entryFiles.length; i++) {
var
filePath = entryFiles[i];
var
filename = filePath.substring(filePath.lastIndexOf(
'\/'
) + 1, filePath.lastIndexOf(
'.'
));
map[filename] = filePath;
}
return
map;
}
//修改入口,已經修改outp的filename
module.exports = {
//entry: "./src/js/index.js",
entry: entries(),
output: {
path: path.join(__dirname,
"dist"
),
filename:
"[name].js"
},
......
//如下省略,能夠見下文詳細配置
|
測試
1.在src/js目錄中新增pageA.js
1
2
3
|
//js只有兩行代碼,在body中加一句話
var
$ = require(
"jquery"
)
$(
"<div>這是jquery生成的多頁面示例</div>"
).appendTo(
"body"
)
|
2.新增pageA.html,也順便修改原來的index.html 對於js文件名的更改
1
2
3
4
5
6
7
8
9
10
|
<!DOCTYPE html>
<
html
lang
=
"en"
>
<
head
>
<
meta
charset
=
"UTF-8"
>
<
title
></
title
>
</
head
>
<
body
>
<
script
src
=
"../dist/index.js"
></
script
>
</
body
>
</
html
>
|
3.執行webpack,啓動dev-server
1
2
|
$ webpack
$ webpack-dev-server
|
OK,成功打包生成pageA.js,成功運行
二:公共庫單獨打包
先來分析下,上個步驟打包的日誌:
index.js 依賴了avalon 和 jquery,而後打包後的index.js 有480kb
pageA.js 只用了jquery,而後打包後的js 有294kb
那麼若是引用的lib庫多一點,又被不少頁面引用,那麼lib庫就會被重複打包到page.js中去,模塊越多重複加載的狀況越嚴重。
若是把公共代碼提取出來做爲單獨的js,那麼就處處能夠複用,瀏覽器也就能夠進行緩存,這時候就須要用到webpack內置插件WebPack.optimize.CommonsChunkPlugin
CommonsChunkPlugin 介紹
使用
1
|
new
webpack.optimize.CommonsChunkPlugin(options)
|
Options
翻譯得比較簡單,詳見官方說明:
2個經常使用的例子,更多例子見官方說明:
1.Commons chunk for entries:針對入口文件提取公共代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
|
new
CommonsChunkPlugin({
name:
"commons"
,
// (the commons chunk name)
filename:
"commons.js"
,
// (the filename of the commons chunk)
// minChunks: 3,
// (Modules must be shared between 3 entries)
// chunks: ["pageA", "pageB"],
// (Only use these entries)
})
|
2.Explicit vendor chunk:直接指定第三方依賴庫,打包成公共組件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
entry: {
vendor: [
"jquery"
,
"other-lib"
],
app:
"./entry"
}
new
CommonsChunkPlugin({
name:
"vendor"
,
// filename: "vendor.js"
// (Give the chunk a different name)
minChunks: Infinity,
// (with more entries, this ensures that no other module
// goes into the vendor chunk)
})
|
CommonsChunkPlugin使用
基於上篇的項目,參考上面的第二個例子,咱們將jquery 和 avalon 提取出來打包成vendor.js
完整的webpack.config.js 以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
```js
var
webpack = require(
"webpack"
);
var
path = require(
"path"
);
var
srcDir = path.resolve(process.cwd(),
'src'
);
var
nodeModPath = path.resolve(__dirname,
'./node_modules'
);
var
pathMap = require(
'./src/pathmap.json'
);
var
glob = require(
'glob'
)
var
CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
var
entries=
function
() {
var
jsDir = path.resolve(srcDir,
'js'
)
var
entryFiles = glob.sync(jsDir +
'/*.{js,jsx}'
)
var
map = {};
for
(
var
i = 0; i < entryFiles.length; i++) {
var
filePath = entryFiles[i];
var
filename = filePath.substring(filePath.lastIndexOf(
'\/'
) + 1, filePath.lastIndexOf(
'.'
));
map[filename] = filePath;
}
return
map;
}
module.exports = {
//entry: "./src/js/index.js",
//entry: entries(),
entry: Object.assign(entries(), {
// 用到什麼公共lib(例如jquery.js),就把它加進vendor去,目的是將公用庫單獨提取打包
'vendor'
: [
'jquery'
,
'avalon'
]
}),
output: {
path: path.join(__dirname,
"dist"
),
filename:
"[name].js"
},
module: {
loaders: [
{test: /\.css$/, loader:
'style-loader!css-loader'
}
]
},
resolve: {
extensions: [
'.js'
,
""
,
".css"
],
root: [srcDir,nodeModPath],
alias: pathMap,
publicPath:
'/'
},
plugins: [
new
CommonsChunkPlugin({
name:
'vendor'
,
minChunks: Infinity
})
]
}
```
|
測試、驗證
1.修改入口(Object.assign 是html5.js裏面的....)
1
2
3
4
5
|
//entry: entries(),
entry: Object.assign(entries(), {
// 用到什麼公共lib(例如jquery.js),就把它加進vendor去,目的是將公用庫單獨提取打包
'vendor'
: [
'jquery'
,
'avalon'
]
}),
|
2.加入插件CommonsChunkPlugin
1
2
3
4
5
6
7
8
|
var
CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
config 中增長 plugins
plugins: [
new
CommonsChunkPlugin({
name:
'vendor'
,
minChunks: Infinity
})
]
|
3.修改index.html 和 pageA.html,增長對verdor.js的引用
1
2
3
|
<
script
src
=
"../dist/vendor.js"
></
script
>
<
script
src
=
"../dist/index.js"
></
script
>
//<
script
src
=
"../dist/pageA.js"
></
script
>
|
4.執行webpack
$ webpack
結果分析
能夠看到index.js 就只有457 bytes了,pageA.js 227bytes。vendor.js 是集成了jquery+avalon,因此有488kb。
這樣vendor.js 就能夠重複利用了,也方便瀏覽器進行緩存。
調試過程當中發現
Uncaught ReferenceError: webpackJsonp is not defined
這個是由於當時把vendor.js引入 放到了page.js 後面,致使page.js執行異常,因此,請必定把vendor.js 放在前面。
生成後的index.js就很輕便了,第三方庫都被打包到vendor中了,代碼以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
webpackJsonp([0],[
/* 0 */
/***/
function
(module, exports, __webpack_require__) {
/**
* Created by sloong on 2016/6/1.
*/
//avalon 測試
var
avalon = __webpack_require__(1);
avalon.define({
$id:
"avalonCtrl"
,
name:
"Hello Avalon!"
});
/*
//zepto 測試
require("zepto")
$("<div>這是zepto生成的</div>").appendTo("body")*/
//jquery 測試
var
$ = __webpack_require__(2)
$(
"<div>這是jquery生成的</div>"
).appendTo(
"body"
)
/***/
}
]);
|
頁面測試均正常
OK,本篇結束了。如何讓webpack 自動在html文件中引入所需js的script標籤,如何給js和css文件加了hash值,這樣瀏覽器每次都能檢測到文件變動,並且也不須要手動修改引入的js文件連接,這些操做webpack都能輕鬆搞定。