這是我學(xué)習(xí)webpack的過(guò)程宴树,后面會(huì)持續(xù)更新红省,大家可以跟著來(lái)學(xué)習(xí)额各,下面正文開(kāi)始。
什么是Webpack
WebPack可以看做是模塊打包機(jī):它做的事情是吧恃,分析你的項(xiàng)目結(jié)構(gòu)虾啦,找到JavaScript模塊以及其它的一些瀏覽器不能直接運(yùn)行的拓展語(yǔ)言(Scss,TypeScript等)痕寓,并將其轉(zhuǎn)換和打包為合適的格式供瀏覽器使用傲醉。
ps:本文都是用淘寶鏡像來(lái)安裝插件,這樣安裝速度快很多呻率,還沒(méi)安裝的小伙伴可以用下面的指令進(jìn)行安裝硬毕。
//安裝淘寶鏡像,命名為cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
安裝webpack
新建一個(gè)空的練習(xí)文件夾礼仗,我這里叫webpack-demo吐咳,然后在cmd或git打開(kāi),用cnpm初始化然后安裝webpack藐守。
package.json文件已經(jīng)就緒挪丢,然后安裝webpack和webpack-cli。
cnpm init? ?//? 初始化,終端會(huì)問(wèn)你一系列諸如項(xiàng)目名稱卢厂,項(xiàng)目描述乾蓬,作者等信息,不過(guò)不用擔(dān)心慎恒,如果你不準(zhǔn)備? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?在cnpm中發(fā)布你的模塊任内,這些問(wèn)題的答案都不重要,回車(chē)默認(rèn)即可融柬,隨即自動(dòng)生成package.json文件
cnpm i webpack webpack-cli -D? //? i指install死嗦,-D相當(dāng)于--save-dev(webpack4.0以上需要安裝webpack-cli)
在根目錄新建一個(gè)文件叫webpack.config.js,作為webpack的配置文件粒氧。
配置文件里有幾個(gè)參數(shù)越除,分別為entry、output、module摘盆、plugins翼雀、devServer,他們分別對(duì)應(yīng):
entry:配置入口文件(需要打包壓縮的文件)的地址孩擂,可以是單一入口狼渊,也可以是多入口。
output:配置出口文件的地址类垦。
module:配置模塊狈邑,主要是解析js/css和圖片轉(zhuǎn)換壓縮等功能。
plugins:配置插件蚤认,根據(jù)你的需要配置不同功能的插件米苹。
devServer:配置開(kāi)發(fā)本地服務(wù)功能
新建src文件夾,作為我們的開(kāi)發(fā)目錄烙懦,新建index.html作為模板文件
dist是打包目錄驱入,運(yùn)行打包命令后自動(dòng)生成(可在webpack配置打包路徑)
我們?cè)赼pp.js寫(xiě)個(gè)函數(shù)fun1,讓他一秒后給id為welcome的元素賦值文本內(nèi)容氯析。
(ps.用些es6語(yǔ)法亏较,let聲明變量或箭頭函數(shù),后面通過(guò)配置處理成es5)
開(kāi)始配置webpack
entry里設(shè)置入口文件掩缓,這里想壓縮app.js雪情,key為模塊名,這里命名為'app'你辣,值為app.js的路徑巡通。
output的path屬性必須是絕對(duì)路徑,這里用path.resolve(__dirname,’dist’)獲取了打包目錄的絕對(duì)路徑舍哄;filename屬性是輸入打包之后的文件名宴凉,其中[name] 指的是根據(jù)入口文件設(shè)置的模塊名,打包成相同的名稱表悬,有幾個(gè)入口文件弥锄,就可以打包出幾個(gè)文件。
開(kāi)始打包
打包之前蟆沫,我們先在package.json的script屬性設(shè)置打包的指令籽暇,webpack4.x要求設(shè)置mode
設(shè)置完之后我們打包只要在終端運(yùn)行 cnpm run build 就行了。
運(yùn)行cnpm run build進(jìn)行打包饭庞,打包成功戒悠,發(fā)現(xiàn)他在dist/js目錄自動(dòng)生成一個(gè)app.bundle.js,這個(gè)就是打包后的壓縮文件舟山。
打開(kāi)app.bundle.js文件绸狐,打包之后能找到之前在app.js書(shū)寫(xiě)的代碼卤恳,雖然有一點(diǎn)不一樣,運(yùn)行起來(lái)效果是一樣的寒矿。
我們把a(bǔ)pp.bundle.js引入根目錄的index.html纬黎,然后打開(kāi)在瀏覽器運(yùn)行看看。
運(yùn)行效果:1秒后頁(yè)面顯示“歡迎使用webpack”劫窒。
這樣就是一個(gè)簡(jiǎn)單的打包過(guò)程,但在一般的項(xiàng)目中拆座,我們還需要打包其他的文件主巍,如css文件和圖片文件,下面就介紹下如何打包這類(lèi)文件挪凑。
使用html-webpack-plugin
看到plugin就知道這是個(gè)插件孕索,它會(huì)在打包的時(shí)候,根據(jù)我們配置的模板html去生成一個(gè)入口html文件躏碳,然后自動(dòng)幫我們引用打包的資源文件搞旭,比如js、css菇绵。這樣的話肄渗,即使我們需要打包很多js文件和css文件,也不必自己手動(dòng)去添加了咬最,方便了很多翎嫡。
安裝html-webpack-plugin
cnpm?i?html-webpack-plugin -D
先引用html-webpack-plugin,然后在plugins進(jìn)行初始化
**filename:打包生成的html名稱永乌;
**template:模板html文件惑申;
**inject:引入打包資源文件的位置
把根目錄引用的app.bundle.js刪掉,然后運(yùn)行打包命令cnpm run build翅雏,然后在dist目錄自動(dòng)生成一個(gè)index.html文件圈驼,他也自動(dòng)引入了打包的js文件,瀏覽器運(yùn)行打包的index.html也正常望几,成功绩脆!
這里先提前說(shuō)下loader的處理順序
=============================================================
loader的工作方式是先處理后面的loader,然后一步步往前執(zhí)行橄妆,比如 {loaders: 'style-loader!css-loader!postcss-loader!less-loader'},它就是先處理less-loader衙伶,接著處理postcss-loader,然后執(zhí)行css-loader害碾,最后處理style-loader矢劲。
=============================================================
使用babel-loader處理js
現(xiàn)在前端開(kāi)發(fā)基本都在使用ES6的語(yǔ)法了,但是ES6,ES7這些標(biāo)準(zhǔn)目前并未被當(dāng)前的瀏覽器完全支持慌随,所以我們可以利用babel-preset-env躺同,它可以根據(jù)配置的目標(biāo)瀏覽器或者運(yùn)行環(huán)境來(lái)自動(dòng)將ES2015+的代碼轉(zhuǎn)換為es5。
安裝babel-loader、@babel/core和@babel/preset-env涛救,@babel/core是babel核心包,@babel/preset-env是ES語(yǔ)法分析包。
cnpm i?babel-loader @babel/core @babel/preset-env -D
在根目錄創(chuàng)建.babelrc文件摊灭,作為babel-loader的配置文件,當(dāng)babel-loader運(yùn)行的時(shí)候,會(huì)檢查這個(gè)配置文件,并讀取相關(guān)的語(yǔ)法和插件配置
**test:用正則匹配需要使用loader的文件
**use:設(shè)置需要用到的loader
**include:設(shè)置需要轉(zhuǎn)換的文件目錄,這里設(shè)置開(kāi)發(fā)目錄src,這樣他就只會(huì)檢測(cè)src目錄下的js文件;
**exclude:設(shè)置不需要轉(zhuǎn)換的文件目錄辅甥,這里設(shè)置插件依賴包目錄node_modules构回,這樣打包會(huì)快點(diǎn)拨扶。
運(yùn)行cnpm run build進(jìn)行打包垦梆,然后打開(kāi)打包生成的app.bundle.js文件辽慕,可以看到經(jīng)過(guò)處理公浪,已經(jīng)把箭頭函數(shù)轉(zhuǎn)譯成功镜撩。
使用css-loader和style-loader處理css
webpack無(wú)法自己打包c(diǎn)ss文件,他需要css-loader和style-loader:
css-loader幫助webpack打包處理css文件
經(jīng)過(guò)css-loader的處理,style-loader主要是新建一個(gè)style標(biāo)簽灸芳,然后插入到html的head標(biāo)簽里蕊肥。
在src/css目錄下新建一個(gè)公共的css文件,命名為common.js,然后先隨便寫(xiě)點(diǎn)樣式。
我們把他引入app.js,在打包的時(shí)候順便處理一下css文件。
安裝css-loader和style-loader
cnpm i css-loader style-loader -D
安裝好嘹朗,開(kāi)始配置css的打包規(guī)則
**test:用正則匹配以css結(jié)尾的文件
**use:設(shè)置需要使用的loader
運(yùn)行cnpm run build進(jìn)行打包惫谤,運(yùn)行成功后瀏覽器打開(kāi)dist/index.hmtl蝴猪,看到body的背景色變了米酬,樣式生效叫确。
打開(kāi)開(kāi)發(fā)者工具看到在head標(biāo)簽里新增了一個(gè)style標(biāo)簽次乓,里面的樣式就是剛才定義的commo.css的樣式丧慈。
使用postcss-loader自動(dòng)處理CSS3屬性前綴
為了瀏覽器的兼容性,有時(shí)候我們必須加入-webkit,-ms,-o,-moz這些前綴姿现。目的就是讓我們寫(xiě)的頁(yè)面在每個(gè)瀏覽器中都可以順利運(yùn)行吮蛹,我們這里使用postcss-loader來(lái)幫我們自動(dòng)補(bǔ)充前綴喜每。
安裝postcss-loader和autoprefixer(自動(dòng)添加前綴的插件)喧兄。
cnpm i postcss-loader autoprefixer -D
安裝好這兩個(gè)模塊后,在項(xiàng)目根目錄下新建?postcss.config.js?和?.browserslistrc?文件未荒,分別作為postcss-loader和browserslist的配置文件及志。
Replace Autoprefixer browsers option to Browserslist config. Use browserslist key in package.json or .browserslistrc file. Using browsers option can cause errors. Browserslist config can be used for Babel, Autoprefixer, postcss-normalize and other tools.
browserslist key屬性建議在packge.json或者新建一個(gè).browserslistrc文件進(jìn)行配置 (ps.browserslist配置說(shuō)明)
這里選擇后者新建.browserslistrc文件的方式
對(duì)postcss.config.js配置完成后片排,我們還需要編寫(xiě)我們的loader配置,在use里添加postcss-loader速侈。
注意:如果我們要打包的css文件里面引用了其他css文件划纽,他會(huì)幫我打包,但是不會(huì)幫我們處理前綴锌畸,那么該如何處理@import引入的css文件勇劣,如何讓他自動(dòng)加上前綴呢?
這時(shí)候我們需要借助css-loader的?importLoaders?參數(shù)
importLoaders? ??默認(rèn)值:0? ? 描述:在 css-loader 前應(yīng)用的 loader 的數(shù)
配置css-loader
這里的importLoaders: 1?是在css-loader?之后指定1個(gè)數(shù)量的loader(即 postcss-loader)來(lái)處理import進(jìn)來(lái)的資源。
在src/css目錄新建一個(gè)tem.css比默,并設(shè)置樣式幻捏。
在common.css文件頭引入剛創(chuàng)建的tem.css
在根目錄index.html引用樣式f-rotate45
OK,common.css里面引入了其他css文件命咐,我們的css-loader也配置好了篡九,開(kāi)始打包,運(yùn)行cnpm run build醋奠,瀏覽器打開(kāi)dist/index.html預(yù)覽榛臼。
打開(kāi)開(kāi)發(fā)者工具可以看到head標(biāo)簽里又多了一個(gè)style標(biāo)簽,展開(kāi)一看就是剛才創(chuàng)建的tem.css窜司,并且他幫我們補(bǔ)上前綴了沛善,完成!
使用extract-text-webpack-plugin分離css
有些簡(jiǎn)單的交互頁(yè)面中塞祈,你的JavasScript頁(yè)面代碼會(huì)非常少金刁,而大部分代碼都在CSS中,這個(gè)插件就可以完美地幫我們提取CSS议薪。
安裝 extract-text-webpack-plugin
cnpm i extract-text-webpack-plugin -D
開(kāi)始配置
首先require引用插件尤蛮,然后修改css配置,最后在plugins里面初始化實(shí)例斯议。
extract-text-webpack-plugin的參數(shù)說(shuō)明:
**use:用于將資源轉(zhuǎn)換為CSS導(dǎo)出模塊的加載程序(必需)产捞;
**fallback:未提取CSS時(shí)應(yīng)使用的加載程序(例如“style-loader”),即編譯后用什么loader來(lái)提取css文件哼御。
配置完成坯临,運(yùn)行cnpm run build打包,終端出現(xiàn)報(bào)錯(cuò)信息艇搀。
原因:webpack4不再支持extract-text-webpack-plugin這個(gè)插件尿扯,需要使用最新版或者替代插件求晶。
解決辦法:卸載之前版本插件焰雕,并安裝最新測(cè)試版。
cnpm i extract-text-webpack-plugin@next -D
再次運(yùn)行cnpm run build打包芳杏,看到dist目錄生成一個(gè)css文件夾矩屁,里面有個(gè)index.css文件,我們寫(xiě)過(guò)的樣式都在index.css里爵赵,看來(lái)分離成功了吝秕。
打包生成的index.html也自動(dòng)引入了index.css,瀏覽器運(yùn)行也正常空幻。
使用purifycss-webpack烁峭、purify-css去除冗余的 css
有時(shí)候我們聲明了很多樣式,但部分樣式并沒(méi)有用到,這樣就會(huì)造成冗余约郁,剛好有插件能幫忙解決缩挑。
注意:如果想使用purify-css 的話,必須結(jié)合extract-text-webpack-plugin 這個(gè)插件鬓梅,否則沒(méi)效果9┲谩!绽快!
安裝?purifycss-webpack芥丧、purify-css。
cnpm i purifycss-webpack purify-css -D
開(kāi)始配置
在webpack.config.js文件頭部引入glob和purifycss-webpack坊罢,因?yàn)槲覀冃枰?b>同步檢查html模板续担,所以我們需要引入node的glob對(duì)象來(lái)使用。
然后在plugins初始化實(shí)例艘绍,這里配置了一個(gè)paths赤拒,主要是尋找html模板,purifycss根據(jù)這個(gè)配置會(huì)遍歷你的文件诱鞠,查找哪些css被使用了挎挖。
開(kāi)始使用
在tem.css里寫(xiě)一個(gè)沒(méi)用的樣式
運(yùn)行cnpm run build打包命令,查看生成的index.css文件航夺,發(fā)現(xiàn)他只展示了我們用到的樣式蕉朵,剛才聲明的.nonesense沒(méi)打包進(jìn)去,而且以前在common.css聲明的.f-flex-box也沒(méi)對(duì)其進(jìn)行打包阳掐。
使用less-loader處理less
新建一個(gè)組件文件夾components和一個(gè)layer組件始衅,并創(chuàng)建layer的html、less和js文件缭保。
在layer.less文件寫(xiě)點(diǎn)樣式汛闸,然后layer.js引入layer.less文件,并且在app.js引入組件layer艺骂。
注意:千萬(wàn)不能在css文件引入less和scss文件诸老,css 引入less和scss 語(yǔ)法是不起作用的,必須同文件引用才能正確解析G 别伏!也就是說(shuō)css文件只能引入css文件,less文件只能引入less文件忧额。
不能把我們新建的layer.less在common.css或者tem.css里面引入厘肮,我這里是在組件layer的js文件里面引入less,然后app.js再引入layer組件睦番,然后打包的時(shí)候?qū)pp里面引入的common.css类茂、layer.js還有自身的js進(jìn)行打包。
配置less
在module添加less的規(guī)則
在根目錄的模板index.html添加個(gè)div,寫(xiě)上剛才在layer.less定義的 #m-new-wrap巩检,因?yàn)闆](méi)用到的樣式會(huì)被purifycss-webpack給過(guò)濾掉恬涧。
打包運(yùn)行cnpm run build,運(yùn)行成功后瀏覽器打開(kāi)dist/index.hmtl碴巾,發(fā)現(xiàn)頁(yè)面有點(diǎn)變化了溯捆,是新增加的樣式生效了。打開(kāi)開(kāi)發(fā)者工具查看厦瓢,剛才的樣式被style標(biāo)簽包住然后加在head標(biāo)簽里提揍。
我們發(fā)現(xiàn)他并沒(méi)有分離css,這里我們用 extract-text-webpack-plugin 修改下配置煮仇,讓less解析完寫(xiě)入index.css劳跃。
打包運(yùn)行cnpm run build,打包完成后浙垫,查看index.css文件刨仑,可以看到分離成功。
思考:我們前面講到一個(gè)css文件@import了其他css文件夹姥,我們想其他css文件也自動(dòng)補(bǔ)全前綴的話杉武,我們必須配置css-loader的importLoaders屬性,那么問(wèn)題來(lái)了辙售,如果一個(gè)less文件@import了其他less文件的話轻抱,那這里也需要配置importLoaders屬性嗎?
·
·
·
·
答案是:不需要配置importLoaders旦部,因?yàn)閘ess文件他先處理了@import進(jìn)來(lái)的less文件祈搜,然后再交給postcss-laoder去添加前綴。小伙伴們可以自己試試看士八。
使用sass-loader處理sass
安裝node-sass和sass-loader
cnpm i node-sass sass-loader -D
配置sass
sass的配置和less差不多
新建一個(gè)layer.scss文件容燕,修改layer.js引入layer.scss。
打包運(yùn)行cnpm run build婚度,打包成功蘸秘,查看生成的index.css文件。
思考:我們前面講到一個(gè)css文件@import了其他css文件陕见,我們想其他css文件也自動(dòng)補(bǔ)全前綴的話秘血,我們必須配置css-loader的importLoaders屬性味抖,但一個(gè)less文件@import了其他less文件评甜,就不需要配置importLoaders屬性,那么問(wèn)題來(lái)了仔涩,如果一個(gè)scss文件@import了其他scss文件的話忍坷,那這里需要配置importLoaders屬性嗎?
·
·
·
我們來(lái)試一下,我們先把purifycss給注釋掉佩研,別讓他把沒(méi)用的代碼過(guò)濾了柑肴。然后新建一個(gè)new_layer.scss文件,并寫(xiě)下需要自動(dòng)補(bǔ)全的樣式旬薯,并且在layer.scss引入new_layer.scss晰骑。
打包運(yùn)行cnpm run build,打包成功绊序,查看生成的index.css文件硕舆,可以看到new_layer經(jīng)過(guò)處理了,并且自動(dòng)加上了前綴骤公。
說(shuō)明sass-loader和less-loader一樣抚官,先處理引入的文件,然后再交給postcss-loader去處理阶捆。
(ps:sass-loader很奇怪凌节,我在網(wǎng)上看別人都是得配置importLoaders的,但是我自己測(cè)試卻不用加洒试,后期再研究研究倍奢。)
使用file-loader、url-loader處理圖片
我們先創(chuàng)建一個(gè)images的文件夾垒棋,里面存放幾張圖片待會(huì)用娱挨,然后找個(gè)css文件設(shè)置個(gè)背景為圖片資源,這里我在layer.scss里改寫(xiě)之前的樣式捕犬。
然后運(yùn)行打包命令cnpm run build跷坝,發(fā)現(xiàn)報(bào)錯(cuò)了,他解析不了圖片碉碉,提示我們需要適當(dāng)?shù)奶幚砥魅ヌ幚磉@種圖片類(lèi)型柴钻。
這里我們用 file-loader 和 url-loader 來(lái)解析圖片:
**file-loader:解決引用路徑的問(wèn)題,拿background樣式用url引入背景圖來(lái)說(shuō)垢粮,我們都知道贴届,webpack最終會(huì)將各個(gè)模塊打包成一個(gè)文件,因此我們樣式中的url路徑是相對(duì)入口html頁(yè)面的蜡吧,而不是相對(duì)于原始css文件所在的路徑的毫蚓。這就會(huì)導(dǎo)致圖片引入失敗。這個(gè)問(wèn)題是用file-loader解決的昔善,file-loader可以解析項(xiàng)目中的url引入(不僅限于css)元潘,根據(jù)我們的配置,將圖片拷貝到相應(yīng)的路徑君仆,再根據(jù)我們的配置翩概,修改打包后文件引用路徑牲距,使之指向正確的文件。
**url-loader:如果圖片較多钥庇,會(huì)發(fā)很多http請(qǐng)求牍鞠,會(huì)降低頁(yè)面性能。這個(gè)問(wèn)題可以通過(guò)url-loader解決评姨。url-loader會(huì)將引入的圖片編碼难述,生成dataURl。相當(dāng)于把圖片數(shù)據(jù)翻譯成一串字符吐句。再把這串字符打包到文件中龄广,最終只需要引入這個(gè)文件就能訪問(wèn)圖片了。當(dāng)然蕴侧,如果圖片較大择同,編碼會(huì)消耗性能。因此url-loader提供了一個(gè)limit參數(shù)净宵,小于limit字節(jié)的文件會(huì)被轉(zhuǎn)為DataURl敲才,大于limit的還會(huì)使用file-loader進(jìn)行copy。
安裝 file-loader 和 url-loader
cnpm i?file-loader url-loader -D
配置url-loader
**use:指定使用的loader和loader的配置參數(shù)择葡;
**limit:把小于500000B的文件打成Base64的格式紧武。
運(yùn)行打包命令,編譯成功敏储,在index.css可以看到有個(gè)background的圖片鏈接是base64阻星,打開(kāi)瀏覽器運(yùn)行也能看到背景圖樣式生效了。
這里說(shuō)明一下為什么只使用了url-loader
有的小伙伴會(huì)發(fā)現(xiàn)我們并沒(méi)有在webpack.config.js中使用file-loader已添,但是依然打包成功了妥箕。我們需要了解file-loader和url-loader的關(guān)系。url-loader和file-loader是什么關(guān)系呢更舞?簡(jiǎn)答地說(shuō)畦幢,url-loader封裝了file-loader。url-loader不依賴于file-loader缆蝉,即使用url-loader時(shí)宇葱,只需要安裝url-loader即可,不需要安裝file-loader刊头,因?yàn)閡rl-loader內(nèi)置了file-loader黍瞧。通過(guò)上面的介紹,我們可以看到原杂,url-loader工作分兩種情況:
1.文件大小小于limit參數(shù)印颤,url-loader將會(huì)把文件轉(zhuǎn)為DataURL(Base64格式);
2.文件大小大于limit污尉,url-loader會(huì)調(diào)用file-loader進(jìn)行處理膀哲,參數(shù)也會(huì)直接傳給file-loader。
也就是說(shuō)被碗,其實(shí)我們只安裝一個(gè)url-loader就可以了某宪。但是為了以后的操作方便,我們這里就順便安裝上file-loader锐朴。
我們上面limit限制了500000B大小的圖片兴喂,也就是說(shuō)超過(guò)488kb就交給file-loader去處理,我們這里試一下把背景圖換成大于488kb的圖片焚志,然后打包衣迷,再看看index.css文件,看看發(fā)生什么變化酱酬,我們發(fā)現(xiàn)路徑不對(duì)壶谒,而且在瀏覽器運(yùn)行也沒(méi)效果。
為什么會(huì)這樣呢膳沽?其實(shí)不分離css就能顯示圖片汗菜,因?yàn)槲覀冎鞍阉械腸ss給分離了,背景圖片設(shè)置了相對(duì)路徑挑社,所以分離之后的圖片路徑就不對(duì)了陨界,也就不會(huì)正常顯示了。