在Nodejs中延迟加载模块

问题描述 投票:4回答:4

我的第一个问题是:谁负责处理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块中需要它,那么这一点并不重要。

node.js requirejs commonjs
4个回答
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的行为:虽然浏览器可能会立即下载所有代码(特别是如果您有一个构建步骤将所有模块放入一个文件中),它们会将每个模块包装在一个函数中它实际上不会被评估,直到它是required。

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


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');

参考


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的回答让我走上了正确的道路。


-2
投票

请记住,解释了nodeJs。所以他只是做了代码中的任何内容,以便不依赖它是什么!...无论你在哪里做“require(something)”,它都会执行正常,除非你有一个sintax,否则不应该抛出任何错误错误或您尚未安装所需的库。

所以你可以随心所欲地做!你可以在If语句中要求包。你需要考虑的是你在那些IF之后遵循正确的方法,因为如果你试图使用一个从未导入的库,你将得到一个RunTime错误。

干杯!

© www.soinside.com 2019 - 2024. All rights reserved.