or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdloader-integration.mdplugin-configuration.mdthread-pool.md
tile.json

loader-integration.mddocs/

Loader Integration

HappyPack loader integration with webpack's module resolution system, enabling seamless delegation of file processing to parallel worker threads.

Capabilities

HappyPack Loader

The HappyPack webpack loader that intercepts file processing and delegates it to configured plugin instances.

/**
 * HappyPack webpack loader function
 * Processes source files by delegating to HappyPack plugin instances
 * @param sourceCode - Original source file content as string
 * @param sourceMap - Source map data from previous loaders (optional)
 * @returns Processed source code and source map via async callback
 * @note Uses webpack's async callback mechanism - never returns directly
 */
function HappyLoader(sourceCode, sourceMap);

The loader is accessed through the package entry point:

// Direct require
require('happypack/loader')

// In webpack configuration
{
  test: /\.js$/,
  use: 'happypack/loader'
}

Loader Query Parameters

Query parameters for configuring how the loader communicates with plugin instances.

/**
 * Loader query parameters for plugin communication
 */
interface HappyLoaderQuery {
  /** Plugin instance ID to use (default: '1') */
  id?: string;
  /** Compiler ID for multi-compiler setups (default: 'default') */
  compilerId?: string;
}

Usage Examples:

// Basic usage - uses default plugin (id: '1')
{
  test: /\.js$/,
  use: 'happypack/loader'
}

// Specific plugin instance
{
  test: /\.js$/,
  use: 'happypack/loader?id=babel'
}

{
  test: /\.css$/,
  use: 'happypack/loader?id=styles'
}

// Multi-compiler setup
{
  test: /\.js$/,
  use: 'happypack/loader?id=babel&compilerId=client'
}

// Object notation
{
  test: /\.js$/,
  use: {
    loader: 'happypack/loader',
    options: {
      id: 'babel',
      compilerId: 'main'
    }
  }
}

Webpack Configuration Integration

Complete webpack configuration patterns for integrating HappyPack loader with various file types and loaders.

/**
 * Webpack module rules configuration with HappyPack
 */
interface WebpackHappyConfig {
  module: {
    rules: WebpackRule[];
  };
  plugins: HappyPlugin[];
}

interface WebpackRule {
  test: RegExp;
  use: string | LoaderConfig;
  include?: string[];
  exclude?: string[];
}

Configuration Examples:

const HappyPack = require('happypack');

module.exports = {
  module: {
    rules: [
      // JavaScript files
      {
        test: /\.js$/,
        use: 'happypack/loader?id=js',
        include: [
          path.resolve(__dirname, 'src')
        ],
        exclude: [
          path.resolve(__dirname, 'node_modules')
        ]
      },
      
      // TypeScript files
      {
        test: /\.tsx?$/,
        use: 'happypack/loader?id=typescript',
        include: [
          path.resolve(__dirname, 'src')
        ]
      },
      
      // Style files
      {
        test: /\.less$/,
        use: 'happypack/loader?id=styles'
      },
      
      // SASS files with different plugin
      {
        test: /\.scss$/,
        use: 'happypack/loader?id=sass'
      }
    ]
  },
  
  plugins: [
    // JavaScript processing
    new HappyPack({
      id: 'js',
      loaders: ['babel-loader?presets[]=es2015']
    }),
    
    // TypeScript processing
    new HappyPack({
      id: 'typescript',
      loaders: [
        'ts-loader'
      ]
    }),
    
    // Style processing
    new HappyPack({
      id: 'styles',
      loaders: [
        'style-loader',
        'css-loader',
        'less-loader'
      ]
    }),
    
    // SASS processing
    new HappyPack({
      id: 'sass',
      loaders: [
        'style-loader',
        'css-loader',
        'sass-loader'
      ]
    })
  ]
};

Loader Context Integration

Understanding how HappyPack loader integrates with webpack's loader context and maintains compatibility.

/**
 * Webpack loader context properties used by HappyPack
 */
interface WebpackLoaderContext {
  /** Current resource being processed */
  resource: string;
  /** Resource path without query */
  resourcePath: string;
  /** Resource query string */
  resourceQuery: string;
  /** Loader context directory */
  context: string;
  /** Webpack target (web, node, etc.) */
  target: string;
  /** Whether to minimize output */
  minimize: boolean;
  /** Whether source maps are enabled */
  useSourceMap: boolean;
  /** Module dependencies */
  _dependencies: any[];
  /** Context dependencies */
  _contextDependencies: any[];
}

Async Loader Behavior

HappyPack loader operates as an asynchronous webpack loader, requiring proper callback handling.

/**
 * Async loader callback pattern
 */
interface AsyncLoaderCallback {
  /**
   * Signal completion of async loader processing
   * @param error - Error if processing failed
   * @param content - Processed source content
   * @param sourceMap - Processed source map
   */
  (error: Error | null, content?: string, sourceMap?: object): void;
}

Internal Processing Flow:

// Internal HappyLoader implementation pattern
function HappyLoader(sourceCode, sourceMap) {
  // Get async callback from webpack
  const callback = this.async();
  
  // Mark as cacheable for webpack
  this.cacheable();
  
  // Parse loader options
  const query = loaderUtils.getOptions(this) || {};
  const loaderId = query.id || '1';
  const compilerId = query.compilerId || 'default';
  
  // Find corresponding HappyPack plugin
  const happyPlugin = findHappyPlugin(this, loaderId);
  
  // Delegate to plugin for parallel processing
  happyPlugin.compile(this, {
    sourceCode: sourceCode,
    sourceMap: sourceMap,
    resource: this.resource,
    // ... other context properties
  }, callback);
}

Multi-Instance Configuration

Advanced patterns for using multiple HappyPack instances with different loader configurations.

/**
 * Multi-instance HappyPack configuration pattern
 */
interface MultiInstanceConfig {
  /** Multiple plugin instances with unique IDs */
  plugins: HappyPluginInstance[];
  /** Corresponding webpack rules for each instance */
  rules: WebpackRuleInstance[];
}

interface HappyPluginInstance {
  id: string;
  loaders: string[];
  threads?: number;
}

interface WebpackRuleInstance {
  test: RegExp;
  loaderId: string;
}

Multi-Instance Example:

const HappyPack = require('happypack');

// Create shared thread pool for efficiency
const sharedPool = HappyPack.ThreadPool({ size: 6 });

module.exports = {
  module: {
    rules: [
      // React JSX files
      {
        test: /\.jsx?$/,
        use: 'happypack/loader?id=jsx',
        include: path.resolve('src'),
        exclude: /node_modules/
      },
      
      // Vue single file components
      {
        test: /\.vue$/,
        use: 'happypack/loader?id=vue'
      },
      
      // CSS modules
      {
        test: /\.module\.css$/,
        use: 'happypack/loader?id=css-modules'
      },
      
      // Regular CSS
      {
        test: /\.css$/,
        exclude: /\.module\.css$/,
        use: 'happypack/loader?id=css'
      }
    ]
  },
  
  plugins: [
    // JSX processing with React transform
    new HappyPack({
      id: 'jsx',
      threadPool: sharedPool,
      loaders: [
        {
          loader: 'babel-loader',
          options: {
            presets: ['es2015', 'react']
          }
        }
      ]
    }),
    
    // Vue component processing
    new HappyPack({
      id: 'vue',
      threadPool: sharedPool,
      loaders: ['vue-loader']
    }),
    
    // CSS modules with specific configuration
    new HappyPack({
      id: 'css-modules',
      threadPool: sharedPool,
      loaders: [
        'style-loader',
        {
          loader: 'css-loader',
          options: {
            modules: true,
            localIdentName: '[name]_[local]_[hash:base64:5]'
          }
        }
      ]
    }),
    
    // Regular CSS processing
    new HappyPack({
      id: 'css',
      threadPool: sharedPool,
      loaders: ['style-loader', 'css-loader']
    })
  ]
};

Error Handling and Debugging

Error handling patterns and debugging techniques for loader integration issues.

/**
 * Common loader integration errors and debugging
 */
interface LoaderErrorTypes {
  /** Plugin not found for specified ID */
  PluginNotFound: 'plugin for the loader could not be found';
  /** Async callback not available */
  AsyncRequired: 'HappyPack only works when asynchronous loaders are allowed';
  /** Plugin list not accessible */
  PluginListUnavailable: 'unable to locate the plugin list';
  /** Configuration mismatch */
  ConfigMismatch: 'loader ID does not match any plugin ID';
}

Debugging Examples:

// Enable debug logging
new HappyPack({
  id: 'debug-example',
  debug: true,
  verbose: true,
  loaders: ['babel-loader']
});

// Verify plugin-loader ID matching
const pluginId = 'babel-processing';

// Plugin configuration
new HappyPack({
  id: pluginId, // Must match loader ID
  loaders: ['babel-loader']
});

// Loader configuration
{
  test: /\.js$/,
  use: `happypack/loader?id=${pluginId}` // Must match plugin ID
}

// Check for common misconfigurations
const config = {
  plugins: [
    new HappyPack({
      id: 'js', // Plugin ID
      loaders: ['babel-loader']
    })
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'happypack/loader?id=javascript' // ❌ ID mismatch!
      }
    ]
  }
};

// Correct configuration
const correctConfig = {
  plugins: [
    new HappyPack({
      id: 'js',
      loaders: ['babel-loader']
    })
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'happypack/loader?id=js' // ✅ IDs match
      }
    ]
  }
};