A week or so ago I finally got around to installing Node.js and started playing around in it. So far I liked what I saw, ie., till this weekend when I decided to grab Express.js and play with that. Now, I run Ubuntu (server edition) as a VirtualBox VM on my Mac OSX and primarily use it as LAMP stack for developing on WordPress. I installed Express.js globally via NPM for ease of use (since its dev environment & I like not having to install it for every project) and here came the first bummer. In NPM 1.10.0, the path where global Node modules are installed changed and Node is unaware of this change so far. 😮 So when I created the Express.js project and ran the
app.js, it threw up error as it couldn’t find Express.js module. Looking up on this revealed that NPM installed Express.js at
/usr/local/lib/node_modules/ which isn’t the place where Node.js looks for global modules. So the way to resolve this situation is to go into project folder and run the following command:
- sudo npm link express
This would make NPM create a symlink in the
<project-folder>/node_modules/ pointing to where it installed Express.js. But this command didn’t help. This was the second bummer. As it happens, my project folder is inside a shared folder which physically resides on host OS (in this case OS-X) and which is mounted in the guest OS (Ubuntu) by VirtualBox. And the global Node.js modules are installed on guest OS (the virtual HDD). Now, VirtualBox disabled creation of symlinks between guest and host OS in v4.1.8, which is why neither NPM can create the symlink nor can I sudo my way into it. I looked around & found a couple of probable solutions/workarounds to this VirtualBox issue, but none of them worked.
So my next step was to install Express.js in my project folder (I could’ve copied it from global install but I was in mood for more pain). This time being prepared for it, I wasn’t surprised when NPM failed to install Express.js in the project folder. Finally I copied Express.js and then ran
sudo npm install to install any dependencies. The project had only one more, the Jade templating engine. It ran through it and then on running
app.js the app gave a 500 error in browser as it was unable to find Jade even though it was there in project folder.
Eventually, I ended up doing this:
- cd ~/ #change to home dir in vm
- express <project_name>
- cd <project_name>
- sudo npm install express #install express locally
- sudo npm install #install any dependencies, at this point it'll only be Jade
- sudo mv <project_name> ~/<shared_folder>/<project_name>
I installed Express.js locally in the project folder because
npm install would’ve skipped over it as its already present in the global scope. Now we need it in global scope as well for its cli utility to create skeleton projects quickly.
All this work because VirtualBox has a stupid bug in guest => host symlinks and they decided to disable the feature, not to mention it hasn’t been fixed in 2 years now!! 😡
Another workaround to this would’ve been that I install Node.js on OS-X as well and create the project in the shared folder and then run it in the VM. But I’ve kinda stopped installing stuff like this on OS-X and I like to keep it all bundled in my VMs so as not to worry when I next update my OS-X. This is one reason PHP, Apache etc remain as they come by default on OS-X, I don’t modify them since I don’t use them.
While this workaround works for now, I think a better way would be to create project on guest OS fs, install any dependencies etc there while the app files would be on shared folder and
nodemon could be told to watch the folder in shared folder for any changes (besides the project folder on guest OS). The only reason I need app files in shared folder is to be able to edit them using my IDE of choice on OS-X. So if you don’t have that requirement then just keep everything on guest OS fs and everything would work smoothly.