关于babel-plugin-istanbul与babel-plugin-import冲突问题的官方解决方法

问题:

Does not work with babel-plugin-import

使用babel7后,按需加载执行报错

以上两个问题都是关于同时使用了istanbul与import的babel插件以后导致的问题。


20201218090823471.png

编译后的前端代码运行后就会报上述的错误。

分析

首先通过上面的issue我们先清楚的了解到一个问题。
为什么

const { Option } = Select;

就存在有问题,但是通过

const Option = Select.Option;

就没有问题呢?

这里我们就需要先了解经过istanbul插桩后变成了怎么样内容了, 我们可以来看下。


const {
  Option
} = (cov_1eldv8eouu().s[0]++, Select.Option);

const {
  Option
} = (cov_1eldv8eouu().s[0]++, Select);

以上就是经过babel解析后的结果,那么这两个给到babel-plugin-import解析后有什么区别呢?

这里就需要我们先确认下 这两个地方首先他经过babel解析成ast的结果是什么样的了?

const {
  Option
} = (cov_1eldv8eouu().s[0]++, Select.Option);
在这里插入图片描述

可以看到这里有个MemberExpression

 MemberExpression(path, state) {
    const { node } = path;
    const file = (path && path.hub && path.hub.file) || (state && state.file);
    const pluginState = this.getPluginState(state);

    // multiple instance check.
    if (!node.object || !node.object.name) return;

    if (pluginState.libraryObjs[node.object.name]) {
      // antd.Button -> _Button
      path.replaceWith(this.importMethod(node.property.name, file, pluginState));
    } else if (pluginState.specified[node.object.name] && path.scope.hasBinding(node.object.name)) {
      const { scope } = path.scope.getBinding(node.object.name);
      // global variable in file scope
      if (scope.path.parent.type === 'File') {
        node.object = this.importMethod(pluginState.specified[node.object.name], file, pluginState);
      }
    }
  }

可以看到babel-plugin-import 是否这块相应的处理的。
但是针对

const {
  Option
} = (cov_1eldv8eouu().s[0]++, Select);

babel解析的结果为

在这里插入图片描述

babel-plugin-import并没有单独针对Identifier的处理逻辑的。

针对这个问题的解决如下:

buildDeclaratorHandler(node, prop, path, state) {
    const file = (path && path.hub && path.hub.file) || (state && state.file);
    const { types } = this;
    const pluginState = this.getPluginState(state);

    const checkScope = targetNode =>
      pluginState.specified[targetNode.name] && // eslint-disable-line
      path.scope.hasBinding(targetNode.name) && // eslint-disable-line
      path.scope.getBinding(targetNode.name).path.type === 'ImportSpecifier'; // eslint-disable-line

    if (types.isIdentifier(node[prop]) && checkScope(node[prop])) {
      node[prop] = this.importMethod(pluginState.specified[node[prop].name], file, pluginState); // eslint-disable-line
    } else if (types.isSequenceExpression(node[prop])) {
      node[prop].expressions.forEach((expressionNode, index) => {
        if (types.isIdentifier(expressionNode) && checkScope(expressionNode)) {
          node[prop].expressions[index] = this.importMethod(
            pluginState.specified[expressionNode.name],
            file,
            pluginState,
          ); // eslint-disable-line
        }
      });
    }
  }

VariableDeclarator中做处理。

在这里插入图片描述

这样子就能够解析到上述的问题了。

你可能感兴趣的:(关于babel-plugin-istanbul与babel-plugin-import冲突问题的官方解决方法)