Import a module lazily using JavaScript Proxy objects to defer loading until first access
npx @tessl/cli install tessl/npm-import-lazy@4.0.0import-lazy provides lazy loading functionality for Node.js modules using JavaScript Proxy objects. It defers the actual import/require operation until the module is first accessed, helping reduce initial load time and memory consumption in applications where certain modules may not always be used.
npm install import-lazyconst importLazy = require('import-lazy');TypeScript:
import importLazy = require('import-lazy');const importLazy = require('import-lazy');
// Create a lazy import function bound to require
const lazyRequire = importLazy(require);
// Import modules lazily - they won't be loaded until first access
const _ = lazyRequire('lodash');
const fs = lazyRequire('fs');
// Module is loaded only when first accessed
_.isNumber(42); // lodash is loaded and cached now
_.isString('hello'); // subsequent calls use cached module
// Works with local modules too
const utils = lazyRequire('./utils');
console.log(utils.formatDate(new Date()));Creates a lazy import function that uses the provided import function to load modules on demand.
/**
* Creates a lazy import function that defers module loading until first access
* @param {function} importFn - Function to use for importing modules (typically require)
* @returns {function} A function that creates lazy proxies for modules
*/
function importLazy(importFn) {
return function(moduleId) {
// Returns a Proxy that loads the module on first access
return new Proxy(function () {}, {
get: (target, property) => { /* loads module and returns property */ },
apply: (target, thisArgument, argumentsList) => { /* loads module and applies as function */ },
construct: (target, argumentsList) => { /* loads module and constructs instance */ }
});
};
}Parameters:
importFn (function): Import function to use for loading modules, typically require
(moduleId: string) => anyReturns:
moduleId (string) and returns a Proxy objectUsage Examples:
// Standard usage with require
const importLazy = require('import-lazy');
const lazyRequire = importLazy(require);
const lodash = lazyRequire('lodash');
// Custom import function
const customImport = (moduleId) => {
console.log(`Loading ${moduleId}`);
return require(moduleId);
};
const lazyCustom = importLazy(customImport);
const moment = lazyCustom('moment');The proxy object returned by the lazy import function supports all standard JavaScript operations.
/**
* Proxy object that intercepts module access and loads the target module on demand
* Supports property access, function calls, and constructor invocations
*/
interface LazyModuleProxy {
// Supports any property access - loads module on first access
[key: string]: any;
// Supports function calls - loads module if it's a function
(...args: any[]): any;
// Supports constructor calls - loads module if it's a class
new (...args: any[]): any;
}Supported Operations:
lazyModule.somePropertylazyModule.someMethod(args)lazyModule(args) (if module exports a function)new LazyModule(args) (if module exports a class)Usage Examples:
const importLazy = require('import-lazy');
const lazyRequire = importLazy(require);
// Property access
const chalk = lazyRequire('chalk');
console.log(chalk.red('Error message')); // chalk loaded on first access
// Function calls (module exports a function)
const validator = lazyRequire('validator');
const isEmail = validator.isEmail('test@example.com');
// Constructor calls (module exports a class)
const EventEmitter = lazyRequire('events');
const emitter = new EventEmitter();
// Mixed usage (object with functions and properties)
const path = lazyRequire('path');
console.log(path.sep); // property access
const joined = path.join('/usr', 'local'); // method callModules are only loaded when first accessed through the proxy. This helps reduce initial application startup time and memory usage.
Once a module is loaded, it's cached for all subsequent accesses. The actual module object is used directly after the first load.
Warning: Destructuring assignment will cause immediate module loading, negating the lazy behavior:
// This will load the module immediately
const {isNumber, isString} = lazyRequire('lodash');
// Equivalent to:
const {isNumber, isString} = require('lodash');The lazy loading is implemented using JavaScript Proxy objects with handlers for:
get: Property access and method retrievalapply: Function calls when the module itself is a functionconstruct: Constructor calls when the module is a classimport-lazy includes TypeScript definitions for type safety:
/**
* Import a module lazily using a Proxy that defers loading until first access
* @template T - Type of the module being imported
* @param importFn - Function to use for importing modules (typically require)
* @returns A function that creates lazy proxies for modules of type T
*/
declare function importLazy<T = unknown>(
importFn: (moduleId: string) => T
): (moduleId: string) => T;
export = importLazy;Usage in TypeScript:
import importLazy = require('import-lazy');
// Type-safe usage
const lazyRequire = importLazy(require);
const lodash = lazyRequire('lodash'); // Type: unknown by default
// With custom typing
interface LodashModule {
isNumber(value: any): value is number;
isString(value: any): value is string;
}
const typedLazyRequire = importLazy<LodashModule>(require);
const typedLodash = typedLazyRequire('lodash'); // Type: LodashModule