产品性能提升的一小步(组件库按需引入方案)

141 阅读1分钟

问题

在开发中,我们经常会维护一下常用的组件库、工具库,但是随着业务的开展这些组件库往往功能越来越多,体积越来越大,不利于项目的加载。为此我们需要进行组件库的按需引入,没有用到的功能不会打包到项目当中。



解决方案

思路

1.根据js模块引入规则,当有相互依赖的模块最终会打包到项目中

2.所以我们需要将组件库中的各种组件进行解耦并单独导出

3.为此我们在组件库中维护一个packages文件夹,用于存放各个独立的导出的组件

4.这时我们就可以通过 import aaa from "xxx/packages/aaa" 的方式进行按需引入了

5.但是我们在组件使用中习惯于 import { aaa, bbb} from "xxx" 的语法形式

6.为此我们需要对于上述的语法进行解析

7.可以通过webpack的loader机制进行语法的解析



代码实现

const getOptions = require("loader-utils").getOptions;

function handlePackage(source, packageName, packageDirName = "packages") {
  const regStr = `import.*{(.*)}.*"${packageName}"`;
  const reg = new RegExp(regStr, "g");
  let match;
  let tempSource = source;
  while ((match = reg.exec(source))) {
    const importStr = match[0];
    const moduleStr = match[1];
    reg.lastIndex = match.index + importStr.length;
    const resStr = moduleStr
      .trim()
      .split(",")
      .map((moduleName) => {
        moduleName = moduleName.trim();
        return `import ${moduleName} from "${packageName}/${packageDirName}/${moduleName}"`;
      })
      .join("\n");

    tempSource = tempSource.replace(importStr, resStr);
  }

  return tempSource;
}

function simpleImportLoader(source) {
  const { packageArr } = getOptions(this);
  let tempSource = source;
  packageArr.forEach(({ packageName, packageDirName }) => {
    tempSource = handlePackage(tempSource, packageName, packageDirName);
  });

  return tempSource;
}

module.exports = simpleImportLoader;