CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-rspack--core

Fast Rust-based web bundler with webpack-compatible API

Pending
Overview
Eval results
Files

hmr.mddocs/

Hot Module Replacement

Development-time module replacement system for fast iteration without losing application state, with full webpack compatibility.

Capabilities

Core HMR Interface

The main HMR API exposed through module.hot when HMR is enabled.

interface Hot {
  /** Accept module updates with optional callback and error handling */
  accept: {
    /** Accept specific modules with callback for handling updates */
    (
      modules: string | string[],
      callback?: (outdatedDependencies: string[]) => void,
      errorHandler?: (
        err: Error,
        context: { moduleId: string | number; dependencyId: string | number }
      ) => void
    ): void;
    
    /** Accept self updates with error handling */
    (
      errorHandler?: (
        err: Error,
        ids: { moduleId: string | number; module: NodeJS.Module }
      ) => void
    ): void;
  };

  /** Get current HMR status */
  status(): HotUpdateStatus;

  /** Decline updates for specific modules */
  decline(module?: string | string[]): void;

  /** Register callback for module disposal */
  dispose(callback: (data: any) => void): void;

  /** Add disposal handler */
  addDisposeHandler(callback: (data: any) => void): void;

  /** Remove disposal handler */
  removeDisposeHandler(callback: (data: any) => void): void;

  /** Invalidate current module */
  invalidate(): void;

  /** Add status change handler */
  addStatusHandler(callback: (status: HotUpdateStatus) => void): void;

  /** Remove status change handler */
  removeStatusHandler(callback: (status: HotUpdateStatus) => void): void;

  /** Data storage between updates */
  data: any;

  /** Check for available updates */
  check(autoApply?: boolean | ApplyOptions): Promise<(string | number)[] | null>;

  /** Apply pending updates */
  apply(options?: ApplyOptions): Promise<(string | number)[] | null>;
}

/** HMR status values indicating current state */
type HotUpdateStatus = "idle" | "check" | "prepare" | "ready" | "dispose" | "apply" | "abort" | "fail";

Usage Examples:

// Basic self-acceptance
if (module.hot) {
  module.hot.accept((err) => {
    if (err) {
      console.error("Cannot accept update:", err);
    }
  });
}

// Accept specific dependencies
if (module.hot) {
  module.hot.accept("./utils", (outdatedDependencies) => {
    console.log("Utils module updated:", outdatedDependencies);
    // Re-import and use updated utils
    import("./utils").then((newUtils) => {
      // Update application state with new utils
    });
  });
}

// Accept multiple dependencies with error handling
if (module.hot) {
  module.hot.accept(
    ["./component-a", "./component-b"],
    (outdatedDependencies) => {
      console.log("Components updated:", outdatedDependencies);
    },
    (err, context) => {
      console.error("Update failed:", err, context);
    }
  );
}

// Data persistence across updates
if (module.hot) {
  // Save state before disposal
  module.hot.dispose((data) => {
    data.currentUser = getCurrentUser();
    data.preferences = getPreferences();
  });

  // Restore state after update
  if (module.hot.data) {
    setCurrentUser(module.hot.data.currentUser);
    setPreferences(module.hot.data.preferences);
  }
}

// Status monitoring
if (module.hot) {
  module.hot.addStatusHandler((status) => {
    console.log("HMR Status:", status);
    
    if (status === "apply") {
      console.log("Applying updates...");
    } else if (status === "fail") {
      console.error("HMR update failed");
    }
  });
}

HMR Configuration Options

Options for controlling update application behavior.

interface ApplyOptions {
  /** Ignore modules that declined the update */
  ignoreUnaccepted?: boolean;
  /** Ignore modules that were declined by dependencies */
  ignoreDeclined?: boolean;
  /** Ignore modules that errored during update */
  ignoreErrored?: boolean;
  /** Handler for declined events */
  onDeclined?: (event: DeclinedEvent) => void;
  /** Handler for unaccepted events */
  onUnaccepted?: (event: UnacceptedEvent) => void;
  /** Handler for accepted events */
  onAccepted?: (event: AcceptedEvent) => void;
  /** Handler for disposed events */
  onDisposed?: (event: DisposedEvent) => void;
  /** Handler for error events */
  onErrored?: (event: ErroredEvent) => void;
}

HMR Event Types

Detailed event types for different HMR scenarios.

/** Module update was successfully accepted */
interface AcceptedEvent {
  type: "accepted";
  /** The module that was updated */
  moduleId: string | number;
  /** Modules that became outdated */
  outdatedModules: (string | number)[];
  /** Dependencies that became outdated */
  outdatedDependencies: { [id: number]: (string | number)[] };
}

/** Module update was declined */
type DeclinedEvent =
  | {
      type: "declined";
      /** The module in question */
      moduleId: string | number;
      /** Update propagation chain */
      chain: (string | number)[];
      /** Module that declined the update */
      parentId: string | number;
    }
  | {
      type: "self-declined";
      /** The module in question */
      moduleId: string | number;
      /** Update propagation chain */
      chain: (string | number)[];
    };

/** Module update was not accepted */
interface UnacceptedEvent {
  type: "unaccepted";
  /** The module in question */
  moduleId: string | number;
  /** Update propagation chain */
  chain: (string | number)[];
}

/** Module was disposed */
interface DisposedEvent {
  type: "disposed";
  /** The module that was disposed */
  moduleId: string | number;
}

/** Error occurred during HMR process */
type ErroredEvent =
  | {
      type: "accept-error-handler-errored";
      /** The module in question */
      moduleId: string | number;
      /** Module owning the error handler */
      dependencyId: string | number;
      /** The error that occurred */
      error: Error;
      /** Original error that triggered the handler */
      originalError: Error;
    }
  | {
      type: "self-accept-error-handler-errored";
      /** The module in question */
      moduleId: string | number;
      /** The error that occurred */
      error: Error;
      /** Original error that triggered the handler */
      originalError: Error;
    }
  | {
      type: "accept-errored";
      /** The module in question */
      moduleId: string | number;
      /** Module owning the accept handler */
      dependencyId: string | number;
      /** The error that occurred */
      error: Error;
    }
  | {
      type: "self-accept-errored";
      /** The module in question */
      moduleId: string | number;
      /** The error that occurred */
      error: Error;
    };

/** Union of all HMR event types */
type HotEvent = AcceptedEvent | DeclinedEvent | UnacceptedEvent | DisposedEvent | ErroredEvent;

ES Modules HMR Support

HMR support for ES modules via import.meta.

interface ImportMeta {
  /** HMR interface for ES modules (same as module.hot) */
  webpackHot: Hot;
  /** Base URL of the module */
  url: string;
  /** Webpack context function */
  webpackContext: (
    request: string,
    options?: {
      recursive?: boolean;
      regExp?: RegExp;
      include?: RegExp;
      exclude?: RegExp;
      preload?: boolean | number;
      prefetch?: boolean | number;
      fetchPriority?: "low" | "high" | "auto";
      chunkName?: string;
      exports?: string | string[][];
      mode?: "sync" | "eager" | "weak" | "lazy" | "lazy-once";
    }
  ) => any;
}

ES Modules Usage:

// ES modules HMR
if (import.meta.webpackHot) {
  import.meta.webpackHot.accept("./dependency", () => {
    console.log("Dependency hot-reloaded");
  });
}

HMR Client Runtime

Client-side runtime files for different HMR integration scenarios.

/** WebSocket-based HMR client for webpack-dev-server */
declare module "@rspack/core/hot/dev-server" {
  // Automatically connects to dev server
}

/** Enhanced dev-server client with better error handling */
declare module "@rspack/core/hot/only-dev-server" {
  // Only hot reloads, no page refresh on errors
}

/** Polling-based HMR client */
declare module "@rspack/core/hot/poll" {
  // Polls for updates periodically
}

/** Signal-based HMR client for Node.js */
declare module "@rspack/core/hot/signal" {  
  // Uses process signals for updates
}

/** HMR logging utility */
declare module "@rspack/core/hot/log" {
  export function setLogLevel(level: "info" | "warning" | "error" | "none"): void;
  export function info(...args: any[]): void;
  export function warning(...args: any[]): void;
  export function error(...args: any[]): void;
}

/** Event emitter for HMR events */
declare module "@rspack/core/hot/emitter" {
  interface EventEmitter {
    on(event: string, listener: (...args: any[]) => void): this;
    emit(event: string, ...args: any[]): boolean;
  }
  
  const emitter: EventEmitter;
  export default emitter;
}

HMR Plugin Configuration

Plugin for enabling Hot Module Replacement.

/** Enable HMR functionality */
class HotModuleReplacementPlugin extends RspackBuiltinPlugin {
  name: "HotModuleReplacementPlugin";
  /** No configuration options needed */
  constructor();
}

Plugin Usage:

import { HotModuleReplacementPlugin } from "@rspack/core";

const config = {
  mode: "development",
  devServer: {
    hot: true
  },
  plugins: [
    new HotModuleReplacementPlugin()
  ]
};

Advanced HMR Patterns

Common patterns for effective HMR integration.

// React component HMR
if (module.hot) {
  module.hot.accept("./App", () => {
    const NextApp = require("./App").default;
    render(<NextApp />, document.getElementById("root"));
  });
}

// Redux store HMR
if (module.hot) {
  module.hot.accept("./reducers", () => {
    const nextRootReducer = require("./reducers").default;
    store.replaceReducer(nextRootReducer);
  });
}

// CSS HMR with extraction
if (module.hot) {
  module.hot.accept("./styles.css", () => {
    // CSS is automatically reloaded by CssExtractRspackPlugin
  });
}

// Manual update checking
if (module.hot) {
  const checkForUpdates = async () => {
    try {
      const outdatedModules = await module.hot.check(false);
      if (outdatedModules) {
        console.log("Updates available:", outdatedModules);
        const result = await module.hot.apply({
          ignoreUnaccepted: true,
          onAccepted: (event) => {
            console.log("Module accepted:", event.moduleId);
          }
        });
        console.log("Updates applied:", result);
      }
    } catch (err) {
      console.error("Update failed:", err);
    }
  };

  // Check for updates every 10 seconds
  setInterval(checkForUpdates, 10000);
}

Install with Tessl CLI

npx tessl i tessl/npm-rspack--core

docs

configuration.md

core-bundling.md

hmr.md

index.md

loaders.md

module-federation.md

plugins.md

tile.json