這篇文章主要介紹“Webpack中Loader和Plugin的區(qū)別是什么”,在日常操作中,相信很多人在Webpack中Loader和Plugin的區(qū)別是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Webpack中Loader和Plugin的區(qū)別是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作的關(guān)注點(diǎn)不是能為您做些什么網(wǎng)站,而是怎么做網(wǎng)站,有沒(méi)有做好網(wǎng)站,給成都創(chuàng)新互聯(lián)公司一個(gè)展示的機(jī)會(huì)來(lái)證明自己,這并不會(huì)花費(fèi)您太多時(shí)間,或許會(huì)給您帶來(lái)新的靈感和驚喜。面向用戶友好,注重用戶體驗(yàn),一切以用戶為中心。
前面兩節(jié)我們有提到Loader與Plugin對(duì)應(yīng)的概念,先來(lái)回顧下
loader 是文件加載器,能夠加載資源文件,并對(duì)這些文件進(jìn)行一些處理,諸如編譯、壓縮等,最終一起打包到指定的文件中
plugin 賦予了 webpack 各種靈活的功能,例如打包優(yōu)化、資源管理、環(huán)境變量注入等,目的是解決 loader 無(wú)法實(shí)現(xiàn)的其他事
從整個(gè)運(yùn)行時(shí)機(jī)上來(lái)看,如下圖所示:
可以看到,兩者在運(yùn)行時(shí)機(jī)上的區(qū)別:
loader 運(yùn)行在打包文件之前
plugins 在整個(gè)編譯周期都起作用
在Webpack 運(yùn)行的生命周期中會(huì)廣播出許多事件,Plugin 可以監(jiān)聽(tīng)這些事件,在合適的時(shí)機(jī)通過(guò)Webpack提供的 API改變輸出結(jié)果
對(duì)于loader,實(shí)質(zhì)是一個(gè)轉(zhuǎn)換器,將A文件進(jìn)行編譯形成B文件,操作的是文件,比如將A.scss或A.less轉(zhuǎn)變?yōu)锽.css,單純的文件轉(zhuǎn)換過(guò)程
在編寫(xiě) loader 前,我們首先需要了解 loader 的本質(zhì)
其本質(zhì)為函數(shù),函數(shù)中的 this 作為上下文會(huì)被 webpack 填充,因此我們不能將 loader設(shè)為一個(gè)箭頭函數(shù)
函數(shù)接受一個(gè)參數(shù),為 webpack 傳遞給 loader 的文件源內(nèi)容
函數(shù)中 this 是由 webpack 提供的對(duì)象,能夠獲取當(dāng)前 loader 所需要的各種信息
函數(shù)中有異步操作或同步操作,異步操作通過(guò) this.callback返回,返回值要求為 string 或者 Buffer
代碼如下所示:
// 導(dǎo)出一個(gè)函數(shù),source為webpack傳遞給loader的文件源內(nèi)容 module.exports = function(source) { const content = doSomeThing2JsString(source); // 如果 loader 配置了 options 對(duì)象,那么this.query將指向 options const options = this.query; // 可以用作解析其他模塊路徑的上下文 console.log('this.context'); /* * this.callback 參數(shù): * error:Error | null,當(dāng) loader 出錯(cuò)時(shí)向外拋出一個(gè) error * content:String | Buffer,經(jīng)過(guò) loader 編譯后需要導(dǎo)出的內(nèi)容 * sourceMap:為方便調(diào)試生成的編譯后內(nèi)容的 source map * ast:本次編譯生成的 AST 靜態(tài)語(yǔ)法樹(shù),之后執(zhí)行的 loader 可以直接使用這個(gè) AST,進(jìn)而省去重復(fù)生成 AST 的過(guò)程 */ this.callback(null, content); // 異步 return content; // 同步 }
一般在編寫(xiě)loader的過(guò)程中,保持功能單一,避免做多種功能
如less文件轉(zhuǎn)換成 css文件也不是一步到位,而是 less-loader、css-loader、style-loader幾個(gè) loader的鏈?zhǔn)秸{(diào)用才能完成轉(zhuǎn)換
由于webpack基于發(fā)布訂閱模式,在運(yùn)行的生命周期中會(huì)廣播出許多事件,插件通過(guò)監(jiān)聽(tīng)這些事件,就可以在特定的階段執(zhí)行自己的插件任務(wù)
在之前也了解過(guò),webpack編譯會(huì)創(chuàng)建兩個(gè)核心對(duì)象:
compiler:包含了 webpack 環(huán)境的所有的配置信息,包括 options,loader 和 plugin,和 webpack 整個(gè)生命周期相關(guān)的鉤子
compilation:作為 plugin 內(nèi)置事件回調(diào)函數(shù)的參數(shù),包含了當(dāng)前的模塊資源、編譯生成資源、變化的文件以及被跟蹤依賴的狀態(tài)信息。當(dāng)檢測(cè)到一個(gè)文件變化,一次新的 Compilation 將被創(chuàng)建
如果自己要實(shí)現(xiàn)plugin,也需要遵循一定的規(guī)范:
插件必須是一個(gè)函數(shù)或者是一個(gè)包含 apply 方法的對(duì)象,這樣才能訪問(wèn)compiler實(shí)例
傳給每個(gè)插件的 compiler 和 compilation 對(duì)象都是同一個(gè)引用,因此不建議修改
異步的事件需要在插件處理完任務(wù)時(shí)調(diào)用回調(diào)函數(shù)通知 Webpack 進(jìn)入下一個(gè)流程,不然會(huì)卡住
實(shí)現(xiàn)plugin的模板如下:
class MyPlugin { // Webpack 會(huì)調(diào)用 MyPlugin 實(shí)例的 apply 方法給插件實(shí)例傳入 compiler 對(duì)象 apply (compiler) { // 找到合適的事件鉤子,實(shí)現(xiàn)自己的插件功能 compiler.hooks.emit.tap('MyPlugin', compilation => { // compilation: 當(dāng)前打包構(gòu)建流程的上下文 console.log(compilation); // do something... }) } }
在 emit 事件發(fā)生時(shí),代表源文件的轉(zhuǎn)換和組裝已經(jīng)完成,可以讀取到最終將輸出的資源、代碼塊、模塊及其依賴,并且可以修改輸出資源的內(nèi)容
到此,關(guān)于“Webpack中Loader和Plugin的區(qū)別是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!