How to distribute dependencies in package.json? - node.js

So I'm building a Front End application based on React. There'll be different packages serving as libraries and exporting components. These components will then be imported into the main package and routed according to need.
Now for the package(s) serving as libraries; I'm trying to understand how to distribute the dependencies between dependencies, devDependencies, and peerDependencies in the package.json file.
Should I be putting everything in dev and peer? Or do things like lodash / babel etc. need to be put in dependencies? Any such best practices; or list of dependencies would be helpful

About dependencies and devDependencies
Dependencies
"dependencies": Packages required by your application in production.
In dependencies you put everything that is imported in your application or needed in some way in the final application, e.g: react, axios etc.
devDependencies
"devDependencies": Packages that are only needed for local development and testing.
In devDependencies you put only things that are used to build your application, eg. webpack, eslint etc.
peerDependencies
You can read about peerDependencies here
You won't use them unless your project is a library.
Questions:
Should I be putting everything in dev and peer?
No, it's safer to put everything in dependencies if you don't know where to put it.
Or do things like lodash / babel etc. need to be put in dependencies?
No, lodash should be in dependencies, because, you are using it in your website. babel on the other hand is used only in built time, so it should be in devDependencies.

Related

Is there a way to tell NPM NOT to use globally installed packages during a build

We work in a large team on multiple projects and everyone has a different set of node packages installed globally.
This can cause different behaviour when different members of the team build a project.
Is there a setting in a package.json file (or other file) that we can apply that forces NPM to only use local packages that have been installed in the local project node_modules.
I assume that this is more relating to development tools and modules (netlify, standard, prettier, #babel/core, rollup, eslint, etc)
Using npm i --save-dev package-a package-b package-c to ensure that you have the exact and correct versions across your development teams. I would suggest looking at package.jsons in projects like three.js, react, nextjs etc to see how they handle it. It can be quite a task to get a correct baseline of devDependencies, but once set, it generally solves a lot of package dependency problems caused by global modules.
See this: http://npm.github.io/how-npm-works-docs/npm3/how-npm3-works.html

Lerna. Install dependencies to root project

I have standard Lerna repository like this:
my-repo
- package.json
- packages
- api
- package.json
- web-app
- package.json
If I need same dependency in both packages (for example lodash), then people in tutorials suggest to install it to both sub modules and then bootstrap project with with lerna bootstrap --hoist flag.
Because of --hoist flag lodash dependency will be loaded only to root level node_modules but both sub-modules will contain it as dependency in their appropriate package.json
But Node’s package resolution algorithm searches up the file tree looking for node_modules folder.
So my question is why I can't just install common dependencies to root level project? Then lodash will be located under root's node_modules. And sub-modules (packages) will find it because Node will search up for node_module until the root of the file system is reached.
At least it will help me to avoid using uncommon lerna bootstrap --hoist, as well as lodash dependency will be present only once at the top level package.json (and not twice: in package.json of both submodules)
So my question is why I can't just install common dependencies to root
level project?
You can, and you're right, node's resolution algorithm will find the shared dependency fine.
The downside of doing this is that you lose flexibility, and you would need to deploy or work with the whole mono-repo which might be fine for you. A more traditional approach is to keep production dependencies in the sub packages so that you can publish the packages and use them individually without depending on the root of the monorepo, but again, this might not be important for you.
If your packages are npm packages that you intend to reuse by publishing to some npm registry, then you should give them proper package.json dependencies.
A package should always list what it requires to operate. E.g. if your "api" package requires lodash at runtime, then it MUST have lodash in its dependencies. Otherwise an app could install it without lodash; then it would fail to run.
In your lerna repo, your "root" package.json is not connected to any npm package, and is not published, so it doesn't affect your "real" npm packages: "api" and "web-app".
Finally, if you don't intend to publish your packages as npm packages, then do whatever you want. Lerna is probably overkill in that case. Even the package.json is overkill, because it's just being used for its scripts.

Install the dev dependencies of my dependencies

I have a monorepo where I have a /packages folder with many packages.
I can use npm i ./packages or npm i if they are already specified using using the file pointer.
Looks something like this:
"dependencies": {
"#reggi/command": "file:packages/command",
"#reggi/dep-merge": "file:packages/dep-merge",
"#reggi/dep-merge-cli": "file:packages/dep-merge-cli",
"#reggi/dep-pointer": "file:packages/dep-pointer"
}
The issue is that if I install these packages I don't get dev dependencies.
What I really want is to also install the devDependencies of these dependencies.
lerna a popular tool that has pioneered the usage of monorepos, suggests that you should add all the devDependencies for these packages in the root package. The issue with this is that it eliminates the ability for two packages to depend on different versions of a given dev dependency.
What I have done is created a script that merges all the devDependencies into dependencies at preinstall then undoes the changes. This works but can be kind of wonky at times, especially when explaining all this to shrinkwrap.
It would be nice if I could just npm i --allDevDepsFromDeps and it would install all of my dependencies dev dependencies.
Is there any other solution I am missing?
I don't see what you're trying to achieve there, aren't the devDepencies used for ... development?
If you want different version for different package just don't put them in the root but in each package.
The issue is that if I install these packages I don't get dev dependencies.
You should consider those packages as 'production'/'bundled' packages, you don't need dev dependencies in this case.
For example, when you are working on #pkg/A, it will have its own devDep but then if you work on #pkg/B that depends on #pkg/A, the #pkg/A should be the production/bundled version (without devDeps).
Maybe you should have a look at bundledDependencies or peerDependencies, that might help you.

Where to put package in package.json? dependency or devdependency

Just a short question.
I develop a api in node & express where i need the package request for my tests and for the api logic itself. Should i put it in the normal dependencies or in the dev dependencies. Or even in both of them? Thx.
In general, dependencies is used for packages your package depends on to run (and be used), whiledevDependencies for packages needed to develop it.
In your case, dependencies sounds right.
Anyway, when developing an app it is mostly for semantics - this only really matters when developing libraries and reusable components.
it seems to be ok, to add it to the dependencies as well as to the devDependencies. So now "npm install --dev" installs only the dependecies for the tests and "npm install" installs everything.

Many unknown modules in node_modules folder

I am new to nodejs. And I found that there are many unknown modules in node_modules folder after I installed three modules (express, jade, gulp) in my local project.
Unknown module examples in the node_modules:
vary
statuses
send
promise
From the tutorials I see from others, after they installed gulp, there will be only one "gulp" folder in their node_modules folder, but this is not my case. Why? Thank you.
The node package manager (npm) updated recently, as part of that update, all modules are installed in the top level node_modules folder. This includes modules that your dependencies need to install. In the past these modules would be nested inside another node_modules folder in express (for example).
This is why the tutorials you read say different, likely they were written before this update.
It is mentioned in the npm changelog here
Your dependencies will now be installed maximally flat. Insofar as is
possible, all of your dependencies, and their dependencies, and THEIR
dependencies will be installed in your project's node_modules folder
with no nesting. You'll only see modules nested underneath one another
when two (or more) modules have conflicting dependencies.
#3697 This will hopefully eliminate most cases where windows users ended up with paths that were too long for Explorer and other standard
tools to deal with.
#6912 (#4761 #4037) This also means that your installs will be deduped from the start.
#5827 This deduping even extends to git deps.
#6936 (#5698) Various commands are dedupe aware now. This has some implications for the behavior of other commands:
npm uninstall removes any dependencies of the module that you
specified that aren't required by any other module. Previously, it
would only remove those that happened to be installed under it,
resulting in left over cruft if you'd ever deduped. npm ls now shows
you your dependency tree organized around what requires what, rather
than where those modules are on disk.
#6937 npm dedupe now flattens the tree in addition to deduping. And bundling of dependencies when packing or publishing changes too:
#2442 bundledDependencies no longer requires that you specify deduped sub deps. npm can now see that a dependency is required by something
bundled and automatically include it. To put that another way,
bundledDependencies should ONLY include things that you included in
dependencies, optionalDependencies or devDependencies.
#5437 When bundling a dependency that's both a devDependency and the child of a regular dependency, npm bundles the child dependency. As a
demonstration of our confidence in our own work, npm's own
dependencies are now flattened, deduped, and bundled in the npm#3
style. This means that npm#3 can't be packed or published by npm#2,
which is something to be aware of if you're hacking on npm.

Resources