简体   繁体   中英

How to turn basic imports into aliased imports?

I'm writing a Babel plugin that should wrap each import into a function call that performs some transformation. The idea is to turn this code:

import { member } from "module-name";
import { member as alias } from "module-name";

into this:

import { member as _member } from "module-name";
const member = someTransform(_member);
import { member as _alias } from "module-name";
const alias = someTransform(_alias);

So for aliased imports (see AST documentation ), I want to change the name of the alias; basic imports should be converted to aliased imports so that I can change their identifier. Adding the assignments is trivial, so I'll ignore it for the remainder of this question.

According to the AST documentation, basic and aliased imports are modelled identically. The only difference is that for a basic import, the imported and local fields contain identical IDs, while they differ for an aliased import.

So I thought I just needed to change the local ID for all ImportSpecifier s. This should automatically turn basic imports into aliased ones; for aliased imports, it should change the alias.

Here's my code ( try it out in the AST explorer ).

function transformImportDeclaration(path) {
  const importSpecifierPaths = path.get('specifiers');
  for (const importSpecifierPath of importSpecifierPaths) {
    const node = importSpecifierPath.node;
    const id = node.local;
    node.local = path.scope.generateUidIdentifier(id.name);
  }
}

export default function (babel) {
  const t = babel.types;

  return {
    visitor: {
      Program(programPath) {
        const declarations = programPath.get('body').filter(path => t.isImportDeclaration(path));
        declarations.forEach(transformImportDeclaration);
      },
    },
  };
}

The problem is that the resulting code is this:

import { _member } from "module-name";
import { member as _alias } from "module-name";

So only the second line with the aliased import is transformed correctly. But the first line with the basic import isn't converted to an aliased import. Instead, it stays a basic import, which now points to the wrong export. I don't understand why this is, because the imported ID of the AST still contains the original ID.

This appears to be a bug in Babel. I created a bug report there.

As a workaround, a commenter suggested replacing the import specifier with a modified copy. He also added a working demo on AST explorer .

The relevant code is this:

importSpecifierPath.replaceWith(
  t.importSpecifier(
    path.scope.generateUidIdentifier(node.imported.name),
    t.clone(node.imported)
  )
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM