babel-plugin-named-asset-import is a Babel plugin that transforms named imports from asset files (particularly SVG files) by rewriting import paths according to a configurable loader map. It enables webpack-style loader syntax in import statements, specifically designed for Create React App to handle assets like SVG components through @svgr/webpack.
npm install babel-plugin-named-asset-importconst namedAssetImportPlugin = require("babel-plugin-named-asset-import");Configure the plugin in your Babel configuration:
// babel.config.js
module.exports = {
plugins: [
[
"babel-plugin-named-asset-import",
{
loaderMap: {
svg: {
ReactComponent: "@svgr/webpack?-svgo![path]"
}
}
}
]
]
};With this configuration, the plugin transforms:
// Input
import { ReactComponent as Logo } from "./logo.svg";
// Output
import { ReactComponent as Logo } from "@svgr/webpack?-svgo!./logo.svg";babel-plugin-named-asset-import is built around the Babel plugin architecture and AST transformation principles:
loaderMap configuration objectThe plugin integrates into Babel's compilation pipeline, intercepting module import/export statements and conditionally rewriting them based on file extensions and named import patterns defined in the configuration.
The main export is a Babel plugin factory function that creates a Babel plugin with visitor methods.
/**
* Creates a Babel plugin that transforms named asset imports
* @param {Object} babel - Babel object containing types (t)
* @param {Object} babel.types - Babel types utilities (destructured from babel param)
* @returns {Object} Babel plugin object with visitor methods
*/
function namedAssetImportPlugin({ types: t }): BabelPlugin;
interface BabelPlugin {
visitor: {
ExportNamedDeclaration(path: NodePath, state: PluginState): void;
ImportDeclaration(path: NodePath, state: PluginState): void;
};
}The plugin accepts configuration through Babel's options system.
interface PluginOptions {
/** Maps file extensions to loader configurations */
loaderMap: LoaderMap;
}
interface LoaderMap {
/** File extension (without dot) */
[extension: string]: {
/** Named import to loader string mapping */
[namedImport: string]: string;
};
}Configuration Example:
{
loaderMap: {
svg: {
ReactComponent: "@svgr/webpack?-svgo![path]"
},
png: {
WebpImage: "webp-loader![path]"
}
}
}Transforms import declarations from asset files when they match the loader map configuration.
Supported Import Patterns:
Examples:
// Named import transformation
import { ReactComponent } from "./logo.svg";
// Becomes:
import { ReactComponent } from "@svgr/webpack?-svgo!./logo.svg";
// Mixed import splitting
import logo, { ReactComponent as Logo } from "./logo.svg";
// Becomes:
import logo from "./logo.svg";
import { ReactComponent as Logo } from "@svgr/webpack?-svgo!./logo.svg";
// Multiple named imports (from test case)
import logo, { logoUrl, ReactComponent as Logo } from "logo.svg";
// Becomes:
import logo from "logo.svg";
import { logoUrl } from "logo.svg";
import { ReactComponent as Logo } from "@svgr/webpack?-svgo!logo.svg";Transforms export declarations from asset files when they match the loader map configuration.
Supported Export Patterns:
Examples:
// Named export transformation
export { ReactComponent } from "./logo.svg";
// Becomes:
export { ReactComponent } from "@svgr/webpack?-svgo!./logo.svg";
// Mixed export splitting (from test case)
export { logoUrl, ReactComponent as Logo } from "logo.svg";
// Becomes:
export { logoUrl } from "logo.svg";
export { ReactComponent as Logo } from "@svgr/webpack?-svgo!logo.svg";The plugin only processes files with extensions defined in the loaderMap configuration:
path.extname() and normalized by removing the leading dotLoader strings support path placeholder substitution:
[path] placeholder is replaced with the original import path! syntaxThe plugin uses a WeakSet to track processed AST nodes:
!)The plugin transforms specific Babel AST node types:
interface NodePath {
node: ImportDeclaration | ExportNamedDeclaration;
replaceWithMultiple(nodes: Array<ImportDeclaration | ExportNamedDeclaration>): void;
}
interface PluginState {
opts: PluginOptions;
}
interface ImportDeclaration {
type: "ImportDeclaration";
source: StringLiteral;
specifiers: Array<ImportSpecifier | ImportDefaultSpecifier>;
}
interface ExportNamedDeclaration {
type: "ExportNamedDeclaration";
source: StringLiteral | null;
specifiers: Array<ExportSpecifier | ExportDefaultSpecifier>;
}
interface StringLiteral {
type: "StringLiteral";
value: string;
}