or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

Expose-Loader

The expose-loader is a webpack loader that allows you to expose modules (in whole or in part) to the global object (self, window, and global). It enables developers to make npm packages available globally in browser environments, particularly useful for legacy code integration and shimming scenarios.

Package Information

  • Package Name: expose-loader
  • Package Type: npm
  • Language: JavaScript (ES6+ with Babel)
  • Installation: npm install expose-loader --save-dev
  • Webpack Version: ^5.0.0
  • Node.js: >= 18.12.0

Core Imports

The expose-loader is a webpack loader, so it's typically configured in webpack configuration files rather than imported directly:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: require.resolve("jquery"),
        loader: "expose-loader",
        options: {
          exposes: ["$", "jQuery"],
        },
      },
    ],
  },
};

For inline usage:

import $ from "expose-loader?exposes=$,jQuery!jquery";

Basic Usage

Exposing entire module:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: require.resolve("jquery"),
        loader: "expose-loader",
        options: {
          exposes: "$", // Exposes entire jQuery to window.$
        },
      },
    ],
  },
};

Exposing specific module exports:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: require.resolve("underscore"),
        loader: "expose-loader",
        options: {
          exposes: [
            {
              globalName: "_.map",
              moduleLocalName: "map", // Only expose the map function
            },
            {
              globalName: "_.filter",
              moduleLocalName: "filter", // Only expose the filter function
            },
          ],
        },
      },
    ],
  },
};

Capabilities

Loader Configuration

The main entry point for expose-loader configuration through webpack.

interface LoaderOptions {
  exposes: string | ExposeConfig | Array<string | ExposeConfig>;
  globalObject?: string;
}

interface ExposeConfig {
  globalName: string | string[];
  moduleLocalName?: string;
  override?: boolean;
}

String-Based Expose Syntax

Simple string format for basic exposing needs.

/**
 * String syntax: "globalName [moduleLocalName] [override]"
 * Separators: space or pipe (|)
 * 
 * Examples:
 * - "$" - Expose entire module as $
 * - "$ jQuery" - Expose as both $ and jQuery
 * - "_.map map" - Expose only 'map' export as _.map
 * - "$ jQuery true" - Override existing global values
 */
type ExposeString = string;

Object-Based Expose Configuration

Detailed configuration object for complex exposing scenarios.

interface ExposeConfig {
  /** The name(s) in the global object (required) */
  globalName: string | string[];
  /** The specific export to expose (optional - defaults to entire module) */
  moduleLocalName?: string;
  /** Allow overriding existing global values (optional - defaults to false) */
  override?: boolean;
}

Usage Examples:

// Single global name
{
  globalName: "$",
  moduleLocalName: "default"
}

// Multiple global names (nested object creation)
{
  globalName: ["lodash", "_"],
  moduleLocalName: "default"
}

// Override existing globals
{
  globalName: "$",
  override: true
}

// Expose specific export
{
  globalName: "_.map",
  moduleLocalName: "map"
}

Array-Based Multiple Exposes

Configure multiple exposures in a single loader rule.

type ExposesList = Array<string | ExposeConfig>;

Usage Example:

{
  exposes: [
    "$",                                    // String format
    "jQuery",                              // Another string format
    {
      globalName: "_.map",
      moduleLocalName: "map"
    },
    {
      globalName: ["utils", "helpers"],
      moduleLocalName: "utilities"
    }
  ]
}

Global Object Configuration

Specify a custom global object for exposing.

interface GlobalObjectOption {
  /** Custom global object reference (optional - defaults to auto-detection) */
  globalObject?: string;
}

Usage Example:

{
  exposes: ["myLibrary"],
  globalObject: "this" // Use 'this' instead of window/global/self
}

Inline Usage Syntax

Use expose-loader directly in import statements.

/**
 * Inline syntax: expose-loader?exposes=config!module
 * Multiple exposes: expose-loader?exposes=config1,config2!module
 * 
 * Examples:
 * - "expose-loader?exposes=$!jquery"
 * - "expose-loader?exposes=$,jQuery!jquery" 
 * - "expose-loader?exposes=_.map|map!lodash"
 */

Usage Examples:

// Single expose
import $ from "expose-loader?exposes=$!jquery";

// Multiple exposes
import $ from "expose-loader?exposes=$,jQuery!jquery";

// With module local name
import { concat } from "expose-loader?exposes=_.concat!lodash/concat";

// Multiple with specific exports
import {
  map,
  reduce,
} from "expose-loader?exposes=_.map|map,_.reduce|reduce!underscore";

Types

Core Type Definitions

interface LoaderContext {
  /** Get validated options for the loader */
  getOptions(schema?: object): LoaderOptions;
  /** Async callback for loader completion */
  async(): (error?: Error, result?: string) => void;
  /** Current webpack mode (development/production) */
  mode?: string;
  /** Module being processed */
  _module: {
    userRequest: string;
    factoryMeta?: {
      sideEffectFree: boolean;
    };
  };
}

interface ExposeItem {
  globalName: string[];
  moduleLocalName?: string;
  override?: boolean;
}

Global Object Detection

/**
 * Runtime global object detection function
 * Returns the appropriate global object for the current environment
 * Priority: globalThis > window > self > global > Function('return this')()
 */
declare function getGlobalThis(): typeof globalThis | typeof window | typeof self | typeof global;

Internal Utility Functions

These functions are used internally by the loader but are part of the public API for advanced use cases.

/**
 * Modifies module request to prevent caching conflicts
 * @param request - webpack module request string
 * @returns Modified request string with "-exposed" suffix
 */
declare function getNewUserRequest(request: string): string;

/**
 * Parses and normalizes expose configuration into standard format
 * @param items - expose configuration (string, object, or array)
 * @returns Array of resolved expose objects
 */
declare function getExposes(items: string | ExposeConfig | Array<string | ExposeConfig>): ExposeItem[];

/**
 * Converts absolute paths to relative paths for webpack
 * @param loaderContext - webpack loader context
 * @param context - base context path
 * @param request - module request to contextualize
 * @returns Contextualized request path
 */
declare function contextify(loaderContext: LoaderContext, context: string, request: string): string;

/**
 * Safely stringifies module requests for code generation
 * @param loaderContext - webpack loader context
 * @param request - module request to stringify
 * @returns JSON stringified request
 */
declare function stringifyRequest(loaderContext: LoaderContext, request: string): string;

/**
 * Replaces [name] placeholder with actual module name
 * @param loaderContext - webpack loader context
 * @param filename - filename template with placeholders
 * @returns Interpolated filename
 */
declare function interpolateName(loaderContext: LoaderContext, filename: string): string;

Configuration Examples

Basic jQuery Integration

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: require.resolve("jquery"),
        loader: "expose-loader",
        options: {
          exposes: ["$", "jQuery"],
        },
      },
    ],
  },
};

Lodash Utilities Exposure

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: require.resolve("lodash"),
        loader: "expose-loader",
        options: {
          exposes: [
            {
              globalName: "_",
            },
            {
              globalName: "_.map",
              moduleLocalName: "map",
            },
            {
              globalName: "_.filter",
              moduleLocalName: "filter",
            },
          ],
        },
      },
    ],
  },
};

Override Protection

// webpack.config.js - Development mode will throw errors
module.exports = {
  mode: "development",
  module: {
    rules: [
      {
        test: require.resolve("jquery"),
        loader: "expose-loader",
        options: {
          exposes: {
            globalName: "$",
            override: false, // Will throw error if $ already exists
          },
        },
      },
    ],
  },
};

Custom Global Object

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: require.resolve("my-library"),
        loader: "expose-loader",
        options: {
          exposes: ["myLib"],
          globalObject: "this", // Use 'this' context instead of window/global
        },
      },
    ],
  },
};

Error Handling

The expose-loader provides several error conditions:

  • Validation Errors: Invalid options configuration will throw during webpack compilation
  • Parse Errors: Malformed string syntax in exposes configuration
  • Override Errors: In development mode, attempting to overwrite existing globals without override: true
  • Module Resolution: Errors when the target module cannot be resolved

Development Mode Protection:

// In development mode, this will throw an error if window.$ already exists
{
  exposes: {
    globalName: "$",
    override: false // Default value
  }
}

// To allow overriding:
{
  exposes: {
    globalName: "$",
    override: true
  }
}

Compatibility

  • Webpack: ^5.0.0 (use expose-loader@1 for Webpack 4)
  • Node.js: >= 18.12.0
  • Browsers: All modern browsers supporting ES5+
  • Environments: Browser (window), Web Workers (self), Node.js (global), Universal (globalThis)

Generated Output

The expose-loader generates runtime code that:

  1. Imports the target module using webpack's require system
  2. Detects the appropriate global object for the environment
  3. Creates nested global properties as needed (e.g., window.lodash._)
  4. Assigns the module or specific exports to the global properties
  5. Includes override protection in development mode
  6. Re-exports the original module for normal usage

Example Generated Code Pattern:

var ___EXPOSE_LOADER_IMPORT___ = require("./path/to/module");
var ___EXPOSE_LOADER_GET_GLOBAL_THIS___ = /* getGlobalThis function */;
var ___EXPOSE_LOADER_GLOBAL_THIS___ = ___EXPOSE_LOADER_GET_GLOBAL_THIS___;

// Create nested structure if needed
if (typeof ___EXPOSE_LOADER_GLOBAL_THIS___["$"] === 'undefined') 
  ___EXPOSE_LOADER_GLOBAL_THIS___["$"] = ___EXPOSE_LOADER_IMPORT___;

module.exports = ___EXPOSE_LOADER_IMPORT___;