Yeoman generators, the file system and symlinks.
I write and maintain a Yeoman generator called “Build A Banner”, aka BAB.
As you might guess from the title, the generator helps in developing animated display ad banners. It creates a directory with customized HTML, JS and CSS starter files, builds a small development server with live-reloading, and has workflows for optimizing and delivering banners to a media company. We use it all the time at JMX2.
Although I’ve been maintaining this repo for years, I have just recently decided to pay attention to how my local generator (i.e. my work in progress version of BAB) and the global generators I’ve also got installed exist within my file system.
A quick primer
Before I dive in, let’s talk about Yeoman quickly. Yeoman is a node package that helps scaffold out projects. What kind of projects? Well, in the case of BAB, the project is building an advertising banner. Another project I scaffold out regularly is building a plugin for Craft CMS. A friend of mine maintains a generator for it called “generator-craftplugin” and it does that exactly. There are all kinds of generators and you can find them at the Yeoman Generator Discover page.
Global node modules
Let’s assume you’ve read the instructions on how to install Yeoman. How do you install generators? Generators are node modules, so you install a generator just like you’d install any node module. Typically you install them globally from the command line like this. (I say “typically” because Yeoman has a built in install a generator feature as well. I don’t use this though.)
To install the current public version of BAB globally, you’d use this command on your command line:
npm install -g generator-buildabanner
To install the current public version of generator-craftplugin globally, you’d use this command on your command line:
npm install -g generator-craftplugin
The -g
is the flag telling npm to install globally.
Local node modules
If the -g
flags wasn’t there, you’d be installing it in a node_modules
subfolder of the directory you’re currently in while in your Terminal. Your module wouldn’t be globally available though, and we need our Yeoman generators to be available anywhere on our computers since we will scaffold out projects in many locations.
You will probably not want everything to be global though. For example, if you wanted the Flickity javascript library installed into your web dev project, you’d want that library to be in your local directory. You’d run the following, with a --save
flag, so you can keep track of it in a package.json file.
npm install flickity --save
You’d see a node_modules
directory created (if it wasn’t there already) and the Flickity files would be inside of it.
Where Yeoman generators live
Let’s get back to Yeoman now. Now that those global Yeoman generators are installed, you might wonder where they exist on your local file system. They are global node modules so they’ll be installed alongside your other global node modules. Ok, where is that? Well, follow me down the rabbit hole.
There are several ways to install Node. The normal way you would install it would be to follow the instructions on the Node JS site. Why would you not follow those instructions? There are many versions of Node. Node is also updated regularly. Sometimes you need a version of Node that is different from the current stable version.
There is a script called Node Version Manager, aka NVM, that helps you install multiple different versions of Node and easily switch between them as you need to. That’s how I’ve got Node installed.
If you’ve followed the official Node directions, your modules are probably installed in either /usr/local/lib/node
or /usr/local/lib/node_modules
.
If you’re using NVM like I am, your modules are installed somewhere like this:
/Users/john/.nvm/versions/node/v10.5.0/lib/node_modules
That path shows you that I’ve got Node 10.5.0 installed and have a node_modules director for that installation of Node.
Check your generators and their version number.
In my case, you can see I’ve got BAB installed. I find I need to check the version of the generators I have installed regularly. The following rather obscure command is how you do that. I have it saved as a text snippet on my machine since I can’t remember it easily.
npm ls -g --depth=1 2>/dev/null | grep generator-
Here’s what that shows for me.
I’ve got version 0.10.4 installed. That’s the old version of BAB and I want my version in development on my local machine to be shown instead.
Using a local generator globally
So far, so good. Here’s where it might get a little tricky. It’s not too bad though.
For my BAB project, I want it available globally, but I need it somewhere else on my file system so I can work on updating it regularly. I keep it here:
~/git/generator-buildabanner
I go to that directory using a terminal program and link that directory using NPM. (Note: Be warned if you’re playing along here before getting to the end. This will remove your globally installed version entirely. You will need to re-install after you’re done.)
npm link
Now let’s check the version of the installed generators again.
Notice the screenshot above. The generator version number is followed by an arrow indicating that it’s pointing to a location to somewhere on the local machine other.
If I navigate to the global node_modules directory, I’d see the previous version of generator-buildabanner
has been replaced by a symlink. In the Mac Finder it looks like an alias link. The small arrow on the folder indicates it’s actually pointing to a different location on your file system, but Node will still use it.
Removing a symlink
If you need to get rid of that symlink, there’s an easy to do it. Navigate back to the location of your locally built project. In my case, that’s ~/git/generator-buildabanner
. Enter this unlink
command.
npm unlink
Poof. The symlink is gone. The original version of the generator is also gone now. The link command overwrote it with the local copy. If you need to reinstall it globally in the normal way you’d install a global node module.
npm install -g generator-buildabanner