可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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.
回答1:
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 require
d.
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.
回答2:
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
回答3:
There are two ways to optionally require something:
Option 1 - Inside a block / if statement
In your code, this will work:
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
The other code may get packaged on the client, but it will never be executed.
Option 2 - Create a library that uses Lazy require ninjary
Create a new library called library_of_libraries.js that does:
thisLibrary = module.exports;
// Lazy load only on usage
thisLibrary.__defineGetter__("A", function () {
return require("A");
});
thisLibrary.__defineGetter__("B", function () {
return require("B");
});
Now, in your other code, when you want the library, it will be loaded on demand.
const LibraryOfLibraries = require("library_of_libraries");
LibraryofLibraries.A.someFunc(); // Library B is never loaded
Credit goes to @Paul Sweatte's answer for leading me down the right path.
回答4:
Remember that nodeJs is interpreted. So he just does whatever is inside the code in order not depending what it is!... It does not matter where you do your "require(something)", it will execute ok and no error should be thrown unless you have a sintax error or you have not installed the library you are requiring.
So you can definetly do as you want!, You can require packages inside If statements. What you have to consider is that you follow the right way after those IF because if you try to use a library that was never imported you will get a RunTime error.
Cheers!