configuration
- webpack 的配置文件蜓耻,是導(dǎo)出一個(gè)對(duì)象的 JavaScript 文件
- 因?yàn)?webpack 配置是標(biāo)準(zhǔn)的 Node.js CommonJS 模塊,你可以做到以下事情:
- 通過(guò) require(...) 導(dǎo)入其他文件
- 使用 JavaScript 控制流表達(dá)式嗡官,例如 ?: 操作符
- 對(duì)常用值使用常量或變量
- 編寫并執(zhí)行函數(shù)來(lái)生成部分配置
entry
- 入口起點(diǎn):指示webpack應(yīng)該使用哪個(gè)模塊來(lái)作為構(gòu)建其內(nèi)部依賴圖的開始
- 每個(gè)HTML頁(yè)面都有一個(gè)入口起點(diǎn)
- 單頁(yè)面應(yīng)用(SPA):一個(gè)入口起點(diǎn)恋日,多頁(yè)面應(yīng)用(MPA):多個(gè)入口起點(diǎn)
- 動(dòng)態(tài)加載模塊不是入口起點(diǎn)
output
配置 output 選項(xiàng)可以控制 webpack 如何向硬盤寫入編譯文件;注意膀篮,即使可以存在多個(gè)入口起點(diǎn),但只指定一個(gè)輸出配置
-
多個(gè)入口起點(diǎn):
如果配置創(chuàng)建了多個(gè)單獨(dú)的 "chunk"(例如岂膳,使用多個(gè)入口起點(diǎn)或使用像 CommonsChunkPlugin 這樣的插件)誓竿,則應(yīng)該使用占位符(substitutions)來(lái)確保每個(gè)文件具有唯一的名稱
```
{
entry: {
app: './src/app.js',
search: './src/search.js'
},
output: {
filename: '[name].js',
path: __dirname + '/dist'
}
}// 寫入到硬盤:./dist/app.js, ./dist/search.js
loader
- loader 讓webpack有能力處理那些非JavaScript文件(webpack 自身只理解JavaScript )[轉(zhuǎn)換某些類型的模塊]
- test屬性:標(biāo)識(shí)出應(yīng)該被對(duì)應(yīng)loader進(jìn)行轉(zhuǎn)換的某些或某個(gè)文件
- use:進(jìn)行轉(zhuǎn)換時(shí)應(yīng)該使用哪個(gè)loader
- loader 支持鏈?zhǔn)絺鬟f。能夠?qū)Y源使用流水線(pipeline)谈截。一組鏈?zhǔn)降?loader 將按照相反的順序執(zhí)行筷屡。loader 鏈中的第一個(gè) loader 返回值給下一個(gè) loader。在最后一個(gè) loader簸喂,返回 webpack 所預(yù)期的 JavaScript
plugin
- 插件目的在于解決 loader 無(wú)法實(shí)現(xiàn)的其他事
- 插件的范圍包括毙死,從打包優(yōu)化和壓縮,一直到重新定義環(huán)境中的變量
- 使用:首先通過(guò)
require()
導(dǎo)入喻鳄,然后將它添加到plugins數(shù)組中扼倘;當(dāng)在一個(gè)配置文件中因?yàn)椴煌康亩啻问褂猛粋€(gè)插件,這時(shí)需要通過(guò)使用 new 操作符來(lái)創(chuàng)建它的一個(gè)實(shí)例 - 由于插件可以攜帶參數(shù)/選項(xiàng)除呵,你必須在 webpack 配置中唉锌,向 plugins 屬性傳入 new 實(shí)例。
- 多數(shù)插件可以通過(guò)選項(xiàng)(option)來(lái)配置
file loader
即使含有
jsx
的語(yǔ)法的文件后綴是js
竿奏,webpack
在加載文件時(shí)test
的正則表達(dá)式依然要包含jsx
publicPath
確保
publicPath
總是以斜桿( / )開頭和結(jié)尾
CommonsChunkPlugin
從應(yīng)用程序bundle中提取vendor引用到vendor bundle袄简,并把引用vendor的部分替換為
__webpack__require()
調(diào)用
module resolution
- resolver 是一個(gè)庫(kù)(library),用于幫助找到模塊的絕對(duì)路徑
- 解析器(resolver)將檢查路徑是否指向文件或目錄泛啸。如果路徑指向一個(gè)文件:
- 如果路徑具有文件擴(kuò)展名绿语,則被直接將文件打包
- 否則,將使用 [resolve.extensions] 選項(xiàng)作為文件擴(kuò)展名來(lái)解析候址,此選項(xiàng)告訴解析器在解析中能夠接受哪些擴(kuò)展名(例如 .js, .jsx)
- 如果路徑指向一個(gè)文件夾吕粹,則采取以下步驟找到具有正確擴(kuò)展名的正確文件:
- 如果文件夾中包含 package.json 文件,則按照順序查找 resolve.mainFields 配置選項(xiàng)中指定的字段岗仑。并且 package.json 中的第一個(gè)這樣的字段確定文件路徑
- 如果 package.json 文件不存在或者 package.json 文件中的 main 字段沒有返回一個(gè)有效路徑匹耕,則按照順序查找 resolve.mainFiles 配置選項(xiàng)中指定的文件名,看是否能在 import/require 目錄下匹配到一個(gè)存在的文件名
- 文件擴(kuò)展名通過(guò) resolve.extensions 選項(xiàng)采用類似的方法進(jìn)行解析
- resolve.alias: 替換初始模塊路徑,來(lái)確保模塊引入變得更簡(jiǎn)單; 例如一些位于 src/ 文件夾下的常用模塊:
alias: { Utilities: path.resolve(__dirname, 'src/utilities/'), Templates: path.resolve(__dirname, 'src/templates/') }
output.filename
- 決定了每個(gè)輸出 bundle 的名稱
- 對(duì)于單個(gè)入口起點(diǎn)荠雕,filename 會(huì)是一個(gè)靜態(tài)名稱
filename: "bundle.js"
- 然而稳其,當(dāng)通過(guò)多個(gè)入口起點(diǎn)(entry point)驶赏、代碼拆分(code splitting)或各種插件(plugin)創(chuàng)建多個(gè) bundle,應(yīng)該使用以下一種替換方式既鞠,來(lái)賦予每個(gè) bundle 一個(gè)唯一的名稱
- 使用入口名稱:
filename: "[name].bundle.js"
- 使用內(nèi)部 chunk id
filename: "[id].bundle.js"
- 使用每次構(gòu)建過(guò)程中煤傍,唯一的 hash 生成
filename: "[name].[hash].bundle.js"
- 使用基于每個(gè) chunk 內(nèi)容的 hash:
filename: "[chunkhash].bundle.js"
output.chunkFileName
- 此選項(xiàng)決定了非入口(non-entry) chunk 文件的名稱
CommonsChunkPlugin
通過(guò)將公共模塊(chunk)拆出來(lái),最終合成的文件(另一個(gè)chunk)能夠在最開始的時(shí)候加載一次嘱蛋,便緩存到緩存中供后續(xù)使用
-
配置:
{ name: string, // or names: string[], // 這是 common chunk 的名稱蚯姆。已經(jīng)存在的 chunk 可以通過(guò)傳入一個(gè)已存在的 chunk 名稱而被選擇。 // 如果一個(gè)字符串?dāng)?shù)組被傳入洒敏,這相當(dāng)于插件針對(duì)每個(gè) chunk 名被多次調(diào)用 // 如果該選項(xiàng)被忽略龄恋,同時(shí) `options.async` 或者 `options.children` 被設(shè)置,所有的 chunk 都會(huì)被使用凶伙, // 否則 `options.filename` 會(huì)用于作為 chunk 名篙挽。 // When using `options.async` to create common chunks from other async chunks you must specify an entry-point // chunk name here instead of omitting the `option.name`. filename: string, // common chunk 的文件名模板∧餮ィ可以包含與 `output.filename` 相同的占位符铣卡。 // 如果被忽略,原本的文件名不會(huì)被修改(通常是 `output.filename` 或者 `output.chunkFilename`)偏竟。 // This option is not permitted if you're using `options.async` as well, see below for more details. minChunks: number|Infinity|function(module, count) => boolean, // 在傳入 公共chunk(commons chunk) 之前所需要包含的最少數(shù)量的 chunks 煮落。 // 數(shù)量必須大于等于2,或者少于等于 chunks的數(shù)量 // 傳入 `Infinity` 會(huì)馬上生成 公共chunk踊谋,但里面沒有模塊蝉仇。 // 你可以傳入一個(gè) `function` ,以添加定制的邏輯(默認(rèn)是 chunk 的數(shù)量) chunks: string[], // 通過(guò) chunk name 去選擇 chunks 的來(lái)源殖蚕。chunk 必須是 公共chunk 的子模塊轿衔。 // 如果被忽略,所有的睦疫,所有的 入口chunk (entry chunk) 都會(huì)被選擇害驹。 children: boolean, // 如果設(shè)置為 `true`,所有公共 chunk 的子模塊都會(huì)被選擇 deepChildren: boolean, // 如果設(shè)置為 `true`蛤育,所有公共 chunk 的后代模塊都會(huì)被選擇 async: boolean|string, // 如果設(shè)置為 `true`宛官,一個(gè)異步的 公共chunk 會(huì)作為 `options.name` 的子模塊,和 `options.chunks` 的兄弟模塊被創(chuàng)建瓦糕。 // 它會(huì)與 `options.chunks` 并行被加載底洗。 // Instead of using `option.filename`, it is possible to change the name of the output file by providing // the desired string here instead of `true`. minSize: number, // 在 公共chunk 被創(chuàng)建立之前,所有 公共模塊 (common module) 的最少大小咕娄。 }
-
給 minChunks 配置傳入函數(shù):
你也可以給 minChunks 傳入一個(gè)函數(shù)亥揖。這個(gè)函數(shù)會(huì)被 CommonsChunkPlugin 插件回調(diào),并且調(diào)用函數(shù)時(shí)會(huì)傳入 module 和 count 參數(shù);
module 參數(shù)代表每個(gè) chunks 里的模塊, 這些 chunks 是通過(guò) name/names 參數(shù)傳入的( 傳入的chunk是沒有被拆出來(lái)之前的公共模塊; 配置中 name/names 字段的說(shuō)明:
這是 common chunk 的名稱圣勒。已經(jīng)存在的 chunk 可以通過(guò)傳入一個(gè)已存在的 chunk 名稱而被選擇
)
module 有兩個(gè)有用的屬性:
+ module.context:這個(gè)公共模塊所在的目錄费变,例如:'/my_project/node_modules/example-dependency'
+ module.resource: 這個(gè)公共模塊的文件名摧扇,例如:'/my_project/node_modules/example-dependency/index.js'
> count 參數(shù)表示 module 被使用的 chunk 數(shù)量當(dāng)你想要對(duì) CommonsChunk 如何決定模塊被打包到哪里的算法有更為細(xì)致的控制, 這個(gè)配置就會(huì)非常有用
new webpack.optimize.CommonsChunkPlugin({ name: 'my-single-lib-chunk', filename: 'my-single-lib-chunk.js', minChunks: function(module, count) { // 如果模塊是一個(gè)路徑胡控,而且在路徑中有 "somelib" 這個(gè)名字出現(xiàn), // 而且它還被三個(gè)不同的 chunks/入口chunk 所使用旁趟,那請(qǐng)將它拆分到 // 另一個(gè)分開的 chunk 中昼激,chunk 的 keyname 是 "my-single-lib-chunk",而文件名是 "my-single-lib-chunk.js" return module.resource && (/somelib/).test(module.resource) && count === 3; } });
> 正如上面看到的锡搜,這個(gè)例子允許你只將其中一個(gè)庫(kù)移到一個(gè)分開的文件當(dāng)中橙困,當(dāng)而僅當(dāng)函數(shù)中的所有條件都被滿足了
Manifest file
- 當(dāng)編譯器(compiler)開始執(zhí)行、解析和映射應(yīng)用程序時(shí)耕餐,它會(huì)保留所有模塊的詳細(xì)要點(diǎn)凡傅。這個(gè)數(shù)據(jù)集合稱為 "Manifest",當(dāng)完成打包并發(fā)送到瀏覽器時(shí)肠缔,會(huì)在運(yùn)行時(shí)通過(guò) Manifest 來(lái)解析和加載模塊
- 分離manifest:將webpack的bootstrap(啟動(dòng))邏輯提取到一個(gè)單獨(dú)的文件中:
new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', minChunks: Infinity });