本文首發(fā)于Array_Huang的技術(shù)博客——
實(shí)用至上
袍嬉,非經(jīng)作者同意,請勿轉(zhuǎn)載厅贪。
原文地址:https://segmentfault.com/a/1190000006863968
如果您對本系列文章感興趣蠢护,歡迎關(guān)注訂閱這里:https://segmentfault.com/blog/array_huang
前言
webpack的配置文件是一個node.js的module,用CommonJS風(fēng)格來書寫养涮,形如:
module.exports = {
entry: "./entry",
output: {
path: __dirname + "/dist",
filename: "bundle.js"
}
}
webpack的配置文件并沒有固定的命名葵硕,也沒有固定的路徑要求,如果你直接用webpack
來執(zhí)行編譯贯吓,那么webpack默認(rèn)讀取的將是當(dāng)前目錄下的webpack.config.js
$ pwd
/d/xampp/htdocs/webpack-seed
$ webpack # webpack此時讀取的實(shí)際上是/d/xampp/htdocs/webpack-seed/webpack.config.js
如果你有其它命名的需要或是你有多份配置文件贬芥,可以使用--config
參數(shù)傳入路徑:
$ webpack --config ./webpackConfig/dev.config.js
另外,在CLI執(zhí)行webpack
指令時可傳入的參數(shù)(當(dāng)然除了--config
)實(shí)際上都可以在配置文件里面直接聲明宣决,我強(qiáng)烈建議可以的話盡量都在配置文件里寫好,有需要的話寫兩份配置也好三份也好(反正配置文件間也是可以互相引用的昏苏,相同的部分就拆成一個module出來以供讀取尊沸,最后拼成各種情況下需要的配置就好了)。
入口文件配置:entry參數(shù)
entry可以是字符串(單入口)贤惯,可以是數(shù)組(多入口)洼专,但為了后續(xù)發(fā)展,請務(wù)必使用object孵构,因?yàn)閛bject中的key在webpack里相當(dāng)于此入口的name屁商,既可以后續(xù)用來拼生成文件的路徑,也可以用來作為此入口的唯一標(biāo)識颈墅。
我推薦的形式是這樣的:
entry: { // pagesDir是前面準(zhǔn)備好的入口文件集合目錄的路徑
'alert/index': path.resolve(pagesDir, `./alert/index/page`),
'index/login': path.resolve(pagesDir, `./index/login/page`),
'index/index': path.resolve(pagesDir, `./index/index/page`),
},
對照我的腳手架項(xiàng)目webpack-seed
的文件目錄結(jié)構(gòu)蜡镶,就很清楚了:
├─src # 當(dāng)前項(xiàng)目的源碼
├─pages # 各個頁面獨(dú)有的部分,如入口文件恤筛、只有該頁面使用到的css官还、模板文件等
│ ├─alert # 業(yè)務(wù)模塊
│ │ └─index # 具體頁面
│ ├─index # 業(yè)務(wù)模塊
│ │ ├─index # 具體頁面
│ │ └─login # 具體頁面
由于每一個入口文件都相當(dāng)于entry里的一項(xiàng),因此這樣一項(xiàng)一項(xiàng)地來寫實(shí)在是有點(diǎn)繁瑣毒坛,我就稍微寫了點(diǎn)代碼來拼接這entry:
var pageArr = [
'index/login',
'index/index',
'alert/index',
];
var configEntry = {};
pageArr.forEach((page) => {
configEntry[page] = path.resolve(pagesDir, page + '/page');
});
輸出文件:output參數(shù)
output參數(shù)告訴webpack以什么方式來生成/輸出文件望伦,值得注意的是,與entry不同煎殷,output相當(dāng)于一套規(guī)則屯伞,所有的入口都必須使用這一套規(guī)則,不能針對某一個特定的入口來制定output規(guī)則豪直。output參數(shù)里有這幾個子參數(shù)是比較常用的:path劣摇、publicPath、filename顶伞、chunkFilename饵撑,這里先給個webpack-seed
中的示例:
output: {
path: buildDir, // var buildDir = path.resolve(__dirname, './build');
publicPath: '../../../../build/',
filename: '[name]/entry.js', // [name]表示entry每一項(xiàng)中的key剑梳,用以批量指定生成后文件的名稱
chunkFilename: '[id].bundle.js',
},
path
path參數(shù)表示生成文件的根目錄,需要傳入一個絕對路徑滑潘。path參數(shù)和后面的filename參數(shù)共同組成入口文件的完整路徑垢乙。
publicPath
publicPath參數(shù)表示的是一個URL路徑(指向生成文件的根目錄),用于生成css/js/圖片/字體文件等資源的路徑语卤,以確保網(wǎng)頁能正確地加載到這些資源追逮。
publicPath參數(shù)跟path參數(shù)的區(qū)別是:path參數(shù)其實(shí)是針對本地文件系統(tǒng)的,而publicPath則針對的是瀏覽器粹舵;因此钮孵,publicPath既可以是一個相對路徑,如示例中的'../../../../build/'
眼滤,也可以是一個絕對路徑如http://www.xxxxx.com/
巴席。一般來說,我還是更推薦相對路徑的寫法诅需,這樣的話整體遷移起來非常方便漾唉。那什么時候用絕對路徑呢?其實(shí)也很簡單堰塌,當(dāng)你的html文件跟其它資源放在不同的域名下的時候赵刑,就應(yīng)該用絕對路徑了,這種情況非常多見于后端渲染模板的場景场刑。
filename
filename屬性表示的是如何命名生成出來的入口文件般此,規(guī)則有以下三種:
- [name],指代入口文件的name牵现,也就是上面提到的entry參數(shù)的key铐懊,因此,我們可以在name里利用
/
瞎疼,即可達(dá)到控制文件目錄結(jié)構(gòu)的效果居扒。 - [hash],指代本次編譯的一個hash版本丑慎,值得注意的是喜喂,只要是在同一次編譯過程中生成的文件,這個[hash]的值就是一樣的竿裂;在緩存的層面來說玉吁,相當(dāng)于一次全量的替換。
- [chunkhash]腻异,指代的是當(dāng)前chunk的一個hash版本进副,也就是說,在同一次編譯中,每一個chunk的hash都是不一樣的影斑;而在兩次編譯中给赞,如果某個chunk根本沒有發(fā)生變化,那么該chunk的hash也就不會發(fā)生變化矫户。這在緩存的層面上來說片迅,就是把緩存的粒度精細(xì)到具體某個chunk,只要chunk不變皆辽,該chunk的瀏覽器緩存就可以繼續(xù)使用柑蛇。
下面來說說如何利用filename參數(shù)和path參數(shù)來設(shè)計(jì)入口文件的目錄結(jié)構(gòu),如示例中的path: buildDir, // var buildDir = path.resolve(__dirname, './build');
和filename: '[name]/entry.js'
驱闷,那么對于key為'index/login'的入口文件耻台,生成出來的路徑就是build/index/login/entry.js
了,怎么樣空另,是不是很簡單呢盆耽?
chunkFilename
chunkFilename參數(shù)與filename參數(shù)類似,都是用來定義生成文件的命名方式的扼菠,只不過征字,chunkFilename參數(shù)指定的是除入口文件外的chunk(這些chunk通常是由于webpack對代碼的優(yōu)化所形成的,比如因應(yīng)實(shí)際運(yùn)行的情況來異步加載)的命名娇豫。
各種Loader配置:module參數(shù)
webpack的核心實(shí)際上也只能針對js進(jìn)行打包,那webpack一直號稱能夠打包任何資源是怎么一回事呢畅厢?原來冯痢,webpack擁有一個類似于插件的機(jī)制,名為Loader
框杜,通過Loader浦楣,webpack能夠針對每一種特定的資源做出相應(yīng)的處理。Loader的種類相當(dāng)多咪辱,有些比較基礎(chǔ)的是官方自己開發(fā)振劳,而其它則是由webpack社區(qū)開源貢獻(xiàn)出來的,這里是Loader的List:list of loaders油狂。
而module正是配置什么資源使用哪個Loader的參數(shù)(因?yàn)榫退闶峭环N資源历恐,也可能有不同的Loader可以使用,當(dāng)然不同Loader處理的手段不一樣专筷,最后結(jié)果也自然就不一樣了)弱贼。module參數(shù)有幾個子參數(shù),但是最常用的自然還是loaders
子參數(shù)磷蛹,這里也僅對loaders子參數(shù)進(jìn)行介紹吮旅。
loaders參數(shù)
loaders參數(shù)又有幾個子參數(shù),先給出一個官方示例:
module.loaders: [
{
// "test" is commonly used to match the file extension
test: /\.jsx$/,
// "include" is commonly used to match the directories
include: [
path.resolve(__dirname, "app/src"),
path.resolve(__dirname, "app/test")
],
// "exclude" should be used to exclude exceptions
// try to prefer "include" when possible
// the "loader"
loader: "babel-loader"
}
]
下面一一對這些子參數(shù)進(jìn)行說明:
-
test
參數(shù)用來指示當(dāng)前配置項(xiàng)針對哪些資源味咳,該值應(yīng)是一個條件值(condition)庇勃。 -
exclude
參數(shù)用來剔除掉需要忽略的資源檬嘀,該值應(yīng)是一個條件值(condition)。 -
include
參數(shù)用來表示本loader配置僅針對哪些目錄/文件责嚷,該值應(yīng)是一個條件值(condition)鸳兽。這個參數(shù)跟test
參數(shù)的效果是一樣的(官方文檔也是這么寫的),我也不明白為嘛有倆同樣規(guī)則的參數(shù)再层,不過我們姑且可以自己來劃分這兩者的用途:test
參數(shù)用來指示文件名(包括文件后綴)贸铜,而include
參數(shù)則用來指示目錄;注意同時使用這兩者的時候聂受,實(shí)際上是and
的關(guān)系蒿秦。 -
loader
/loaders
參數(shù),用來指示用哪個/哪些loader來處理目標(biāo)資源蛋济,這倆貨表達(dá)的其實(shí)是一個意思棍鳖,只是寫法不一樣,我個人推薦用loader
寫成一行碗旅,多個loader間使用!
分割渡处,這種形式類似于管道
的概念,又或者說是函數(shù)式編程
祟辟。形如loader: 'css?!postcss!less'
医瘫,可以很明顯地看出,目標(biāo)資源先經(jīng)less-loader處理過后將結(jié)果交給postcss-loader作進(jìn)一步處理旧困,然后最后再交給css-loader醇份。
條件值(condition)可以是一個字符串(某個資源的文件系統(tǒng)絕對路徑),可以是一個函數(shù)(官方文檔里是有這么寫吼具,但既沒有示例也沒有說明僚纷,我也是醉了),可以是一個正則表達(dá)式(用來匹配資源的路徑拗盒,最常用怖竭,強(qiáng)烈推薦!)陡蝇,最后痊臭,還可以是一個數(shù)組,數(shù)組的元素可以為上述三種類型登夫,元素之間為與關(guān)系(既必須同時滿足數(shù)組里的所有條件)趣兄。需要注意的是,loader是可以接受參數(shù)的悼嫉,方式類似于URL參數(shù)艇潭,形如'css?minimize&-autoprefixer',具體每個loader接受什么參數(shù)請參考loader本身的文檔(一般也就只能在github里看了)。
添加額外功能:plugins參數(shù)
這plugins參數(shù)相當(dāng)于一個插槽位(類型是數(shù)組)蹋凝,你可以先按某個plugin要求的方式初始化好了以后鲁纠,把初始化后的實(shí)例丟到這里來。
示例代碼
諸位看本系列文章鳍寂,搭配我在Github上的腳手架項(xiàng)目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed
)改含。
本文提到的所有內(nèi)容,都可以在示例代碼根目錄下的webpack.config.js
里找到對應(yīng)的內(nèi)容(不過可能稍微有點(diǎn)復(fù)雜呢迄汛,畢竟是一個可以投入生產(chǎn)環(huán)境的架構(gòu)了捍壤,不過看過我后續(xù)的文章,就會覺得很簡單的啦哈哈哈哈)鞍爱。
附系列文章目錄(同步更新)
- webpack多頁應(yīng)用架構(gòu)系列(一):一步一步解決架構(gòu)痛點(diǎn)
- webpack多頁應(yīng)用架構(gòu)系列(二):webpack配置常用部分有哪些鹃觉?
- webpack多頁應(yīng)用架構(gòu)系列(三):怎么打包公共代碼才能避免重復(fù)?
- webpack多頁應(yīng)用架構(gòu)系列(四):老式j(luò)Query插件還不能丟睹逃,怎么兼容盗扇?
- webpack多頁應(yīng)用架構(gòu)系列(五):聽說webpack連less/css也能打包?
- webpack多頁應(yīng)用架構(gòu)系列(六):聽說webpack連圖片和字體也能打包沉填?
- webpack多頁應(yīng)用架構(gòu)系列(七):開發(fā)環(huán)境疗隶、生產(chǎn)環(huán)境傻傻分不清楚?
- webpack多頁應(yīng)用架構(gòu)系列(八):教練我要寫ES6翼闹!webpack怎么整合Babel斑鼻?
- webpack多頁應(yīng)用架構(gòu)系列(九):總有刁民想害朕!ESLint為你阻擊垃圾代碼
- webpack多頁應(yīng)用架構(gòu)系列(十):如何打造一個自定義的bootstrap
- webpack多頁應(yīng)用架構(gòu)系列(十一):預(yù)打包Dll猎荠,實(shí)現(xiàn)webpack音速編譯
- webpack多頁應(yīng)用架構(gòu)系列(十二):利用webpack生成HTML普通網(wǎng)頁&頁面模板
- webpack多頁應(yīng)用架構(gòu)系列(十三):構(gòu)建一個簡單的模板布局系統(tǒng)
- webpack多頁應(yīng)用架構(gòu)系列(十四):No復(fù)制粘貼坚弱!多項(xiàng)目共用基礎(chǔ)設(shè)施
- webpack多頁應(yīng)用架構(gòu)系列(十五):論前端如何在后端渲染開發(fā)模式下夾縫生存
本文首發(fā)于Array_Huang的技術(shù)博客——
實(shí)用至上
,非經(jīng)作者同意法牲,請勿轉(zhuǎn)載。
原文地址:https://segmentfault.com/a/1190000006863968
如果您對本系列文章感興趣琼掠,歡迎關(guān)注訂閱這里:https://segmentfault.com/blog/array_huang