Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy loading of modules in Nodejs

My first question is : Who is responsible to handle require statements in a Nodejs application ? is it Node itself ? or CommonJS ? or RequireJS ? Is CommonJS included in Node ? what about RequireJS?

Now my second question :

I have an if-else statement , which decides if we are rendering on server side or client side. I want to load different libraries when it's rendering on client side or server side. Is it possible to load the modules in runtime ? exactly at the moment it's required ?

    if (typeof window === undefined){
       var serverSideLibrary = require('A');
       //.... 
    }else{
       var clientSideLibrary = require('B');
    }

It looks like Node loads everything required before starting the application. So it's not important if you require it at the top of the code or in that if-else block.

like image 279
Arian Avatar asked May 25 '15 18:05

Arian


2 Answers

In Node.js, Node itself handles require. And you're mistaken—a require is not evaluated until the program's evaluation reaches it. If you have this code:

var mod;

setInterval(function() {
  if (true) {
    mod = require("a");
  } else {
    mod = require("b");
  }
}, 5000);

...you can be sure of two things: 1. Module b will never be loaded, and 2. Module a won't be loaded until five seconds have elapsed.

In the browser, require is only defined if you use a library that defines it, like RequireJS, Browserify or Webpack. In general these tools stay close to Node's behavior: While the browser might download all of the code at once (especially if you have a build step that puts all of your modules into a single file), they will wrap each module in a function so that it won't actually be evaluated until it's required.

If you want to load different modules depending on whether your code is running on the client or the server, I would recommend doing this in your build step—most build tools, like those mentioned above, have this functionality or it's available as a plugin—instead of just an if statement, because with the if statement you're still making the browser download code it's never going to use.

like image 77
Jordan Running Avatar answered Oct 20 '22 01:10

Jordan Running


Override the .js file extension to hide .js files from the directory loop which happens by default when require is called, and create custom methods which programmatically call require on demand:

var fs = require('fs'),
    IonicAppLib = module.exports,
    path = require('path');

var camelCase = function camelCase(input) {
    return input.toLowerCase().replace(/-(.)/g, function(match, group1) {
        return group1.toUpperCase();
    });
};

//
// Setup all modules as lazy-loaded getters.
//
fs.readdirSync(path.join(__dirname, 'lib')).forEach(function (file) {
  file = file.replace('.js', '');
  var command;

  if (file.indexOf('-') > 0) {
    // console.log('file', file);
    command = camelCase(file);
  } else {
    command = file;
  }

  IonicAppLib.__defineGetter__(command, function () {
    return require('./lib/' + file);
  });
});

IonicAppLib.__defineGetter__('semver', function () {
  return require('semver');
});

which wraps the accessor for the variable assigned to the require call:

var IonicAppLib = require('ionic-app-lib');

References

  • Lazy loading your node modules - Josh Bavari's Ramblings

  • nodejs module.require and require

  • Auto require a directory in Node.js (Example)

  • Modules: Exports Shortcut | Node.js v7.10.0 Documentation

  • node/module.js at master · nodejs/node · GitHub

like image 28
4 revs Avatar answered Oct 19 '22 23:10

4 revs