每天读一点webpack-001

彭博 -
每天读一点webpack-001
每天读一点webpackday-01-webpack入口npm包我们可以通过package.json中的包信息文件快速的定位到这个包的入口文件,通过webpack的包信息main字段可以得到整个webpack项目的入口位置为 lib/index.js入口文件入口文件中通过动态导入的方式将项目的各个模块进行整合,如各种内部插件,内部依赖,内部配置信息等。包的缓存

在入口文件中通过一个缓存方法lazyFunctionwebpack 这个模块进行了缓存操作,其中源码如下

// 通过 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));
};
特别申明:本文内容来源网络,版权归原作者所有,如有侵权请立即与我们联系(cy198701067573@163.com),我们将及时处理。

Tags 标签

javascript前端node.jses6webpack

扩展阅读

加个好友,技术交流

1628738909466805.jpg