webpack之Loader

loader支持鏈式調用,所以開發上需要嚴格遵循“單一職責”原則,即每個loader只負責自己需要負責的事情:將輸入信息進行處理,並輸出為下一個loader可識別的格式。

實際開發中,很少會出現需要自己寫loader來實現複雜需求的場景,如果某個擴展名的文件無法快速集成到自動化構建工具裡,估計很快就會被拋棄了,大家都那麼忙是吧。但是瞭解loader的基本原理和編譯器的基本原理卻是非常有必要的。

二. 如何寫一個loader

如果需要編寫一個功能完整的loader,建議先到webpack的官方網站瀏覽一下loader有哪些API,地址:webpack官網-loader API,其中對於編寫同步loader,異步loader,如何跳過loader,如何獲取options配置項等等都做了非常詳細的解釋,本篇中不再贅述。

假設現在要實現一個dash-loader,它的功能是加載並處理名稱為*.tpl.html的文件,將其變為一個CommonJs模塊。也就是說要完成一個如下的基本轉換:

轉換前的文本:


這裡是標題


這裡是內容


轉換後的文本:

var str = '

這裡是標題

這裡是內容

';module.exports = str;

那麼webpack.config.js中需要增加如下的配置:

...
module:{ rules:[{ test: /\.tpl\.html$/, use:[{ loader:'dash-loader'
}]
}]
}

在項目的node_modules依賴文件夾中新建dash-loader文件夾,並在其中新建一個index.js文件,內容的基本格式為:

//index.jsmodule.exports = function(source){ var tpl="";
source.split(/\r?\n/).forEach(function(line){
line=line.trim(); if(!line.length){ return;
} //對line進行處理...
tpl+=line;
}); return "var tpl=\'" + tpl + "\'\nmodule.exports = tpl";
}

最終由dash-loader返回的數據就好像是從某個CommonJs模塊中讀入的一樣了。

三. loader的編譯器本質

瞭解了loader的基本結構,那麼loader裡到底應該寫點什麼才能完成代碼轉換呢?這就涉及到了一個新的概念——編譯器(Compiler)。一個基本的編譯器,需要經過tokenize,parse,transform,stringify幾個核心步驟,它的應用是非常廣的,SPA中的virtual-DOM的解析,babel中的ES6語法解析等等,babel的官網曾經推薦過一個非常棒的開源項目(10k+Star),詳細講述瞭如何一步一步實現一個編譯器的,建議感興趣的同學可以自行學習。

https://github.com/jamiebuilds/the-super-tiny-compiler


分享到:


相關文章: