webpack源碼中一些精妙的方法總結
前言
過年這一段時間一直在研究webpack的源碼,由於過年周圍氣氛比較歡快,心態有點飄導致沒有沉下心來仔細研究其中的細節。經過反思之後,靜心重新捋順webpack的源碼,這時發現不少巧妙的方法值得學習。這裡我已經迫不及待的跟大傢分享瞭,希望對大傢平常開發過程中有所幫助。
精妙方法
緩存函數
這個方法最精妙的地方在於將執行結果緩存,減少函數的重復執行以達到提升性能的目的,對於執行越復雜越耗時的函數收益越大。但是,不適用於動態執行結果的函數。
const memoize = fn => { let cache = false; let result = undefined; return () => { if (cache) { return result; } else { result = fn(); cache = true; fn = undefined; return result; } }; };
這個方法跟惰性函數有點相似,隻在函數第一次調用的時候執行,將fn()的執行結果緩存到result上,然後通過cache設置為true來標記緩存已開啟。這裡還有個細節值得學習:由於閉包的原因,fn方法被新的函數持有,一直在調用棧中得不到釋放,而在代碼中有一句fn = undefined,手動釋放內存。
屬性劫持
這個方法通過自定義get方法或者value值來重定義obj的屬性。實現的結果有點類似於Object.freeze,但又不完全相同。通過Object.defineProperty定義name的get屬性描述符來保證obj的值永遠不變;通過Object.defineProperty來將name的writable設置為false來保證obj的value不會被改變。
const mergeExports = (obj, exports) => { ... for (const name of Object.keys(descriptors)) { const descriptor = descriptors[name]; if (descriptor.get) { const fn = descriptor.get; Object.defineProperty(obj, name, { configurable: false, enumerable: true, get: memoize(fn) }); } else if (typeof descriptor.value === "object") { Object.defineProperty(obj, name, { configurable: false, enumerable: true, writable: false, value: mergeExports({}, descriptor.value) }); } else { ... } } return Object.freeze(obj); };
這裡還有個小的知識點:通過將屬性的configurable屬性描述符設置為false來保證屬性不可被刪除。
數組比較
進行兩個數組是否相等的比較。想必大傢都知道,如果使用==進行數組比較的話,是進行引用地址的比較,所以想要判斷兩個數組是沒有方法進行直接比較的。而webpack源碼中的這個方法給我提供瞭一種數組比較的方式。當然瞭,這個方法隻適用於扁平化的一維基本類型數組,如果想要比較復雜的情況的話,需要在for循環的基礎上稍加改造。
exports.equals = (a, b) => { if (a.length !== b.length) return false; for (let i = 0; i < a.length; i++) { if (a[i] !== b[i]) return false; } return true; };
配置項校驗
webpack中的實現的代碼量比較多,我們就隻說一下大體實現思路,通過定義需要校驗的所有配置項的Schema校驗規則。大體Schema格式如下:
"Amd": { "description": "Set the value of `require.amd` and `define.amd`. Or disable AMD support.", "anyOf": [ { "description": "You can pass `false` to disable AMD support.", "enum": [false] }, { "description": "You can pass an object to set the value of `require.amd` and `define.amd`.", "type": "object" } ] },
其中key對應的是需要校驗的配置項,value中的desciption對應的是提示信息,其餘部分對應的是校驗規則。
結尾
到此這篇關於webpack源碼中一些精妙的方法的文章就介紹到這瞭,更多相關webpack源碼的精妙方法內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- webpack模塊化的原理解析
- 淺談Webpack是如何打包CommonJS的
- webpack output.library的16 種取值方法示例
- webpack cjs運行時分析示例詳解
- 關於vue中使用three.js報錯的解決方法