Can I review which node_modules I need? - javascript

Is there a way to review which node_modules packages are used in my create-react-app project and delete modules which are not in use? Other than manually reviewing all used packages and their dependencies?
I'd like to reduce the amount of space used up by the project. It's committed to a resources repository, and the node_modules folder alone triples the space used.

For repo size (assuming you're using git):
git rm -r --cached ./node_modules
Add the line /node_modules to your .gitignore file
git add .
git commit -m "Remove node_modules from repo"
For build size:
create-react-app is pretty good at tree shaking, so you shouldn't need to worry too much about this. Certain packages may have more modular ways of importing, which can help - usually these will be documented on a package-by-package basis. For example, Material UI icons supports two import syntaxes:
// option 1
import AccessAlarmIcon from '#material-ui/icons/AccessAlarm'
import ThreeDRotation from '#material-ui/icons/ThreeDRotation'
// option 2
import { AccessAlarm, ThreeDRotation } from '#material-ui/icons'
Of these, option 1 is likely to yield the smallest bundle size.
For size on your development machine:
The biggest difference you can make here (assuming you have other projects) is probably switching to something like pnpm, which stores node_modules centrally on your local machine and then links out to them from your project, rather than having many instances of identical modules.
For general housekeeping and tidiness:
You could try using a tool such as depcheck to detect unused dependencies. This is probably overkill, though, unless it's a particular pain point for your project.

Probably the easiest way is not to include the node modules by adding it to the gitignore file (or creating one), but if that's not an option, probably just unsintall the unneeded packages

Related

Sharing configs in multi module javascript project

Let's say we have a project with lots of sub-packages:
👩‍🍳 project root
🍔sup package a
package.json
tsconfig.json
webpack.config.js
🍟 sub package b
package.json
tsconfig.json
webpack.config.js
This kind of structure most likely contains lots of redundancies, in both, settings and dependencies. I would like to have a way to manage these common settings and dependencies in a centralized way.
For example:
If a new sup package 🌮 is added, it would be nice, if common settings could be inherited from some kind of a centralized setting-thingy
If the version of a dependency, that is used in several sub packages, is changed, I would like to have a way to change the version at some central point, so that all sub packages "see" the new version.
I would like to change a property in all tsconfig.json's in one step, instead of editing all tsconfig.json's manually.
🤩In essence, I want to apply the DRY-principle to a project configuration.
I looked into npm workspaces, lerna, yarn, webpack, but didn't find anything that would do all of that. How could this be achieved?
🙄In Java, I would come close to this using Maven. There I could at least manage the versions of my dependencies in a central config. Isn't there something like that in the JavaScript universe?

Must i specify dependencies in package json file

I just recently heard of the package.json file but all my small projects have always worked without it.
I've installed many npm modules globally and always use var x = require("express");"just for example" without even initializing the package.json and putting express as a dependency.
Is it really important
First of all, I strongly doubt require("express") will work out of the box without having the express package installed in your project's node_modules folder, but just globally. There are ways to accomplish this, though.
But even if you accomplished to require packages from the global installation folder, what happens if you have multiple packages requiring different versions of the same package? There may be breaking changes between major versions of packages. So if you install a new version of package xy globally, older projects of yours expecting a different version of package xy may stop working.
On just your local machine, you can achieve all that, still without a package.json though.
The main purpose of the package.json comes clear, when you want to share your project with other people. Aside from some basic information (like a package name and some description), it will also list the dependencies which need to be installed for the project to be runable. While the necessary dependencies may exist on your machine, how will you make sure, they are also installed on a different machine without having them listed somewhere? And the place for listing the dependencies of a package is -- surprise surprise --- the package.json file ...
They are global, not in your project so when you do the deploy, you will must have to install all global for each server.
Yuu can install packages-cli global, but project dependencies ( also dev on dev dependencies) is better have its own package.json so you can deploy.
Also if you share your project, how someone will know what packages is needed.
The better is to have for each project its own package.json on its root folder, even if you always use the same libs.

Why do we need multiple node modules folders inside each project?

I'm new to JS development and was wondering given that the size of node modules is an issue of concern where one has to even go on deleting the folder when many projects pile up and is not used, why can't we have a global node modules folder, like m2 for maven and then reference it in our projects?
Why do we need multiple node modules folders inside each project?
You can install packages globally and use them with the -g flag when using npm install.
But this isn't done often, and often isn't recommended, because the same package can have many, many different versions. SomeLibrary version 5.6.1 can be significantly different from SomeLibrary version 5.7.1. If you have multiple projects, they'll very often have different dependencies, and different dependency versions. If you try to source them all from the same global install, you'll usually run into problems very quickly. Having a separate node_modules folder for each project solves this problem for you; often, package versioning for each project you have will "just work" without any extra configuration.
There are also managers like Yarn which can cache package downloads, so you don't re-download huge numbers of duplicate megabytes over multiple projects
Variety of reasons. Just FYI, you can install npm packages globally using the -g flag when installing.
Here's some reasons:
Different project may require different versions of a package.
A single machine can consist of multiple different environment, i.e
containers or virtual machines.
Sharing code between projects/environments introduces potential security risks.
For the above reasons, and others, you might not actually want a projects
packages to leave the scope of that project.
since java script is not compiled, we will need to have all the plugins in each deployment verses maven is compiled so we can compile it to machine code with the plugin globally installed

Is there any way to reorganize node_modules?

There is big and deep node_modules directory. And there are many sub-folders with the same modules that are located in different subdirectories. Sometimes the same versions of the modules, there are sometimes differences in minor versions.
Is there a tool for reorganization of node_modules to remove duplicates, put them in the root directory and somehow still a bunch of modules to optimize this?
The NPM hierarchy is actually fairly complex and they've done a lot of work to optimize it. The most you're losing here is a little disk space. If you really need to prune the package structure for your app then you can take a look at npm dedupe which is built right into npm and does exactly what you're asking for (consolidates duplicates as much as possible).
I know a lot of people are against checking in node_modules directory but in production applications we've found that checking in node_modules makes it so much easier to pin down fatal changes in our application. Sure you usually know that your application broke after the last npm update but if your app is rather large like ours is then that simply isn't granular enough to solve problems quickly and efficiently. So in large production applications (i.e. not libraries being published to NPM) I use npm dedupe to simplify the package structure before checking them in.
If you're writing code that others will consume (via NPM or otherwise) then checking in node_modules isn't the best idea and you should avoid doing so by adding node_modules to your version control system's ignore list. You should also make sure you're dependencies in package.json are specific version numbers with as few ranges as possible (please don't put asterisks in place of the version numbers in your production apps :/).
If you follow those basic patterns then you can just forget about the node_modules directory and let npm take care of you.

What is the perfect workflow to work on A, B & C in parallel where A depends on B and B on C?

I wonder what is the perfect workflow if one needs to work on project A, B and C in parallel where A depends on B and B depends on C.
Currently I have everything in one repository which speeded up the early development. So my working directory looks like this:
/A/
/A/B
/A/B/C
So A is the project that is driving the development but it also means B and C are in parallel evolvement.
However, I want to release the projects B and C individually as well as they are quite useful for others.
However, I'm torn on how to do this without ruining my development speed. npm is great for distribution and dependency management but during development you definitely don't want to move temporally versions across the internet just to get the files to update in a different folder on your machine :)
On the other hand you also don't want to manually copy them over. Heck, all this I have to switch directories to work on B and now copy it over to /A/B is scary and seems error prone.
So, git submodule seemed like the answer as it's essentially enabling exactly that: You would keep your directory layout just as it is. Then when you make changes to files in B you can directly test them out in A without having to copy something over. And when you think it's ready you can just commit and push from the three different folders. Everything goes into three different repositories automatically. Seems like heaven yet everybody hates git submodule for various reasons.
I have pretty much the same problem when working on grunt plugins. I have the grunt plugin in it's own repository and then when I'm working on it I have to copy it over in one of the projects where I use it to drive the development. And then at the end of the day I copy it back to the grunt plugin working directory, make commits and push them. Thank god, I'm not the author of thousands of grunt plugins so I can deal with that but for this project I'm currently working on, I would definitely like to find a better solution.
So I wonder, what is the answer?
Note that Git submodules point to a specific version of the external repository, i.e. to a specific commit.
To update all Git submodules to the latest version, you’d still have to run a command:
git submodule foreach git pull origin master
Depending on your situation, you could possibly use npm instead of Git submodules. In that case, you simply list your dependencies in package.json, then run npm install in the root of the repository to fetch them. If a dependency is updated and a new version is published, you just run npm update again and it will match the version requirements set in the package.json file. You could also use npm to point to a specific commit, much like how Git submodules work:
{
"devDependencies": {
"dependency-a": "git://github.com/the-user-name/the-project-name.git#b3c24169432a924d05020c85f852d4a1736e66d4"
}
}
Or, if you want to use a bleeding edge version of a dependency, like the master branch of a given Git repository, you could use:
{
"devDependencies": {
"dependency-a": "git://github.com/the-user-name/the-project-name.git#master"
}
}
I've tried all number of these workflows and have decided that git submodules are not the answer. The main reason for me being that they couple projects together at a scm level and it is not intuitive as to where exactly in the revision history this coupling happens. Especially in a detached head scenario.
I rely on npm for depency managment with a combination of npm link and git URLs. npm link is great when I want to test something locally. git URLs are perfect to resolve dependencies during pull requests. Eventually I always want a published module with a version number I can match to a git tag for future reference and issue tracking. I use npm version to do this in one step. Allows for projects to depend on each other at varying levels of coupling during my development cycle.
Would using git subtree be the answer here? This article Alternatives To Git Submodule: Git Subtree did a good job explaining the pros and cons of using git subtree versus git submodules.

Categories