1.13.0 • Published 6 years ago

require-extra v1.13.0

Weekly downloads
6
License
MIT
Repository
github
Last release
6 years ago

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.
1.13.0

6 years ago

1.12.0

6 years ago

1.11.4

6 years ago

1.11.3

6 years ago

1.11.2

6 years ago

1.11.1

6 years ago

1.10.2

6 years ago

1.10.1

6 years ago

1.10.0

6 years ago

1.9.1

6 years ago

1.9.0

6 years ago

1.8.0

6 years ago

1.7.1

6 years ago

1.7.0

6 years ago

1.6.0

6 years ago

1.5.8

6 years ago

1.5.7

6 years ago

1.5.6

6 years ago

1.5.5

6 years ago

1.5.4

6 years ago

1.5.3

6 years ago

1.5.2

6 years ago

1.5.1

6 years ago

1.5.0

6 years ago

1.4.2

6 years ago

1.4.1

6 years ago

1.4.0

6 years ago

1.3.0

6 years ago

1.2.0

7 years ago

1.1.0

7 years ago

1.0.0

7 years ago

0.7.0

7 years ago

0.6.0

7 years ago

0.4.1

7 years ago

0.4.0

8 years ago

0.3.12

8 years ago

0.3.11

8 years ago

0.3.10

8 years ago

0.3.9

8 years ago

0.3.8

8 years ago

0.3.7

8 years ago

0.3.6

8 years ago

0.3.5

8 years ago

0.3.4

8 years ago

0.3.3

8 years ago

0.3.2

8 years ago

0.3.1

8 years ago

0.3.0

8 years ago

0.2.3

8 years ago

0.2.2

9 years ago

0.2.0

9 years ago

0.1.0

9 years ago