or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-babel-plugin-component

Babel plugin that transforms named component imports into specific module paths for tree-shaking optimization

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/babel-plugin-component@1.1.x

To install, run

npx @tessl/cli install tessl/npm-babel-plugin-component@1.1.0

index.mddocs/

Babel Plugin Component

Babel Plugin Component is a Babel transformation plugin that enables modular component imports by transforming named imports into specific module paths. It automatically handles both JavaScript module imports and CSS style imports, enabling tree-shaking optimization and reducing bundle sizes for component libraries like Element UI, Ant Design, and custom libraries.

Package Information

  • Package Name: babel-plugin-component
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install babel-plugin-component -D

Core Imports

// As Babel plugin in .babelrc
{
  "plugins": [["component", options]]
}
// Programmatic usage
const plugin = require('babel-plugin-component');

Basic Usage

// .babelrc configuration
{
  "plugins": [["component", {
    "libraryName": "element-ui",
    "style": true
  }]]
}
// Input code
import { Button, message } from 'element-ui';

// Output after transformation (with Babel helpers)
require("element-ui/lib/button/style.css");
var _Button = _interopRequireDefault(require("element-ui/lib/button")).default;
require("element-ui/lib/message/style.css");
var _message = _interopRequireDefault(require("element-ui/lib/message")).default;

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

Architecture

Babel Plugin Component operates through several key mechanisms:

  • AST Transformation: Uses Babel's visitor pattern to transform import declarations and component references
  • Import Resolution: Maps component names to specific module paths using configurable directory structures
  • Style Handling: Automatically injects CSS imports based on component usage and configuration
  • Multi-Library Support: Handles multiple component libraries in a single project through configuration arrays
  • Cache Management: Maintains internal caches to optimize repeated transformations and handle complex import scenarios

Capabilities

Plugin Factory Function

Core function that creates the Babel plugin with specified default library name.

/**
 * Creates a Babel plugin function with specified default library name
 * @param {string} defaultLibraryName - Default library name to use when not specified in options
 * @returns {Function} Babel plugin function
 */
function core(defaultLibraryName);

Main Plugin Export

Default export that provides a pre-configured plugin for Element UI.

/**
 * Default plugin export configured for 'element-ui' library
 * @returns {Function} Babel plugin configured for Element UI
 */
module.exports; // Returns core('element-ui')

Plugin Configuration Options

Complete configuration interface for customizing plugin behavior.

interface PluginOptions {
  /** Name of the library to transform imports for */
  libraryName?: string;
  /** Library directory path (default: 'lib') */
  libDir?: string;
  /** Style import handling - true for default style.css, string for custom path, false for none */
  style?: boolean | string;
  /** Root directory for components */
  root?: string;
  /** Convert camelCase to dash-case for component names (default: true) */
  camel2Dash?: boolean;
  /** File extension for style files (default: '.css') */
  ext?: string;
  /** Style library name - regular name or prefixed with ~ for independent theme */
  styleLibraryName?: string;
  /** Advanced style library configuration */
  styleLibrary?: StyleLibraryConfig;
}

interface StyleLibraryConfig {
  /** Style library name (same as styleLibraryName) */
  name: string;
  /** Include base.css file (default: true) */
  base?: boolean;
  /** Template for style file paths, supports [module] placeholder */
  path?: string;
  /** Fallback to component's own style if theme style not found */
  mixin?: boolean;
  /** Root directory for styles */
  root?: string;
}

Multiple Library Configuration

Configuration for handling multiple component libraries.

/**
 * Multiple library configuration array
 * Each array element: [plugin, options, libraryIdentifier]
 */
type MultiLibraryConfig = Array<[Function, PluginOptions, string]>;

Usage Example:

{
  "plugins": [
    ["component", {
      "libraryName": "antd",
      "style": true
    }, "antd"],
    ["component", {
      "libraryName": "element-ui",
      "style": true
    }, "element-ui"]
  ]
}

Import Transformation Patterns

The plugin handles various import and usage patterns:

Named Imports:

// Input
import { Button, Input } from 'antd';

// Output (with style: true, simplified for clarity)
require("antd/lib/button/style.css");
var _Button = _interopRequireDefault(require("antd/lib/button")).default;
require("antd/lib/input/style.css");
var _Input = _interopRequireDefault(require("antd/lib/input")).default;

Function Calls:

// Input
import { message } from 'element-ui';
message('Hello');

// Output
require("element-ui/lib/message/style.css");
var _message = require("element-ui/lib/message").default;
_message('Hello');

Member Expressions:

// Input
import Components from 'antd';
Components.Button;

// Output
var _Components = require("antd/lib").default;
_Components.Button;

Array Usage:

// Input
import { Button, Input } from 'antd';
const components = [Button, Input];

// Output
var _Button = require("antd/lib/button").default;
var _Input = require("antd/lib/input").default;
const components = [_Button, _Input];

Style Import Strategies

Different approaches for handling CSS and style imports:

Basic Style Import:

// Configuration
{ "style": true }

// Transforms to
require("library/lib/component/style.css");

Custom Style Path:

// Configuration
{ "style": "custom.css" }

// Transforms to
require("library/lib/component/custom.css");

Style Library with Theme:

// Configuration
{
  "styleLibraryName": "theme-default"
}

// Transforms to
require("library/lib/theme-default/component.css");

Independent Theme Package:

// Configuration
{
  "styleLibraryName": "~my-theme"
}

// Transforms to (resolved to current working directory)
require("/path/to/cwd/my-theme/component.css");

Advanced Style Library:

// Configuration
{
  "styleLibrary": {
    "name": "theme-custom",
    "base": true,
    "path": "[module]/index.css",
    "mixin": true
  }
}

// Base style import
require("library/lib/theme-custom/base.css");

// Component style import
require("library/lib/theme-custom/button/index.css");

Component Directory Structure Support

The plugin supports various component library directory structures:

Standard Structure:

- lib/
  - component-name/
    - index.js
    - style.css

Theme Structure:

- lib/
  - theme-default/
    - base.css
    - index.css
    - component-name.css
  - component-name/
    - index.js

Custom Path Structure:

- lib/
  - theme-custom/
    - component-name/
      - index.css
  - component-name/
    - index.js

Name Transformation

Component name transformation options:

/**
 * Converts component name based on camel2Dash setting
 * @param {string} str - Component name to transform
 * @param {boolean} camel2Dash - Whether to convert camelCase to dash-case
 * @returns {string} Transformed name
 */
function parseName(str, camel2Dash);

Examples:

// camel2Dash: true (default)
'DatePicker' → 'date-picker'
'Button' → 'button'

// camel2Dash: false
'DatePicker' → 'DatePicker'
'Button' → 'Button'

Error Handling

The plugin includes error handling for common configuration issues:

Import Conflict Error:

// Throws error when mixing import-all and on-demand imports
throw Error('[babel-plugin-component] If you are using both on-demand and importing all, make sure to invoke the importing all first.');

File Existence Checking:

/**
 * Checks if style file exists when using mixin option
 * Falls back to component's own style if theme style not found
 */
const isExist = require('fs').existsSync;

Babel Visitor Methods

The plugin implements the following Babel visitor methods to transform different AST node types:

Program:

  • Description: Initializes plugin state for each file
  • Purpose: Resets internal tracking objects for component imports

ImportDeclaration:

  • Description: Transforms import statements for the target library
  • Handles: Named imports, default imports, namespace imports
  • Purpose: Identifies and tracks component imports to be transformed

CallExpression:

  • Description: Transforms function calls using imported components
  • Purpose: Replaces component function calls with transformed imports

MemberExpression:

  • Description: Transforms member access on imported components
  • Purpose: Handles object property access on imported components

AssignmentExpression:

  • Description: Transforms assignments involving imported components
  • Purpose: Handles variable assignments with component references

ArrayExpression:

  • Description: Transforms array elements that reference imported components
  • Purpose: Processes component references within array literals

Property:

  • Description: Transforms object property values
  • Purpose: Handles component references in object property assignments

VariableDeclarator:

  • Description: Transforms variable declarations
  • Purpose: Processes component references in variable initializations

LogicalExpression:

  • Description: Transforms logical expressions (&&, ||)
  • Purpose: Handles component references in logical operations

ConditionalExpression:

  • Description: Transforms ternary conditional expressions
  • Purpose: Processes component references in conditional expressions

IfStatement:

  • Description: Transforms if statement conditions
  • Purpose: Handles component references in if conditions and tests

Dependencies

The plugin relies on the following external dependencies:

/**
 * Babel helper for adding module imports
 */
const { addSideEffect, addDefault } = require('@babel/helper-module-imports');

/**
 * Node.js built-in modules
 */
const resolve = require('path').resolve;
const isExist = require('fs').existsSync;

Types

/**
 * Babel plugin function signature
 */
type BabelPlugin = ({ types }: { types: any }) => {
  visitor: {
    [key: string]: (path: any, state: { opts: PluginOptions }) => void;
  };
};

/**
 * Internal cache structures
 */
interface Cache {
  [libraryName: string]: number; // 1 = import-all, 2 = on-demand
}

interface CachePath {
  [libraryName: string]: string; // Resolved style library paths
}

interface ImportAll {
  [libraryPath: string]: boolean; // Tracks import-all usage
}