CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-parcel--plugin

Plugin API for Parcel bundler - provides base classes for creating Parcel plugins including transformers, resolvers, bundlers, namers, runtimes, packagers, optimizers, compressors, reporters, and validators

67

1.06x
Overview
Eval results
Files

bundling.mddocs/

Bundle Generation

The Bundler plugin controls how assets are grouped into bundles and optimizes the bundle graph for performance, caching, and loading strategies. Bundlers determine the overall structure of the build output.

Capabilities

Bundler Class

Base class for creating bundle generation plugins.

/**
 * Base class for bundle generation plugins
 * @template T - Configuration type for this bundler
 */
export declare class Bundler<T> {
  constructor(opts: BundlerOpts<T>);
}

/**
 * Bundler plugin configuration interface
 * @template ConfigType - Type of configuration returned by loadConfig
 */
interface BundlerOpts<ConfigType> {
  /** Load configuration for this bundler */
  loadConfig?: (args: {
    config: Config;
    options: PluginOptions;
    logger: PluginLogger;
    tracer: PluginTracer;
  }) => Promise<ConfigType> | ConfigType;

  /** Create bundles from the asset graph (required) */
  bundle(args: {
    bundleGraph: MutableBundleGraph;
    config: ConfigType;
    options: PluginOptions;
    logger: PluginLogger;
    tracer: PluginTracer;
  }): Promise<void>;

  /** Optimize the bundle graph (required) */
  optimize(args: {
    bundleGraph: MutableBundleGraph;
    config: ConfigType;
    options: PluginOptions;
    logger: PluginLogger;
  }): Promise<void>;
}

Usage Example:

import { Bundler } from "@parcel/plugin";

export default new Bundler({
  // Load bundler configuration
  loadConfig({config}) {
    return {
      minBundleSize: config.minBundleSize || 1000,
      maxBundleSize: config.maxBundleSize || 100000,
      splitChunks: config.splitChunks !== false
    };
  },

  // Create bundles from assets (required)
  async bundle({bundleGraph, config, logger}) {
    // Get all assets
    const assets = bundleGraph.getAssets();
    
    // Create entry bundles
    for (const entry of bundleGraph.getEntryAssets()) {
      const bundle = bundleGraph.createBundle({
        entryAsset: entry,
        target: entry.env.context,
        type: getOutputType(entry.type)
      });
      
      bundleGraph.addAssetToBundle(entry, bundle);
    }
    
    // Group related assets into shared bundles
    if (config.splitChunks) {
      await this.createSharedBundles(bundleGraph, config);
    }
  },

  // Optimize bundle graph (required)
  async optimize({bundleGraph, config, logger}) {
    // Remove empty bundles
    for (const bundle of bundleGraph.getBundles()) {
      if (bundleGraph.getBundleAssets(bundle).length === 0) {
        bundleGraph.removeBundle(bundle);
      }
    }
    
    // Merge small bundles
    await this.mergeSmallBundles(bundleGraph, config);
    
    // Optimize bundle dependencies
    await this.optimizeBundleDependencies(bundleGraph);
  }
});

Bundle Graph Operations

/**
 * Mutable bundle graph for creating and modifying bundles
 */
interface MutableBundleGraph {
  /** Get all assets in the graph */
  getAssets(): Array<Asset>;
  
  /** Get entry assets */
  getEntryAssets(): Array<Asset>;
  
  /** Get all bundles */
  getBundles(): Array<Bundle>;
  
  /** Create a new bundle */
  createBundle(options: CreateBundleOptions): Bundle;
  
  /** Remove a bundle */
  removeBundle(bundle: Bundle): void;
  
  /** Add an asset to a bundle */
  addAssetToBundle(asset: Asset, bundle: Bundle): void;
  
  /** Remove an asset from a bundle */
  removeAssetFromBundle(asset: Asset, bundle: Bundle): void;
  
  /** Get assets in a specific bundle */
  getBundleAssets(bundle: Bundle): Array<Asset>;
  
  /** Create a dependency between bundles */
  createBundleDependency(from: Bundle, to: Bundle): void;
  
  /** Get bundles that depend on the given bundle */
  getBundleDependents(bundle: Bundle): Array<Bundle>;
  
  /** Get bundles that the given bundle depends on */
  getBundleDependencies(bundle: Bundle): Array<Bundle>;
}

/**
 * Options for creating a new bundle
 */
interface CreateBundleOptions {
  /** Entry asset for the bundle */
  entryAsset?: Asset;
  
  /** Bundle target */
  target: Target;
  
  /** Bundle output type */
  type: string;
  
  /** Whether this bundle needs a stable name */
  needsStableName?: boolean;
  
  /** Bundle behavior */
  bundleBehavior?: BundleBehavior;
  
  /** Bundle priority */
  priority?: BundlePriority;
  
  /** Environment for this bundle */
  env?: EnvironmentOptions;
}

/**
 * Bundle priority levels
 */
type BundlePriority = "sync" | "parallel" | "lazy";

Bundle Information

/**
 * A bundle in the bundle graph
 */
interface Bundle {
  /** Bundle ID */
  id: string;
  
  /** Bundle type */
  type: string;
  
  /** Target environment */
  target: Target;
  
  /** Entry asset if this is an entry bundle */
  entryAsset?: Asset;
  
  /** Main entry asset */
  mainEntryAsset?: Asset;
  
  /** Bundle file path */
  filePath?: FilePath;
  
  /** Bundle name */
  name?: string;
  
  /** Bundle display name */
  displayName?: string;
  
  /** Bundle statistics */
  stats: BundleStats;
  
  /** Environment for this bundle */
  env: Environment;
  
  /** Whether this bundle needs a stable name */
  needsStableName: boolean;
  
  /** Bundle behavior */
  bundleBehavior?: BundleBehavior;
  
  /** Bundle metadata */
  meta: Record<string, any>;
}

/**
 * Bundle statistics
 */
interface BundleStats {
  /** Bundle size in bytes */
  size: number;
  
  /** Time to create bundle */
  time: number;
}

Common Bundling Strategies

Entry Point Bundling:

// Create a bundle for each entry point
for (const entry of bundleGraph.getEntryAssets()) {
  const bundle = bundleGraph.createBundle({
    entryAsset: entry,
    target: entry.target,
    type: getOutputType(entry.type),
    needsStableName: true
  });
  
  bundleGraph.addAssetToBundle(entry, bundle);
}

Code Splitting:

// Create shared bundles for common dependencies
const sharedAssets = findSharedAssets(bundleGraph);
if (sharedAssets.length > 0) {
  const sharedBundle = bundleGraph.createBundle({
    target: primaryTarget,
    type: 'js',
    bundleBehavior: 'inline'
  });
  
  for (const asset of sharedAssets) {
    bundleGraph.addAssetToBundle(asset, sharedBundle);
  }
}

Size-based Optimization:

// Merge small bundles to reduce HTTP requests
const smallBundles = bundleGraph.getBundles().filter(bundle => 
  bundle.stats.size < config.minBundleSize
);

for (const smallBundle of smallBundles) {
  const targetBundle = findMergeTarget(smallBundle, bundleGraph);
  if (targetBundle) {
    mergeBundles(smallBundle, targetBundle, bundleGraph);
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-parcel--plugin

docs

bundling.md

compression.md

index.md

naming.md

optimization.md

packaging.md

reporting.md

resolution.md

runtime.md

transformation.md

validation.md

tile.json