or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-loadable--babel-plugin

Babel plugin for loadable components that enables server-side rendering by transforming dynamic imports

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

To install, run

npx @tessl/cli install tessl/npm-loadable--babel-plugin@5.16.0

index.mddocs/

@loadable/babel-plugin

@loadable/babel-plugin is a Babel plugin that transforms loadable component function calls to enable server-side rendering (SSR) support in React applications. The plugin analyzes dynamic import() statements within loadable() calls and injects additional properties required for SSR, including chunk names, synchronous loading methods, and module resolution functions.

Package Information

  • Package Name: @loadable/babel-plugin
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install --save-dev @loadable/babel-plugin

Core Imports

// Babel plugin configuration (in babel.config.js or .babelrc)
module.exports = {
  plugins: ['@loadable/babel-plugin']
};

For custom import signatures:

module.exports = {
  plugins: [
    ['@loadable/babel-plugin', {
      signatures: [
        { name: 'default', from: '@loadable/component' },
        { name: 'loadable', from: 'my-custom-loadable' }
      ]
    }]
  ]
};

Basic Usage

The plugin transforms loadable component calls automatically during build time:

// Input code
import loadable from '@loadable/component';

const AsyncComponent = loadable(() => import('./MyComponent'));

// Plugin transforms this to include SSR properties
const AsyncComponent = loadable({
  chunkName(props) { return 'MyComponent'; },
  isReady(props) { /* ... */ },
  importAsync: () => import('./MyComponent'),
  requireAsync(props) { /* ... */ },
  requireSync(props) { /* ... */ },
  resolve(props) { /* ... */ },
  resolved: {}
});

Architecture

The plugin operates during Babel's AST transformation phase and consists of:

  • Main Plugin: Entry point that configures visitor patterns and transformation logic
  • Property Generators: Modules that create the injected SSR-support methods
  • Signature Detection: Logic to identify loadable function calls based on import patterns
  • AST Transformation: Code that replaces loadable function calls with enhanced objects

Capabilities

Plugin Configuration

Configure which import patterns the plugin should transform.

/**
 * Main Babel plugin export - configured in Babel configuration
 * @param api - Babel API object containing types and other utilities
 * @param options - Plugin configuration options
 * @returns Babel plugin object with visitor methods
 */
function loadablePlugin(api: object, options: LoadablePluginOptions): BabelPlugin;

interface LoadablePluginOptions {
  /** Array of import signature patterns to transform */
  signatures?: ImportSignature[];
}

interface ImportSignature {
  /** Import specifier name ('default' for default imports, or named import) */
  name: string;
  /** Package name to match for transformation */
  from: string;
}

interface BabelPlugin {
  /** Inherits syntax-dynamic-import plugin for import() support */
  inherits: object;
  /** AST visitor configuration */
  visitor: {
    Program: {
      enter(programPath: object): void;
    };
  };
}

Default Configuration:

// Default signatures - transforms @loadable/component imports
const DEFAULT_SIGNATURE = [{ name: 'default', from: '@loadable/component' }];

Transformation Targets

The plugin identifies and transforms these patterns:

// 1. loadable() function calls (based on import signatures)
loadable(() => import('./Component'))

// 2. lazy() function calls (when imported from @loadable/component)  
import { lazy } from '@loadable/component';
lazy(() => import('./Component'))

// 3. loadable.lib() method calls
loadable.lib(() => import('./library'))

// 4. Functions with #__LOADABLE__ comment - supports multiple function types:
/* #__LOADABLE__ */ () => import('./Component')                    // Arrow function
/* #__LOADABLE__ */ function() { return import('./Component') }    // Function expression
const obj = { /* #__LOADABLE__ */ load() { return import('./Component') } }  // Object method

Generated Runtime Methods

When the plugin transforms a loadable call, it injects these SSR-support methods:

interface LoadableComponentObject {
  /** 
   * Generates webpack chunk name for the dynamic import
   * Handles webpack comments and template literals
   */
  chunkName(props: any): string;
  
  /**
   * Checks if the module is ready (loaded) for synchronous rendering
   * Returns true if module is available in webpack module cache
   */
  isReady(props: any): boolean;
  
  /**
   * Original async import function - preserves the dynamic import()
   */
  importAsync: () => Promise<any>;
  
  /**
   * Async module loading with resolution tracking
   * Updates resolved state when promise completes
   */
  requireAsync(props: any): Promise<any>;
  
  /**
   * Synchronous module loading for SSR
   * Uses __webpack_require__ or Node.js require based on environment
   */
  requireSync(props: any): any;
  
  /**
   * Resolves module ID for the dynamic import
   * Uses require.resolveWeak or require.resolve based on availability
   */
  resolve(props: any): string;
  
  /**
   * Object tracking resolved module states
   * Maps module IDs to boolean resolution status
   */
  resolved: Record<string, boolean>;
}

Webpack Integration

The plugin handles webpack-specific features for chunk naming and module resolution:

// Webpack comment processing for chunk names
import(
  /* webpackChunkName: "my-chunk" */ 
  './Component'
);

// Template literal support for dynamic chunk names
const componentName = 'MyComponent';
import(`./components/${componentName}`);

Chunk Name Generation Rules:

  • Static imports: Uses file path converted to chunk-safe format
  • Template literals: Preserves dynamic expressions with sanitization
  • Webpack comments: Respects existing webpackChunkName comments
  • Path normalization: Removes file extensions and converts special characters to hyphens

Error Handling

The plugin validates usage patterns and throws errors for unsupported configurations:

// Error: Multiple import calls not supported
loadable(() => {
  import('./ComponentA');
  import('./ComponentB');  // Throws error
});

Common Error Messages:

  • "loadable: multiple import calls inside loadable() function are not supported"
  • Webpack comment parsing errors with compilation context
  • Template literal processing errors for invalid expressions

Environment Detection

The plugin generates environment-aware code that works in different contexts:

// Browser environment (webpack)
if (typeof __webpack_require__ !== 'undefined') {
  return __webpack_require__(id);
}

// Node.js environment  
return eval('module.require')(id);

// Webpack modules check
if (typeof __webpack_modules__ !== 'undefined') {
  return !!(__webpack_modules__[key]);
}

Types

// Plugin accepts these configuration options
interface LoadablePluginOptions {
  signatures?: ImportSignature[];
}

interface ImportSignature {
  name: string;        // 'default' | string (named import)
  from: string;        // Package name like '@loadable/component'
}

// Internal transformation context
interface TransformContext {
  path: object;        // Babel AST path to the loadable call
  callPath: object;    // Babel AST path to the import() call
  funcPath: object;    // Babel AST path to the function expression
}

// Generated object structure
interface GeneratedLoadableObject {
  chunkName(props: any): string;
  isReady(props: any): boolean;
  importAsync: () => Promise<any>;
  requireAsync(props: any): Promise<any>;
  requireSync(props: any): any;
  resolve(props: any): string | number;
  resolved: Record<string, boolean>;
}