webpack初識(shí)(2)
上篇我們只是簡(jiǎn)單的說(shuō)明了如何將html寒矿,css,js使用webpack進(jìn)行打包操作,但是我們頁(yè)面不可能沒(méi)有圖片這些東西室奏,所以這篇?jiǎng)t是著重介紹幾個(gè)必不可少的loader和plugin,來(lái)完善我們頁(yè)面的基礎(chǔ)需求劲装,在這里大家可能要先預(yù)習(xí)一下ejs模板的一些語(yǔ)法知識(shí)胧沫,不然可能會(huì)看不懂(雖然我也會(huì)解釋啦)。
- 首先是loader的介紹占业,這次我們要用到的loader可就有點(diǎn)多了绒怨,他們分別是:
url-loader
,postcss-loader
谦疾,babel-loader
甜滨;記得使用npm命令安裝哦- 先來(lái)介紹一下
url-loader
帚豪,該loader可以在規(guī)定范圍內(nèi)處理圖片,將其變成base64字符串趴俘,這樣可以減少http請(qǐng)求數(shù)對(duì)于超出規(guī)定范圍的則會(huì)使用file-loader
進(jìn)行解析,不用擔(dān)心镇眷,url-loader
本身已經(jīng)封裝好了file-loader
所以就無(wú)需安裝,并且你還可以將以前需要file-loader
解析的全部交由url-loader
去解析理論上是可行的,它會(huì)處理你的js音同,css中對(duì)圖片的引用好了就介紹到這里,讓我們上代碼秃嗜,還記得上一章節(jié)里我說(shuō)的哪個(gè)結(jié)構(gòu)嗎权均?不記得是需要回去溫習(xí)一遍的哦:
使用正則在匹配字體和圖片文件,這里的// url-loader是在規(guī)定最小范圍內(nèi)將圖片等轉(zhuǎn)換成base64字符內(nèi)嵌到頁(yè)面中 { test: /\.(png|jpg|gif|svg|bmp|eot|woff|woff2|ttf)/, use: { loader: 'url-loader', options: { limit: 5 * 1024, outputPath: 'images', } } },
limit
就是設(shè)置超過(guò)這個(gè)值就會(huì)交由file-loader
去解析锅锨,而低于且包括這個(gè)大小的均會(huì)被解析成base64叽赊,outputPath則是設(shè)置輸出的位置,默認(rèn)是在dist目錄中必搞,在這里就是dist/images文件夾里了必指。那么有個(gè)糟糕的問(wèn)題,我們?cè)趆tml中直接使用img標(biāo)簽的怎么辦恕洲,這個(gè)是不被url-loader
去識(shí)別處理的塔橡,而且如果使用html-withimg-loader
則會(huì)導(dǎo)致html-webpack-plugin
不去處理html中的模板代碼,所以我們索性就去直接使用模板語(yǔ)法就好了<img src="<%= require('./image/amy.jpg')%>" alt="">
像這樣去寫霜第,就能被正確解析了葛家。- 這樣之后我們就發(fā)現(xiàn)基本上該有的功能是齊了,但是呢如果是我們使用了
transform
這個(gè)css屬性泌类,那么就需要對(duì)其做兼容寫法癞谒,但是這樣是肯定很繁瑣,總不能每個(gè)我都要寫吧刃榨,所以弹砚,我們就可以使用postcss-loader
,通過(guò)他配置的插件可以對(duì)css進(jìn)行一些處理喇澡,比如添加前綴這種迅栅;既然是loader那么就是需要配置了,這個(gè)loader需要放在你css處理的最右邊晴玖,因?yàn)樾枰热ヌ幚韈ss读存,然后交由css-loader
去處理,我們需要去webpack.config.js
文件的同級(jí)目錄去新建一個(gè)postcss.config.js
然后我們需要輸入
當(dāng)然呕屎,這里的插件我們也是要安裝的让簿,直接module.exports = { "plugins": { "postcss-import": {}, "postcss-url": {}, "autoprefixer": {} } }
npm i postcss-import postcss-loader postcss-url -D
至于他們是干嘛的,大家可以去參考postcss的文檔啦秀睛,這里就不作過(guò)多的闡述尔当。- 要是我們使用了es6的語(yǔ)法呢?瀏覽器它沒(méi)有辦法去支持那么我們的代碼就這樣作廢了?當(dāng)然不會(huì)椭迎,我們可以使用
babel-loader
對(duì)我們的js代碼進(jìn)行"降級(jí)"處理锐帜,在使用babel-loader
的時(shí)候我們需要以下幾個(gè)依賴npm i babel-core babel-plugin-transform-runtime babel-preset-env babel-preset-stage-0 -D
其中env是轉(zhuǎn)換es6,stage-0為將所有es6語(yǔ)法全部轉(zhuǎn)換為es5畜号,但是這里需要注意的是缴阎,babel-loader
的版本直接安裝是8.x的,但是其對(duì)應(yīng)的依賴還是沒(méi)有升級(jí)到简软,所以我們需要安裝7版本的蛮拔,npm i babel-loader@7 -D
就好了,現(xiàn)在我們需要去配置一下webpack的文件:
// 既然是loader痹升,那么也是在老位置建炫,接著 { test: /\.js/, exclude: /(node_modules)/, loader: 'babel-loader' }
- 先來(lái)介紹一下
在這里我新加了一個(gè)exclude
這個(gè)是告知loader忽略某個(gè)文件夾,畢竟我們總不能一股腦把依賴也編譯了把疼蛾,這樣就太傻了耗時(shí)還不討好~肛跌,至此就完成了所有的開(kāi)發(fā)需要的操作,我們可以隨意的在代碼中使用最新的技術(shù)据过,而不用擔(dān)心大部分的兼容問(wèn)題惋砂。
但是現(xiàn)在我們還需要做一件事情妒挎,就是在和package.json同級(jí)目錄下绳锅,新建一個(gè)名為 .babelrc
沒(méi)錯(cuò),文件名就叫這個(gè)酝掩,然后在里面寫上
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-0"
],
"env": {
"test": {
"presets": ["env", "stage-0"]
}
}
}
在這里則是配置babel-loader的轉(zhuǎn)換規(guī)則鳞芙,大體的意思就是將代碼轉(zhuǎn)換為第0階段,并且代碼兼容市面上使用率大于1%的瀏覽器期虾,并且不再兼容ie8原朝。而且這里的一個(gè)modules為false則是關(guān)閉對(duì)es6語(yǔ)法中import和export的轉(zhuǎn)換并且當(dāng)build環(huán)境被設(shè)置為 production
時(shí),將會(huì)啟動(dòng)代碼壓縮功能镶苞,(在文章下面的代碼壓縮部分會(huì)有詳細(xì)說(shuō)明)這個(gè)代碼壓縮的同時(shí)也會(huì)對(duì)代碼進(jìn)行檢查喳坠,只打包引用的方法或者代碼塊;但是這個(gè)功能依賴es6語(yǔ)法的import和export茂蚓,故這里關(guān)閉對(duì)這個(gè)的轉(zhuǎn)換壕鹉,來(lái)使這個(gè)設(shè)置項(xiàng)生效。
- 現(xiàn)在就是我們的plugin介紹時(shí)間了聋涨,
mini-css-extract-plugin晾浴,optimize-css-assets-webpack-plugin,copy-webpack-plugin牍白,uglifyjs-webpack-plugin
還有webpack原生自帶的HotModuleReplacementPlugin和NamedModulesPlugin脊凰。- 別看這么多,他們每個(gè)的用處基本是一樣的茂腥,現(xiàn)在先來(lái)介紹功能相同的也是最好使用的
optimize-css-assets-webpack-plugin 和 uglifyjs-webpack-plugin
他們二者都是壓縮功能狸涌,前者是壓縮css而后者則是壓縮js切省,用法很簡(jiǎn)單,在插件的位置直接new
完事帕胆!就像這樣:
而new OptimizeCSSAssetsPlugin(), new UgliftjsWebpackPlugin()
mini-css-extract-plugin
是有點(diǎn)不同的数尿,他是將css全部提取出來(lái)放到一個(gè)css文件中,這樣有個(gè)好處惶楼,減少了http的請(qǐng)求數(shù)右蹦,但是如果過(guò)大的話,反而會(huì)有壞處歼捐,但是不用擔(dān)心何陆,因?yàn)檫@個(gè)是可以配置的,這個(gè)插件的配置有點(diǎn)復(fù)雜我們需要將style-loader
替換為{ loader: MiniCssExtractPlugin.loader, options: { publicPath: '../' } },
為了方便大家我就直接寫上來(lái)啦豹储,這里是使用了該插件自帶的一個(gè)loader贷盲,然后設(shè)置了publicPath
其實(shí)這里是為了,下面做鋪墊剥扣,現(xiàn)在我們要去插件那里去設(shè)置導(dǎo)出的規(guī)則
要注意哦鞠鲜,plugins:[ new MiniCssExtractPlugin({ filename: "[name].[chunkhash:8].css", chunkFilename: "[id].css" }), ]巩剖, // 這里是為了配置css導(dǎo)出的路徑,也就是之前上面的publicPath為什么要../的原因钠怯,其實(shí)運(yùn)行起來(lái)就知道了佳魔。 optimization: { // 是否對(duì)代碼進(jìn)行壓縮,必須在production環(huán)境下才會(huì)生效晦炊! minimize: true, splitChunks: { cacheGroups: { styles: { name: 'css/index', test: /\.css$/, chunks: 'all', enforce: true } } } },
optimization
和plugins
是同級(jí)的,不要搞錯(cuò)了断国,這里我就不做過(guò)多闡述了贤姆,命名方式和之前是一樣的,這樣稳衬,就可以將css全部提取都dist目錄下的css文件夾啦霞捡。- 現(xiàn)在來(lái)說(shuō)說(shuō)
copy-webpack-plugin
這個(gè)插件,該插件的功能是將目錄或者為念拷貝到指定目錄薄疚,例如
這里碧信,new CopyWebpackPlugin([{ from: path.join(__dirname, 'public'), to: path.join(__dirname, 'dist', 'public') }]),
from
就是需要將什么文件夾或者目錄移動(dòng)到to
中設(shè)置的地方,是不是很簡(jiǎn)單易懂,當(dāng)然输涕,如果需要拷貝移動(dòng)的目錄中是空的音婶,它將不會(huì)去移動(dòng)這個(gè)目錄哦~ - 別看這么多,他們每個(gè)的用處基本是一樣的茂腥,現(xiàn)在先來(lái)介紹功能相同的也是最好使用的
- 而webpack自帶的兩個(gè)插件呢,我們需要先引入webpack莱坎,
const webpack = require('webpack')
衣式,然后在插件位置直接new webpack.HotModuleReplacementPlugin(), new webpack.NamedModulesPlugin()
,這兩個(gè)插件比較特殊,它是為了devServer中的hot碴卧,inline這兩個(gè)選項(xiàng)服務(wù)(要在devServer中加入并且設(shè)置為true才行哦)弱卡,這兩個(gè)插件是在你做了更改時(shí),只替換被你更改的那部分模塊住册,不刷新瀏覽器婶博,并且以模塊名來(lái)代替原本的id,當(dāng)然荧飞,這里可能有的小伙伴加了但是發(fā)現(xiàn)并沒(méi)有實(shí)現(xiàn)預(yù)期的不刷新瀏覽器凡人,這是因?yàn)槟K更換會(huì)觸發(fā)一個(gè)冒泡效果,當(dāng)這個(gè)冒泡被最外層的容器模塊捕捉的時(shí)候叹阔,由于沒(méi)有任何方法來(lái)處理它挠轴,所以就直接觸發(fā)了瀏覽器刷新來(lái)達(dá)到更新頁(yè)面的目的,所以需要我們自己去捕捉這個(gè)問(wèn)題這里我會(huì)說(shuō)明一下如何捕捉和處理耳幢,但是至于到底要不要這樣做岸晦。就得看你們自己了,因?yàn)槲覀€(gè)人覺(jué)得是沒(méi)太大必要睛藻。因?yàn)橹皇莏s必須要這樣處理启上,而css則不需要因?yàn)閏ss-loader已經(jīng)內(nèi)置了該功能。
// 我們需要再最外層的容器模塊中加入下面的代碼
// 最外層的容器模塊代表著承載所有模塊的入口代碼
if(module.hot){
module.hot.accept('發(fā)生更改的模塊文件名', () => {
// 此處是當(dāng)模塊發(fā)生更改之后店印,需要執(zhí)行什么行為冈在,一般的就是重新掛載一次模塊
})
}
- 當(dāng)我們的項(xiàng)目需要使用
bootstrap
怎么辦,其實(shí)非常方便吱窝,如果已經(jīng)向上面那樣配置好了讥邻,只需要npm i bootstrap
然后再主js中import
也好require
也罷迫靖,均可以正常生效院峡。
至此webpack的配置就完成了,但是我們還需要對(duì)配置文件進(jìn)行優(yōu)化系宜,我們需要區(qū)分開(kāi)開(kāi)發(fā)環(huán)境和生產(chǎn)環(huán)境照激,讓開(kāi)發(fā)環(huán)境下對(duì)代碼不進(jìn)行混淆壓縮,開(kāi)生產(chǎn)環(huán)境中則反之盹牧,這就是下一次要說(shuō)的問(wèn)題啦~有疑問(wèn)的小可愛(ài)可以在評(píng)論區(qū)提出來(lái)哦俩垃!