How are relative paths resolved inside of node packages? - node.js

I am making a npm package which, after installation, runs a postinstall script located in the lib/ directory. This postinstall script in turn copies a config file, located in the same directory (as the module), to the user's project's root using fs.copyFile function. But I am a little confused about how the two paths are referenced when from inside the node_modules directory.
So, long talk made short, I want to figure out what prefixes should I use to refer to files in MY module and for the user's project's directory. Basically, how are relative paths resolved by node when referenced from a script inside the node_modules directory?

Related

Is there any way of changing the relative path of a mjs file (to make it see a different node_modules folder)?

When I'm executing pure node.js scripts I can change the path where it searches for node_modules as the following:
export NODE_PATH="/home/user/node_modules"
node "/home/user/different/path/file.js"
This way, I can make scripts located inside /home/user/different/path/ see the node_modules folder located in /home/user/ when they are executed.
So far everything is fine, the problem starts with .mjs files. If I try running:
export NODE_PATH="/home/user/node_modules"
node "/home/user/different/path/file.mjs"
I'll receive the error Error [ERR_MODULE_NOT_FOUND] for the modules that I use in my code. The workaround that I know for that is creating a symbolic link inside my script's folder. Something like:
ln -s "/home/user/node_modules" "/home/user/different/path/node_modules"
After doing that, if I run node "/home/user/different/path/file.mjs" it'll work as expected and I'll be able to use libraries installed on /home/user/node_modules with the import statement in my script. However, I'd like to find a solution that doesn't require me to create a symbolic link of the node_modules folder. Is there any alternative solution when I'm working with .mjs files that allows me to change its relative path?

Accessing cli global files with NodeJS

I'm developing a CLI module that can be installed either locally or globally. It references local templates to be used during the CLI process (e.g. copy some of them in the current folder, ...).
How can I retrieve the path where those templates are installed (in the current node_modules folder or in the global npm/yarn node_modules folder) to use them?
So the scenario is that a user installs your tool via npm install, and then that tool copy some templates -- from your project folder -- into the user current working directory (among other things).
So your template files may be installed in a local node_modules installation or in the global one.
In both cases, you can access the absolute path to a resource given a relative path from your script file, via the path module:
const pathToResource = path.resolve('../templates/myTemplate.txt');
pathToResource will be the absolute path and will change from some users to others, depending upon they installed the module locally or globally.
I don't know if it's the best solution but I manage to retrieve the binary path by doing : path.resolve(require.resolve('my-cli'), '../', 'templates')
Source: https://github.com/nodejs/help/issues/388#issuecomment-264731257

Run Nodejs program that ignores parent node_modules

I have a library and I want to test it by doing a full install locally before publishing to npm. One of the things I want to test is if all the dependencies are part of the project. Because of how nodejs structures its module system though, (a nodejs module is searched for at every directory level) I do not have a good way to ensure that the module I am requiring came from the current folder's node_modules, and not the parent folder's node_modules.
Here is the project structure:
library-folder/
package.json
node_modules/
testing/integration/
package.json
node_modules/
test-install.js
I want to know if there is a way to tell nodejs to only require modules from the current directory, and ignore any parent directories.
I do not have a good way to ensure that the module I am requiring came from the current folder's node_modules, and not the parent folder's node_modules.
For that, you can use require.resolve and check the path it returns.
I resolved this issues by creating a file in the child's root project folder.
File's name should be called like this: .env
The content: SKIP_PREFLIGHT_CHECK=true

how to make webpack use shared node modules in the parent directory

I want to use shared node modules which is kept in the parent directory. I have the following folder structure:
parent directory
node_modules
company
serverless.yml
handler.js
webpack.config
I have to use webpack to create packages and upload into aws-lamda. But the webpack is looking for node modules. But I am getting the following error:
Overriding the webpack directory in serverless-webpack since it uses v1 version of webpack...
cp: cannot stat 'node_modules/webpack': No such file or directory
How can I make webpack.config point to the node_modules in the parent directory?
if you read the NodeJS require documentation you are highly encouraged to use local node_modules folders even if your packages require have the same dependencies.
https://nodejs.org/api/modules.html#modules_loading_from_node_modules_folders
Alternatively your can work with NODE_PATH , notice that require will first look into local node_modules then start looking into other folders so try to delete local node_modules
If the NODE_PATH environment variable is set to a colon-delimited list of absolute paths, then Node.js will search those paths for modules if they are not found elsewhere. (Note: On Windows, NODE_PATH is delimited by semicolons instead of colons.)
Since webpack exposes many module resolving options https://webpack.github.io/docs/resolving.html
Resolving a module path
For resolving a module Resolve first gathers all search directories for modules from Webpack’s context directory. This process is similar to the node.js resolving process, but the search directories are configurable with the configuration option resolve.modulesDirectories. In addition to this the directories in the configuration option resolve.root are prepended, and directories in the configuration option resolve.fallback are appended.

How to specify node_modules folder for locally referenced node module

We need to specify node_modules folder for locally referenced node
module that resides in an external folder relative to the current
application folder.
We have a scenario where we are referencing an external common module’s js files within another client-side app, however the same node modules being references in both are being duplicated in the final build. we have tried using webpack.optimize.DedupePlugin() without any success.
The directory structure is as follows:
We have a private npm module on the local disk called ‘common’, and then we have our project folder called ‘app’.
Both folders are on the same level in directory structure & are under the same root.
The ‘app’ itself is a npm module & has a package.json file with its own node_modules folder.
|—root
|— common/node_modules
|— app/node_modules
We want to specify via configuration either via npm or web pack a way for the app to resolve references from its specified path of node_modules and not to refer to any other node_modules location including the one in common module.
You can use npm link or just a simple symlink. Do something like that:
cd root/app (your app directory)
npm link ../common
OR
cd root/app (your app directory)
ln -s ../common node_modules/common

Resources