In the world of web development today it’s hard to stay updated with the ever increasing amount of new modules, libraries and packages that are released each day. What’s hot today can be forgotten tomorrow.
One way to be sure that you are using state of the art techniques is to use a scaffolding tool when building new apps/packages. With a scaffolding tool you can also get help when upgrading an existing project that has already been generated with the tool.
The most popular scaffolding tool today is Yeoman and it has a huge amount of project generators. To save time when setting up new projects I decided to create a Yeoman generator of my own – generator-klei which is a MEAN stack (MongoDB, ExpressJS, AngularJS and NodeJS) app generator. At first it was a great experience and I was really satisfied with the generator, that was until it had to be maintained.
Maintaining Yeoman generators
Maintaining a Yeoman generator and trying to keep it up to date with new best practices and any new and improved Grunt plugins is time consuming and not as easy as I’d imagined. The Yeoman generator API is not intuitive enough for me, at least because I’m not using it every day. The Gruntfile is even harder to maintain in my opinion. This is because it is hard to maintain a big Gruntfile while trying to follow the DRY and KISS principles.
When I saw Gulp for the first time and learned how you structure a Gulpfile I felt that it offered a much more intuitive and “easy to keep DRY” alternative to Grunt. This feeling was verified when I started to use it. When rewriting the functionality in generator-klei’s Gruntfile for Gulp, I was able to shave off half of the code right away, and it was easier to understand as well. Less code and more understandable code means less time consuming maintenance, which was just what we needed.
The idea of replacing Yeoman is born
I was wondering, what if Yeoman could be replaced by something similar that was simpler, as well as being easier to write and maintain?
I saw many similarities between what Yeoman does and what Gulp can do, which is mainly: take some source files (gulp.src), process them with a template engine (e.g. gulp-template) and write them to a destination (gulp.dest). It is also possible to prompt the user for project options like Yeoman does from within a Gulpfile too by using the inquirer module directly.
Yeoman also installs project dependencies, using Bower and Npm, after project generation. To get the same functionality from Gulp, I created the gulp-install plugin, which does exactly that. Another good feature of Yeoman is that it prompts the user before overwriting any files when rerunning the generator in the same directory twice, a feature I have replicated in the gulp-conflict plugin.
By leveraging these additional plugins, I now had the ability to create a Yeoman like generator using pure Gulp. What was still needed, though, is a tool that discovers all the installed generators and allowed the user the ability to run a specific one.
The result of all of this work is Slush. It is the new scaffolding tool on the block, and, in the true spirit of Gulp, it is a streaming scaffolding system. Slush offers a CLI that will find all of your globally installed “Slush generators” (i.e. a project generator built using Gulp instead of Yeoman) and it gives you the ability to run them in the current working directory to scaffold out new projects.
Slush generators and their Slushfiles
As I mentioned a Slush generator is a Yeoman-like project generator built with Gulp. It uses a Slushfile (slushfile.js) instead of a Gulpfile. They are built in the same way, though a Gulpfile is meant for local use and the Slushfile is intended for global use.
A Slush generator should follow the convention of having a name prefixed with “slush-” and have “slushgenerator” as a keyword in its package.json.
Existing generators can be found at the Slush homepage, and new generators that are published to npm and follow the rules above are automatically added to the list.
Go ahead and create your own! If you’ve written a Gulpfile then you should have no difficulties getting started, if not or you need some help take a look at the Gulp documentation first. Then reference my first post about Slush or an existing Slush generator for inspiration.
Running a Slush generator
To get started with Slush, first you need to install Slush globally:
npm install -g slush
Next, install your generator of choice, for example slush-angular:
npm install -g slush-angular
The installed generator can now be run with:
slush angular, which will trigger the “default” task within slush-angular’s Slushfile. To run another task (think Yeoman subgenerators) the syntax is:
A generator might take some arguments as well which then should be provided as:
slush slush <generator>:<task> arg1 arg2 "long arg3"
To list installed generators just run
slush without any parameters. To see available tasks within a generator run:
slush <generator> --tasks.
That’s Slush. In a few steps, thanks to Gulp, I’ve managed to recreate the functionality of Yeoman in a modular and, in my opinion, more maintainable way. With Slush you don’t have to learn how to write both generators and taskrunner files, just learn Gulp and you’re good with both. I am already using Slush instead of Yeoman and I hope you’ll try it as well!
The future of Slush
The core of Slush itself probably won’t change that much. Instead the focus will be on the testability of Slush generators. I’m planning on developing an npm module which will be used in tests to replace
gulp.dest for easier testing and verification of a generator’s functionality. A good mock for the inquirer module is also needed.
Do you have any ideas or want to help? Let me know!
Brian has published in a variety of technical publications over the years, has presented at numerous conferences and events and has served as a technical editor on a number of books.
You can read Brian’s blog archive with 9+ years of content at remotesynthesis.com (he still posts, infrequently). You can find a full list of Brian’s past publications and presentations. Follow Brian on Twitter @remotesynth.