每天读一点 webpack
day-01-webpack 入口
- npm 包咱们能够通过
package.json
中的包信息文件疾速的定位到这个包的入口文件,通过webpack
的包信息main
字段能够失去整个webpack
我的项目的入口地位为lib/index.js
入口文件
- 入口文件中通过动静导入的形式将我的项目的各个模块进行整合,如各种外部插件,外部依赖,外部配置信息等。
包的缓存
-
在入口文件中通过一个缓存办法
lazyFunction
将webpack
这个模块进行了缓存操作,其中源码如下// 通过 lazyFunction 对指定包进行缓存操作 const fn = lazyFunction(() => require("./webpack"));
-
如何实现包的缓存?
lazyFunction
其实是应用了 闭包 的形式对包进行了缓存。先看要害源码,memoize
办法通过闭包的形式将入参中函数fn
的执行后果缓存起来,这样在下次想要获取fn
函数的返回后果时就无需在执行fn
办法了。const memoize = fn => { let cache = false let result = undefined // 返回一个函数 结构一个 闭包,用于缓存 fn 函数的返回值 return () => {if(cache) {return result}else {result = fn() cache = true return result } } }
-
而
lazyFunction
只是对以上memoize
办法的简略封装,使得其返回的办法反对参数传递,实际上相当于一次柯里化解决。然而memoize
中并没有承受其传入的参数,因而此次封装并无成果。其实能够间接将memoize
办法进行一步革新,让其作为返回值的函数承受入参,并传递给fn
函数即可达到预期成果,const lazyFunction = factory => {const fac = memoize(factory); const f = (...args) => {return fac()(...args); } return f; };
包的合并
-
入口文件中并没有简略对依赖进行组合,而是通过
mergeExports
办法对各个模块进行了 组装 。该办法次要通过Object.defineProperty
来达到对象组装的目标,这样做的目标是,能够更好的对对象的属性进行管制,如属性的 读、写、删除、枚举。相干源码如下getOwnPropertyDescriptors
用于获取对象上 所有属性 的描述符-
该办法中应用了递归的形式将 对象类型的属性平铺开来,这样使得 源码模块特间关系能够放弃的同时,升高了模块性能利用的复杂性。
const mergeExports = (obj, exports) => {const descriptors = Object.getOwnPropertyDescriptors(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 { throw new Error("Exposed values must be either a getter or an nested object"); } } return /** @type {A & B} */ (Object.freeze(obj)); };