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

resolution.mddocs/

Module Resolution

The Resolver plugin enables custom module resolution logic for import and require statements. Resolvers determine how module specifiers are resolved to actual file paths and provide the foundation for custom module systems.

Capabilities

Resolver Class

Base class for creating module resolution plugins.

/**
 * Base class for module resolution plugins
 * @template T - Configuration type for this resolver
 */
export declare class Resolver<T> {
  constructor(opts: ResolverOpts<T>);
}

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

  /** Resolve a module specifier to a file path (required) */
  resolve(args: {
    dependency: Dependency;
    options: PluginOptions;
    logger: PluginLogger;
    tracer: PluginTracer;
    specifier: FilePath;
    pipeline?: string;
    config: ConfigType;
  }): Promise<ResolveResult | null>;
}

Usage Example:

import { Resolver } from "@parcel/plugin";
import path from "path";

export default new Resolver({
  // Load resolver configuration
  loadConfig({config}) {
    return config.getConfigFrom(/* config path */);
  },

  // Main resolution logic (required)
  async resolve({dependency, specifier, options, logger}) {
    // Handle different types of specifiers
    if (specifier.startsWith('~')) {
      // Resolve from node_modules
      const modulePath = specifier.slice(1);
      const resolved = path.resolve(options.projectRoot, 'node_modules', modulePath);
      
      return {
        filePath: resolved,
        sideEffects: false
      };
    }
    
    if (specifier.startsWith('./') || specifier.startsWith('../')) {
      // Relative path resolution
      const fromDir = path.dirname(dependency.sourcePath);
      const resolved = path.resolve(fromDir, specifier);
      
      return {
        filePath: resolved,
        sideEffects: true
      };
    }
    
    // Return null to let other resolvers handle this
    return null;
  }
});

Resolution Results

/**
 * Result from a module resolution operation
 */
interface ResolveResult {
  /** Resolved file path */
  filePath: FilePath;
  
  /** Whether this module has side effects */
  sideEffects?: boolean;
  
  /** Module resolution priority */
  priority?: ResolvePriority;
  
  /** Whether this is an excluded dependency */
  isExcluded?: boolean;
  
  /** Code to inline instead of resolving */
  code?: string;
  
  /** Query parameters for the resolved module */
  query?: URLSearchParams;
  
  /** Pipeline to use for processing this module */
  pipeline?: string;
  
  /** Environment for this module */
  env?: EnvironmentOptions;
  
  /** Module metadata */
  meta?: Record<string, any>;
  
  /** Symbol exports from this module */
  symbols?: Map<Symbol, SymbolResolution>;
}

/**
 * Resolution priority levels
 */
type ResolvePriority = "sync" | "parallel" | "lazy";

Dependency Information

/**
 * Dependency being resolved
 */
interface Dependency {
  /** Module specifier to resolve */
  specifier: string;
  
  /** Source file path containing this dependency */
  sourcePath: FilePath;
  
  /** Source location of the dependency */
  loc?: SourceLocation;
  
  /** Import type */
  specifierType: SpecifierType;
  
  /** Whether this is an optional dependency */
  isOptional?: boolean;
  
  /** Whether this dependency is async */
  isAsync?: boolean;
  
  /** Dependency priority */
  priority?: DependencyPriority;
  
  /** Bundle behavior for this dependency */
  bundleBehavior?: BundleBehavior;
  
  /** Environment for this dependency */
  env?: EnvironmentOptions;
  
  /** Dependency metadata */
  meta?: Record<string, any>;
  
  /** Pipeline to use for this dependency */
  pipeline?: string;
  
  /** Symbols imported from this dependency */
  symbols?: Map<Symbol, SymbolResolution>;
}

/**
 * Types of module specifiers
 */
type SpecifierType = 
  | "commonjs" 
  | "esm" 
  | "url" 
  | "relative" 
  | "absolute";

/**
 * Dependency loading priority
 */
type DependencyPriority = "sync" | "parallel" | "lazy";

/**
 * Bundle inclusion behavior
 */
type BundleBehavior = 
  | "inline" 
  | "isolated";

Source Location Information

/**
 * Location information in source code
 */
interface SourceLocation {
  /** Source file path */
  filePath: FilePath;
  
  /** Start position */
  start: Position;
  
  /** End position */
  end: Position;
}

/**
 * Position in source code
 */
interface Position {
  /** Line number (1-based) */
  line: number;
  
  /** Column number (0-based) */
  column: number;
}

Common Resolution Patterns

Package Resolution:

// Resolve from node_modules
if (!specifier.startsWith('.')) {
  const packagePath = await options.packageManager.resolve(specifier, fromPath);
  return { filePath: packagePath };
}

Alias Resolution:

// Handle path aliases
const aliases = config.aliases || {};
for (const [alias, target] of Object.entries(aliases)) {
  if (specifier.startsWith(alias)) {
    const resolved = specifier.replace(alias, target);
    return { filePath: path.resolve(options.projectRoot, resolved) };
  }
}

Extension Resolution:

// Try different file extensions
const extensions = ['.js', '.ts', '.jsx', '.tsx'];
for (const ext of extensions) {
  const withExt = specifier + ext;
  if (await options.inputFS.exists(withExt)) {
    return { filePath: withExt };
  }
}

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