在Nodejs中延迟加载模块

时间:2015-05-25 18:49:07

标签: node.js requirejs commonjs

我的第一个问题是:谁负责处理Nodejs应用程序中的require语句?是Node本身吗?还是CommonJS?还是RequireJS? CommonJS是否包含在Node中? RequireJS怎么样?

现在我的第二个问题:

我有一个if-else语句,它决定我们是在服务器端还是客户端渲染。我想在客户端或服务器端渲染时加载不同的库。是否可以在运行时加载模块?恰好在它需要的那一刻?

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

看起来Node在启动应用程序之前加载了所需的所有内容。因此,如果您在代码顶部或if-else块中需要它,那么这一点并不重要。

4 个答案:

答案 0 :(得分:7)

在Node.js中,Node本身处理require。你错了 - 在程序的评估到达之前,require不会被评估。如果你有这个代码:

var mod;

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

...您可以确定两件事:1。永远不会加载模块b,并且2.模块a将在五秒钟后才会加载。

在浏览器中,require仅在您使用定义它的库时定义,例如RequireJS,Browserify或Webpack。通常,这些工具保持接近Node的行为:虽然浏览器可能会立即下载所有代码(特别是如果您有一个构建步骤将所有模块放入一个文件中),它们会将每个模块包装在一个函数中在require d。

之前,它不会被实际评估

如果要根据代码是在客户端还是服务器上运行来加载不同的模块,我建议您在构建步骤中执行此操作 - 大多数构建工具(如上所述)具有此功能或可用作一个插件 - 而不仅仅是一个if语句,因为使用if语句,您仍然在制作浏览器下载代码,它永远不会使用。

答案 1 :(得分:1)

重写.js文件扩展名以隐藏目录循环中的.js文件,默认情况下调用require时会发生这种情况,并创建以编程方式调用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');
});

包装分配给require调用的变量的访问者:

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

<强>参考

答案 2 :(得分:0)

有两种方法可以选择需要一些东西:

选项1-块内/ if语句

在您的代码中,这将起作用:

let theLibary;
if (typeof window === undefined){
   theLibrary = require('A');
} else {
   theLibrary = require('B');
}
// Now use theLibrary and only the one you want will be included

其他代码可能会打包在客户端上,但永远不会执行。

选项2-创建一个使用Lazy require ninjary的库

创建一个名为library_of_libraries.js的新库,该库执行以下操作:

thisLibrary = module.exports;

// Lazy load only on usage
thisLibrary.__defineGetter__("A", function () {
    return require("A");
});

thisLibrary.__defineGetter__("B", function () {
    return require("B");
});

现在,在您的其他代码中,当您需要该库时,它将按需加载。

const LibraryOfLibraries = require("library_of_libraries");

LibraryofLibraries.A.someFunc();  // Library B is never loaded

@Paul Sweatte的答案使我走了正确的道路。

答案 3 :(得分:-2)

请记住解释nodeJs。所以他只是做了代码里面的任何事情,以便不依赖它是什么!......无论你在哪里做什么&#34;要求(某事)&#34;,它都会执行正常,没有错误应该是抛出,除非你有sintax错误或者你没有安装你需要的库。

所以你可以随心所欲地做!你可以在If语句中要求包。您需要考虑的是在这些IF后面按照正确的方式进行操作,因为如果您尝试使用从未导入过的库,则会出现RunTime错误。

干杯!