A simple trick to make npm and yarn installs on Mac a bit less painful
One of the funniest and most overused memes of the JavaScript side of the Internet world is surely the one below.
If you’ve ever ventured inside a node_module directory of a medium sized project the (unknown?) author of this successful image clearly has a point.
For instance if you had to start a fresh project with Create React App and, just after running ‘npx create-react-app my-app’ you were to count the number of files you’d see something like this:
$ find ./node_modules -type f | wc -l
27032
Just like that, you gave over 27k new items to our friend Spotlight to index.
Now, I rarely use Spotlight other than to quickly open an app, and when I do this happens
Mac spotlight search be like:
— Bruno Lemos (@brunolemos) March 25, 2019
Me: Types a couple letters
Mac: Here's the exact app you want
Me: Awesome, let me just press enter
Mac: OR MAYBE YOU WANT THIS COMPLETELY UNRELATED THING
*opens completely unrelated thing*
But I digress. What’s important is that the fact I rarely use it doesn’t prevent Spotlight to crawl the content of my HD. As any other entry in the file system the content of node_modules gets indexed by Spotlight by default. I never really thought about this util I read the following tweet.
Does your Mac becomes slow/unresponsive (fans kicking in etc.) when you `npm install` a huge project with a million tiny dependencies? I learned that adding an empty `.metadata_never_index` in /node_modules *beforehand* will prevent Spotlight from indexing all that crap.
— Roel Van Gils (@roelvangils) April 2, 2019
This along with the fact that we may often run a command like rm -rf ./node_modules && yarn
means that Spotlight is potentially re-indexing this content multiple times a day.
With this newly acquired knowledge we can use a couple of tricks to avoid this issue and hopefully spare some wasted, memory intensive work to our machines.
For example, you can add a postinstall block to your package.json scripts so that it will be invoked in the background whenever you install the dependencies of your project.
{
//...
"scripts": {
"clean": "rm -rf ./build",
"start": "node index.js",
"postinstall": "touch ./.metadata_never_index" // <--
}
}
This is nice and easy but you will need to do the same for all your projects, plus it will run for everyone else using that package.json, even if not on a Mac.
To have a similar functionality available everywhere on your Mac and without touching the package.json you can add this to your ~/.bash_profile
or ./zsh_profile
.
# open your profile with `vim ~/.bash_profile`
# and paste the function below
function npmi {
mkdir node_modules 2>/dev/null
touch ./node_modules/.metadata_never_index
if [ -f yarn.lock ]; then
yarn install $@
else
npm install $@
fi
}
Running npmi
on the root of any node project will add the .metadata_never_index
file automatically, just before installing the dependencies.
Finally it may be useful to just do the same for all existing projects on our file system.
find . -type d -name "node_modules" -exec touch "{}/.metadata_never_index" \;
This was suggested on Yarn’s Github in a comment to this issue and it seems it appeared first as far back as 2016 in a StackExchange answer.
Hopefully this simple trick will save us a bit of time (and battery power!) in the future.