摘要:動(dòng)態(tài)編譯編譯到這行的時(shí)候進(jìn)行編譯原理分析注本文參考代碼為版本代碼。于是簡(jiǎn)單寫了一個(gè)運(yùn)行去看這個(gè)的執(zhí)行時(shí)機(jī)以及。當(dāng)然雖然是廢棄的,但是這個(gè)模塊已經(jīng)鎖死,所以大佬還在肆無忌憚的用,當(dāng)然已經(jīng)做了修正
babel原理分析-babel-register addHook 前言
閱讀本文時(shí)希望您對(duì)babel-register有一定了解,如果還有不了解的可以閱讀之前的文章傳送門
在之前的文章中已經(jīng)簡(jiǎn)單介紹了babel-register的功能
那么babel如何給require加上鉤子,使得在node環(huán)境下實(shí)現(xiàn)動(dòng)態(tài)編譯的呢(靜態(tài)編譯:統(tǒng)一babel。動(dòng)態(tài)編譯:js編譯到這行的時(shí)候進(jìn)行編譯)
原理分析注:本文參考代碼為babel-0.7.0-beta版本代碼。
其實(shí)在上文babel-register中可以看到,node環(huán)境下babel的編譯,是通過一個(gè)require上addHook的解決方法,那么這個(gè)hook是怎么掛載到require上的呢
首先想到的是node官版有沒有提供原生的方法處理,官版確實(shí)提供了一個(gè)require.extensions的方法,可惜已經(jīng)廢棄了,moudle模塊也沒有所謂addhook的辦法。那就只能安靜點(diǎn)看pirate的實(shí)現(xiàn)了
深入pirate的源碼時(shí),我們卻發(fā)現(xiàn)實(shí)際pirate這個(gè)npm包并沒有做什么功能
核心代碼不超過100行,如下
const Module = module.constructor.length > 1 ? module.constructor : BuiltinModule; export function addHook(hook, opts = {}) { // eslint-disable-line import/prefer-default-export let reverted = false; const loaders = []; const oldLoaders = []; let exts; const originalJSLoader = Module._extensions[".js"]; const matcher = opts.matcher || null; const ignoreNodeModules = opts.ignoreNodeModules !== false; exts = opts.extensions || opts.exts || opts.extension || opts.ext || [".js"]; if (!Array.isArray(exts)) exts = [exts]; exts.forEach((ext) => { if (typeof ext !== "string") throw new TypeError(`Invalid Extension: ${ext}`); const oldLoader = Module._extensions[ext] || originalJSLoader; oldLoaders[ext] = oldLoader; loaders[ext] = Module._extensions[ext] = function newLoader(mod, filename) { let compile; if (!reverted) { if (shouldCompile(filename, exts, matcher, ignoreNodeModules)) { compile = mod._compile; mod._compile = function _compile(code) { mod._compile = compile; const newCode = hook(code, filename); if (typeof newCode !== "string") { throw new Error(HOOK_RETURNED_NOTHING_ERROR_MESSAGE); } return mod._compile(newCode, filename); }; } } oldLoader(mod, filename); }; }); return function revert() { if (reverted) return; reverted = true; exts.forEach((ext) => { if (Module._extensions[ext] === loaders[ext]) { Module._extensions[ext] = oldLoaders[ext]; } }); }; }
看起來這個(gè)代碼做的事很簡(jiǎn)單就是在給原生moudle方法上不斷地掛載moudle._extension[".js/.es6/.jsx"]之類的處理func,始終沒有看到執(zhí)行時(shí)機(jī)。
于是簡(jiǎn)單寫了一個(gè)demo
console.log("naturelessTT") debugger; require("require.js")
babel-node index.js --inspect-brk運(yùn)行去看這個(gè)hook的執(zhí)行時(shí)機(jī)以及call stack。
實(shí)際是require文件時(shí),io讀取文件后會(huì)通過moudle.load的方法加載文件,然后依次執(zhí)行_extension里掛載的方法
真相大白,但是令人驚訝的是0.7之前的版本并沒有引入pirate這個(gè)包,看了0.6.26版本后,emmmm,babel大佬使用了官版已經(jīng)標(biāo)記為廢棄的require.extensions。
當(dāng)然雖然是廢棄的,但是node這個(gè)模塊已經(jīng)鎖死,所以babel大佬還在肆無忌憚的用,當(dāng)然0.7已經(jīng)做了修正
Deprecated In the past, this list has been used to load non-JavaScript modules into Node.js by compiling them on-demand. However, in practice, there are much better ways to do this, such as loading modules via some other Node.js program, or compiling them to JavaScript ahead of time. Since the module system is locked, this feature will probably never go away. However, it may have subtle bugs and complexities that are best left untouched. Note that the number of file system operations that the module system has to perform in order to resolve a require(...) statement to a filename scales linearly with the number of registered extensions. In other words, adding extensions slows down the module loader and should be discouraged.
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93617.html
摘要:是怎么工作的如何編譯應(yīng)用場(chǎng)景語法糖的代碼統(tǒng)一相關(guān)概念介紹依賴,提供的方法,只轉(zhuǎn)化語法,不轉(zhuǎn)換類,的基礎(chǔ)配置利用對(duì)進(jìn)行劫持,在中進(jìn)行原理見同時(shí)對(duì)后的進(jìn)行緩存,提高下次效率讀取緩存根據(jù)判斷是否需要重新中傳入配置入口函數(shù)提供 Babel babel是怎么工作的? parse->AST->transform->gengerate 如何編譯js->AST babel應(yīng)用場(chǎng)景 語法糖的polyfi...
摘要:安裝然后在的配置文件加入入口文件引入這樣就可以啦,還是可以減少很多代碼量的。是參數(shù),等同于執(zhí)行正常。這個(gè)包很簡(jiǎn)單,就是引用了和,然后生產(chǎn)環(huán)境把它們編譯到目錄下,做了映射,供使用。 引入 這個(gè)問題是對(duì)自己的發(fā)問,但我相信會(huì)有很多跟我一樣的同學(xué)。對(duì)于 babel 的使用,近半年來一直停留在與 webpack 結(jié)合使用,以及在瀏覽器開發(fā)環(huán)境下。導(dǎo)致很多 babel 的包,我都不清楚他們是干嘛...
摘要:今天分享一篇公司大佬的文章,非常厲害的大神崇拜臉,講講服務(wù)端渲染。服務(wù)端渲染,它到底用了什么原理呢服務(wù)端渲染原理服務(wù)端渲染的方式有很多,主流的服務(wù)端語言為使用渲染。 富婆來報(bào)道,今天想問題想不出來,隨手抓了一下頭發(fā),沒想到啊沒想到,我那濃(mei)密(sheng)茂(ji)盛(gen)的秀發(fā)又少了好幾根,一定要改掉這個(gè)想不出來問題就揪頭發(fā)的壞習(xí)慣。今天分享一篇公司大佬的文章,非常厲害的...
摘要:如何讓運(yùn)行模塊文件,及其原理最新版的支持最新版幾乎所有特性,但有一個(gè)特性卻一直到現(xiàn)在都還沒有支持,那就是從開始定義的模塊化機(jī)制。便是使用這種方式達(dá)到運(yùn)行模塊文件的目的的。 如何讓 node 運(yùn)行 es6 模塊文件,及其原理 最新版的 node 支持最新版 ECMAScript 幾乎所有特性,但有一個(gè)特性卻一直到現(xiàn)在都還沒有支持,那就是從 ES2015 開始定義的模塊化機(jī)制。而現(xiàn)在我們很...
摘要:安裝注意版本為為支持語法安裝依賴包注意為了使支持語法,在加入注意為了使支持語法,在加入小貓快跳最終運(yùn)行或都可以參考 安裝 mocha, chai,mochawesome,istanbul npm install mocha chai mochawesome [email protected] --save-dev 注意1: istanbul 版本為 ^1.0.0-alpha....
閱讀 2912·2021-11-25 09:43
閱讀 2338·2021-11-24 09:39
閱讀 2722·2021-09-23 11:51
閱讀 1415·2021-09-07 10:11
閱讀 1459·2019-08-27 10:52
閱讀 1947·2019-08-26 12:13
閱讀 3368·2019-08-26 11:57
閱讀 1405·2019-08-26 11:31