node.js how to manage two third-party packages - node.js

I'm write a node.js application.
this application depend on another package, assume AAA..
so in "dependencies" of package.json should include it (above AAA)
my problem is:
i want to check if user has installed AAA and use it, otherwise use AAA which my application install.
pseudolanguage:
import AAA as myAAA from 'AAA';
let fallback
if (user has been installed AAA){
fallback = AAA;
} else {
fallback = myAAA;
}
can i do that?

In short, no, what you are trying to do can not be done in a simple manner. The order by which Node.js tries to locate a module referred by name is as follows :
Check to see if the given module is a core module.
Search for a directory named node_modules in the current directory
(project directory).
Work the way up the folder hierarchy, checking each level for a
node_modules folder.
Look at the directory paths outlined in the require.paths array in
node.
You cant make Node.JS change the order of this lookup - which is what you are trying to do.
There can be other ways to achieve this - for example, look for the global node_modules install location and see if the package is in that folder - if so, you can require() the absolute path to the global package, if not, you can require() the package as usual, and the local package will be used.
Reference:
http://www.bennadel.com/blog/2169-where-does-node-js-and-require-look-for-modules.htm

Related

How does require work?

I have 2 files in a folder called js. I am using webpack.
js/app.js and js/login.es6.
I'm trying to include the login from my app.js:
require('login.es6') fails
require('./login.es6') works.
Any idea why?
When you write require('login.es6') node will look for a module named login.es6 in your node_modules.
When you write require('./login.es6') node understands that ./login.es6 is a relative path and will load your js/login.es6.js file.
This is needed to distinguish between modules and local files. There may be a npm module called login.es6; this way you can reference both the module and your local file in your project.
The node.js docs on require are pretty nice and gives a good overview of how modules are prioritized when loaded.
The gist is, if you don't start the string with ./, require will first look for a core module, then recursively look in the node_modules directory/-ies. So it's normal to start require calls to local files with ./.

How to build node addon, so that it can be imported only by name, and not path

When I build a node add-on by creating a standard binding.gyp and running node-gyp build, the addon.node library is created in the subdirectory build/{Release|Debug}/. When I write tests or other javascript code to use this module, I have to give explicit path to the library location
For example,
var addon = require('./build/Release/addon')
However, I would like to do this by only specifying the module name and let node's module search for the library
var addon = require('addon')
How can that be achieved?
I believe the only way to do this is setting require() and having the module in the node_modules folder or having the module in a node_modules folder in one of the parent directories.
Node uses the require() method with no path defined as an indicator to look for the module in the node_modules directory. Unless its an native module.
Its detailed in the docs here.
There's a module for that if you're okay with another dependency.
https://www.npmjs.com/package/bindings
That will search all of the possible build output locations automatically, including debug and release directories.

Nodejs require module from external folder

I'm developing microservice architecture on nodejs.
I moved 'core' functionality to separate git repository, and each 'service' add that core as npm dependency.
In service I use core as
require('core/module1');
In that case nodejs takes 'core' from node_modules, it's ok for production but for development I want to take 'core' from the external folder not from node_modules.
My main idea - do changes in 'core' and immidiately get the result in 'service'.
I cannot use NODE_PATH for specify external 'core' folder, because I've used it now.
I found solution to use 'app-module-path' module for adding additional directories to the Node.js module search path.
if(isDevelopment()){
require('app-module-path').addPath('path_to_core_folder');
}
It's working solution, but maybe you can suggest some more clear way?
My folders structure
- core
module1
- service1
-index.js
-node_modules
-core
Thanks.
Either one works. If you require('modulename') and it's present in your node_modules folder, it will be loaded from there. If you want it to load from another folder or from your main folder, you need to do require('./modulename") which will look for it in the current folder. Alternatively you can do require('./my_modules/modulename') which will work for a subfolder.
i would look at the mockrequire module, it allows you to redirect the directory your modules are loaded from
npm link is the answer to your problem. You can run the below command in the root directory of 'service1' (where your package.json is present)
npm link [../relative-path-to/library]
Refer to https://docs.npmjs.com/cli/v7/commands/npm-link for more details about npm link.

require('module/component') when component.js is not in module root?

I'm trying to create a npm package of a couple React components. These will be used in a couple of other projects so I would like them in a separate package.
What I would like to be able to do is require('comps/a-component') from an app using this package. I could do this by putting all my components in the root of the module, but I don't want to do that. Instead I want to have all components in src/components/ because the root will be overcrowded.
This seems like a trivial thing to do but I have not yet succeeded. I've looked through https://docs.npmjs.com/files/package.json trying to find an option to set the root or something. Does anyone have any ideas on how to achieve this?
Thanks!
You can make symlink in you node_modules directory to your components directory. This would allow you to require your components from anywhere in your app like you said: require('comps/a-component'). To create the symlink on a linux or osx you can do something like this
cd ./node_modules; ln -snf ../src/components comps;
Another option would be to actually create npm packages out of each component, that way you could have them listed in your dependencies of your package.json.
Another promising option that was released in npm 2.0 are local dependencies. This allows you to point to a local npm package on your file system. In this case each component would have to be written as an npm package with a package.json https://docs.npmjs.com/files/package.json#local-paths
If your app is like this:
- AppFolder
|-index.js
|-Readme.md
|-/src
|-app.js
|-anotherThing.js
If I want to use anotherThing.js, I can just do var anotherThing = require('./src/anotherThing');. Unless I fail to understand your problem.
Or maybe you meant the main attribute in package.json

require name instead of file path

I am looking at some code on github.
https://github.com/madhums/node-express-mongoose/blob/master/config/routes.js
On line 7 it says.
var home = require('home');
home.js is in another folder. I am wondering how this works, and how I can do this in my own code.
on
http://nodejs.org/api/modules.html#modules_folders_as_modules
it explains how to create a self-contained directory, but I can only find the package.json in the root folder. So how does this work?
It seems like a more clean way than having direct file references.
There are ways to refer to folders on the filesystem as packages in node, npm link for example, will pretend a folder is a module using symlinks.
The package you linked to is cheating a bit though, and I'd argue it's not clean at all when put like that. It's actually setting the NODE_PATH to include all controllers when the service is ran: https://github.com/madhums/node-express-mongoose/blob/master/package.json#L13
So all controllers files like home.js are autmatically available. The .js is always optional anyway.

Resources