or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-rollup--plugin-virtual

A Rollup plugin which loads virtual modules from memory instead of the filesystem

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@rollup/plugin-virtual@2.1.x

To install, run

npx @tessl/cli install tessl/npm-rollup--plugin-virtual@2.1.0

index.mddocs/

@rollup/plugin-virtual

@rollup/plugin-virtual is a Rollup plugin that loads virtual modules from memory instead of the filesystem. It enables developers to define module content programmatically by mapping module IDs to their source code strings, which is particularly useful for dynamically generated code, configuration modules, or modules that don't exist as physical files.

Package Information

  • Package Name: @rollup/plugin-virtual
  • Package Type: npm
  • Language: JavaScript/TypeScript
  • Installation: npm install @rollup/plugin-virtual --save-dev

Core Imports

import virtual from "@rollup/plugin-virtual";

For CommonJS:

const virtual = require("@rollup/plugin-virtual");

Basic Usage

import virtual from "@rollup/plugin-virtual";

export default {
  input: "src/entry.js",
  plugins: [
    virtual({
      // Define virtual modules by mapping IDs to source code
      batman: `export default 'na na na na na'`,
      "src/robin.js": `export default 'batmannnnn'`
    })
  ]
};

Important: Place this plugin before other plugins like @rollup/plugin-node-resolve or @rollup/plugin-commonjs in your plugin array to ensure proper module transformation.

Architecture

The plugin implements a virtual module system with several key components:

  • Virtual Module Prefix: All virtual modules are internally prefixed with \0virtual: to distinguish them from filesystem modules
  • Dual Resolution Strategy: Supports both direct key lookups and path-based resolution for relative imports
  • Memory Storage: Module content is stored in memory as strings, with no filesystem interaction
  • Resolution Map: Maintains an internal map of resolved absolute paths to module content for relative import handling

Module Resolution Flow:

  1. Direct Match: If a module ID exists directly in the modules object, it's resolved with the virtual prefix
  2. Relative Resolution: For relative imports, the plugin resolves paths relative to the importing virtual module
  3. Path Normalization: File paths are converted to absolute paths for consistent lookup

Capabilities

Virtual Module Creation

Creates a Rollup plugin that loads virtual modules from memory.

/**
 * A Rollup plugin which loads virtual modules from memory.
 * @param modules - Object mapping module IDs to their source code strings
 * @returns Virtual plugin instance with resolveId and load hooks
 */
function virtual(modules: RollupVirtualOptions): VirtualPlugin;

interface RollupVirtualOptions {
  [id: string]: string;
}

Parameters:

  • modules: Object where keys are module identifiers and values are the module source code as strings

Module ID Patterns:

  • Bare module names: "batman" - Direct module name lookup
  • Relative paths: "./robin.js" - Resolved relative to importing module
  • Absolute paths: "src/foo.js" - Resolved to absolute filesystem path

Usage Examples:

// Bare module example
virtual({
  "my-module": `
    export const config = { debug: true };
    export default function() { return "Hello!"; }
  `
})

// Relative path example  
virtual({
  "./utils.js": `
    export function formatDate(date) {
      return date.toISOString().split('T')[0];
    }
  `
})

// Dynamic entry point example
virtual({
  entry: `
    import batman from 'batcave';
    import { formatDate } from './utils.js';
    console.log(batman, formatDate(new Date()));
  `
})

Bundle Entry Point Usage

The plugin can be used to specify virtual entry points for bundles:

import virtual from "@rollup/plugin-virtual";

export default {
  input: "entry", // Virtual module name
  plugins: [
    virtual({
      entry: `
        import batman from 'batcave';
        import robin from './robin.js';
        console.log(batman, robin);
      `,
      batcave: `export default 'I am Batman!'`,
      "./robin.js": `export default 'I am Robin!'`
    })
  ]
};

Types

import { Plugin } from 'rollup';

interface RollupVirtualOptions {
  /** Module ID to source code mapping */
  [id: string]: string;
}

/**
 * Plugin instance returned by virtual() function
 * Implements Rollup's Plugin interface with virtual module support
 */
interface VirtualPlugin extends Plugin {
  name: 'virtual';
  
  /**
   * Resolves virtual module IDs with internal prefix system
   * @param id - Module identifier to resolve
   * @param importer - Path of the importing module
   * @returns Prefixed virtual module ID or null if not found
   */
  resolveId(id: string, importer?: string): string | null;
  
  /**
   * Loads virtual module content from memory
   * @param id - Resolved module ID (with virtual prefix)
   * @returns Module source code or null if not a virtual module
   */
  load(id: string): string | null;
}

Module Resolution Behavior

The plugin implements custom module resolution through two main hooks:

resolveId Hook Implementation

/**
 * Resolves module IDs to virtual modules with prefix system
 * @param id - The module ID to resolve (e.g., 'batman', './robin.js')
 * @param importer - The path of the importing module
 * @returns Virtual module ID with '\0virtual:' prefix, or null if not found
 */
resolveId(id: string, importer?: string): string | null;

Resolution Logic:

  1. Direct Key Match: If id exists directly in the modules object, returns \0virtual:${id}
  2. Relative Path Resolution: When an importer is present:
    • Strips \0virtual: prefix from importer if present
    • Resolves the relative path using Node.js path resolution
    • Checks if the resolved absolute path exists in the internal resolved IDs map
    • Returns \0virtual:${resolvedPath} if found
  3. No Match: Returns null to let other plugins handle the module

load Hook Implementation

/**
 * Loads virtual module content from memory
 * @param id - The resolved module ID (must start with '\0virtual:')
 * @returns Module source code string or null for non-virtual modules
 */
load(id: string): string | null;

Loading Logic:

  1. Virtual Module Check: Only processes IDs starting with \0virtual:
  2. ID Normalization: Removes the \0virtual: prefix to get the original ID
  3. Content Lookup: Checks both direct module keys and the resolved paths map
  4. Content Return: Returns the string content or null if not found

Internal Data Structures:

  • modules: Original object mapping IDs to source code
  • resolvedIds: Map of absolute paths to source code for relative import support
  • PREFIX: Constant \0virtual: used to identify virtual modules

Requirements

  • Node.js: v8.0.0+
  • Rollup: v1.20.0+ or v2.0.0+
  • Plugin Order: Must be placed before other resolution plugins (node-resolve, commonjs)

Common Use Cases

  1. Dynamic Code Generation: Generate modules programmatically based on build-time data
  2. Configuration Modules: Create configuration modules without physical files
  3. Testing: Mock modules for testing scenarios
  4. Bundling Virtual Entry Points: Combine multiple virtual modules into a single entry point
  5. Inline Templates: Embed template strings as importable modules