npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

require-extra

v1.13.0

Published

NodeJs module loading with an asynchronous flavour

Downloads

16

Readme

require-extra

NodeJs module loading with an asynchronous flavour. Adds a number of useful functions and extra options not available via native require() as well as making it asynchronous.

Installation

$ npm install --save require-extra

Or

$ yarn add require-extra

Asynchronous loading

The loader returns a Promise.

Note: Whilst module paths are resolved asynchronously and their content loaded, any requires within the module will load in the normal sychronous way (see roadmap).

var requireX = require('require-extra');

requireX('express').then(function(express){
  console.log('Module express has loaded');
}, function(error){
  console.error('Module express, failed to load', error);
});

Callbacks following the standard node style can be used instead of (or as well as) promises.

var requireX = require('require-extra');

requireX('express', function(error, express){
  if(error){
    console.error('Module express, failed to load');
  }else{
    console.log('Module express has loaded', error);
  }
});

Promises

Breaking change: This module now uses native promises instead of the bluebird-style it used previously. The reason for this change is to reduce the dependencies and it make the use of async/await seamless.

The promise type returned can be overriden by setting the promise library.

requireX.set('Promise', require('bluebird'));

This will cause all returned promises to be wrapped in the supplied promise library.

Loading multiple modules at once

The loader can also accept an array of module-id's/paths; this will then load together asynchronously.

var requireX = require('require-extra');

requireX.require(['express' , 'socket.io']).spread(function(express, IO){
  console.log('Module express & socket.io has loaded');
}).catch(function(error){
  console.error('Module express or socket.io has failed to load', error);
});

Note: All modules in the array will load together. This might not be what you want. Performance boosts created by caching, where two modules have a shared dependency could be lost. It is possible in this situation that the dependency will be loaded twice. In most situations this will not be an issue or not happen but this behaviour should be noted and tested if performance is a big issue.

Asynchronous require.resolve()

A resolve method is available. It works just like the native require.resolve(), except asynchronously. The resolve() method is a wrapper around resolve.

var requireX = require('require-extra');

requireX.resolve('express').then(function(path){
  console.log('Path to express module: ', path);
}, function(error){
  console.error('Failed to find module express');
});

Possible breaking change: Previously, the library used the async-resolve library but this has been swapped for a wrapped version of resolve. The wrapped version supplies all the same methods and properties as the original async-resolve method so no errors should result.

Passing options to require() and resolve()

An options object can be passed to both require() and require.resolve() as the first argument.

The possible options are:

  1. resolver: A resolver class instance for calculating paths (this an object with resolve function like the one available in async-resolve).
  2. basedir The route directory to use for starting path calculations. If this is not supplied then the path is calculated using an algorithm that loops through a stack trace.
  3. moduleDirectory [defaults to node_modules] Where to search for modules.
  4. parent The parent module to give exported module.
  5. scope The scope to add to default scope (default being: require, __dirname, __filenmae, exports). You can also supply a function which decideds how to apply the scope depending on the module. With a function you can make some child modules have a special scope and others default.
var requireX = require('require-extra');

requireX({
  dir: '/home/me/.npm',
  resolver: myResolverClass
}, 'express').then(function(express){
  console.log('Module express has loaded');
}, function(error){
  console.error('Module express, failed to load', error);
});

Creating your own resolver class

The getResolver() method can be used to create a new resolver class instance. This can be passed back to require or resolve as in the above example.

var requireX = require('require-extra');

myResolverClass = requireX.getResolver({
  // default: ['.js', '.json', '.node'] - specify allowed file-types, note that the 
  // order matters. in this example index.js is prioritized over index.coffee 
  extensions: ['.js', '.coffee', '.eco'],
  // default : 'node_modules' - its 'node_modules' directory names, may be changed 
  moduleDirectory : 'other_modules'
})

Trying multiple paths for a module

The method try() will try an array of paths looking for a module until it it finds the requested file. Module is loaded and returned or a default value (defaults to undefined).

var requireX = require('require-extra');

requireX.try(
  ['/somePath', '../some/other/path'], null
).then(function(someModule){
  if(someModule !== null){
    console.log('Module found');
  }else{
    console.warn('Module not found');
  }
}, function(error){
  console.error('Failed loading module', error);
});

You can also use the native require by passing true as the first option to try. This is useful if you want to to try different module paths but do not want to use an async require. The method still returns a promise and the requires are actually done on nextTick() but using the native node require().

var requireX = require('require-extra');

requireX.try(
  true
  ['/somePath', '../some/other/path'], null
).then(function(someModule){
  if(someModule !== null){
    console.log('Module found');
  }else{
    console.warn('Module not found');
  }
}, function(error){
  console.error('Failed loading module', error);
});

Importing an entire directory

The method importDirectory() will import all modules in a directory (excluding the calling module if it is in the same directory). This is useful when loading order is not important and you want all modules in a specfic folder. Can be used to reduce config options in large modules, just drop the file in-place and no need to tell it to load.

var requireX = require('require-extra');

requireX.importDirectory(
  '/somePath'
).then(function(modules){
  console.log('My module', modules);
}, function(error){
  console.error('Failed loading directory', error);
});

Each module is imported into its own property (unless the merge option is set to true, see below).

The second parameter, an options object, allows for greater control over the imports:

  1. extension: [defaults to ['.js', '.json', '.node']] Filter for files with this extension. Defaults to the default for the resolver class (currently node standard of .js, .json, .node). Can pass an array here or a string containing one extension name.
  2. imports: [defaults to new object] Object to import into.
  3. callback: Callback to run after each import will fire function(, ).
  4. merge: [defaults to false] Whether to merge imorted properties and methods together.
  5. useSyncRequire [defaults to false] Whether to use the native node require or the async version in this module.
  6. parent The parent module name. Async/Await functions do not give a full stack trace so this is essential when these are used as this cannot be calculated.
  7. basedir The directory we count as the base for resolve operations. As with parent this is needed if async/await is being used.