You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求识别module.exports的正确Babel AST检测类型

How to Detect module.exports with Babel AST

Great question! The issue here is that module.exports falls under CommonJS syntax, which uses completely different AST node types than ES module exports like export default or export const—that’s why your existing checks for ExportDefaultDeclaration and ExportNamedDeclaration aren’t picking it up. The DeclareModuleExports type you tried is actually for TypeScript declaration statements (like declare module.exports: MyType), so it won’t work for regular CommonJS assignment code.

Here’s how to properly detect different forms of module.exports and exports using Babel’s AST types:

1. Direct module.exports assignment (e.g. module.exports = myValue)

This maps to an AssignmentExpression node. To confirm it’s a module.exports assignment, you need to check that the left-hand side is a MemberExpression where:

  • The object is an Identifier named module
  • The property is an Identifier named exports

Example AST structure for module.exports = foo:

{
  type: "AssignmentExpression",
  left: {
    type: "MemberExpression",
    object: { type: "Identifier", name: "module" },
    property: { type: "Identifier", name: "exports" }
  },
  right: { type: "Identifier", name: "foo" } // The value being exported
}

2. Named exports via module.exports (e.g. module.exports.myFunc = myFunc)

This is also an AssignmentExpression, but the left-hand side is a nested MemberExpression: the outer MemberExpression has an object of module.exports (another MemberExpression) and a property matching the export name (e.g. myFunc).

3. Direct exports assignments (e.g. exports.myVar = 123 or exports = { ... })

Similar to module.exports, this uses AssignmentExpression:

  • For exports.myVar = 123: The left-hand side is a MemberExpression where the object is an Identifier named exports
  • For exports = { ... }: The left-hand side is simply an Identifier named exports (note: this pattern is less common because it overrides the exports reference, breaking links to module.exports)

Example Detection Code

Here’s a practical snippet using Babel’s traverse API to detect all export types (ES and CommonJS):

const babel = require('@babel/core');
const t = require('@babel/types');

const sampleCode = `
// CommonJS exports
module.exports = { hello: 'world' };
module.exports.greet = () => 'hi';
exports.foo = 'bar';

// ES module exports
export default 'es-default';
export const esNamed = 'es-named';
`;

babel.transform(sampleCode, {}, (err, result) => {
  if (err) throw err;
  
  babel.traverse(result.ast, {
    // Detect ES module default exports
    ExportDefaultDeclaration(path) {
      console.log('ES Default Export:', path.node.declaration);
    },
    // Detect ES module named exports
    ExportNamedDeclaration(path) {
      console.log('ES Named Export:', path.node.declaration);
    },
    // Detect CommonJS exports
    AssignmentExpression(path) {
      const leftNode = path.node.left;
      
      // Check for module.exports = ...
      if (t.isMemberExpression(leftNode) &&
          t.isIdentifier(leftNode.object, { name: 'module' }) &&
          t.isIdentifier(leftNode.property, { name: 'exports' })) {
        console.log('CommonJS Default Export:', path.node.right);
      }
      // Check for module.exports.NAME = ...
      else if (t.isMemberExpression(leftNode) &&
               t.isMemberExpression(leftNode.object) &&
               t.isIdentifier(leftNode.object.object, { name: 'module' }) &&
               t.isIdentifier(leftNode.object.property, { name: 'exports' })) {
        console.log(`CommonJS Named Export (module.exports.${leftNode.property.name}):`, path.node.right);
      }
      // Check for exports.NAME = ...
      else if (t.isMemberExpression(leftNode) &&
               t.isIdentifier(leftNode.object, { name: 'exports' })) {
        console.log(`CommonJS Named Export (exports.${leftNode.property.name}):`, path.node.right);
      }
      // Check for exports = ...
      else if (t.isIdentifier(leftNode, { name: 'exports' })) {
        console.log('CommonJS Exports Assignment:', path.node.right);
      }
    }
  });
});

Key Notes

  • Always use Babel’s @babel/types utility functions (like t.isMemberExpression) instead of checking type directly—they validate additional properties and make your code more robust.
  • Keep in mind that module.exports can be assigned to any expression (functions, classes, objects, literals), so you’ll need to handle the right side of the AssignmentExpression based on your use case.
  • If you’re working with mixed ES and CommonJS code, this approach will cover all export patterns you’re likely to encounter.

内容的提问来源于stack exchange,提问作者ChoclateLove

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:04:00