By Joakim Bengtson
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.
Presenting Slush
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:
slush <generator>:<task>
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
.
Conclusion
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!
I’ve now released a module for mocking `gulp.dest`: https://www.npmjs.org/package/mock-gulp-dest to ease testing of Slush generators.
Been using Grunt and Yeoman’s for quite a while now, and have been sporadically reading about gulp without great interests. I wasn’t seeing clear benefits of jumping from Grunt to Gulp, especially with the amount of Grunt plugins available.
After reading that article it kind of convinced me to take a (bit) deeper look into Gulp and to try Slush.
I just fiddled with your Angular Generator, and while it does pretty much the same things as Yeoman’s Generator, I can appreciate the freshness of it and the impression that the gulp file is indeed a bit easier to read/understand than Yeoman’s Gruntfile
That’s more of a Gulp question but I’ll ask:
In Grunt’s UseMin tasks, you can override/add the “main” property of the bower.json files of bower components, mostly useful if a package is missing the “main” property in it’s bower.json file. Is there an equivalent in Gulp?
A quick thing too:
I noticed that in your Angular Generator, the app.js doesn’t pass the JSHint verification as it’s missing the ‘use strict’ statement
Then it should then be wrapped in a closure:
(function() {
‘use strict’;
[…]
})();
I am definitely looking forward to see these projects mature, thanks for your hard work!
Thank you for your comment!
Good catch. Will have to fix that in the generator.
About overriding bower components’ main property, that is possible thanks to the gulp-bower-files plugin, which IMO is a correct place for the functionality instead of within a usemin plugin.
Great Article! After working with grunt I fell in love with gulp immediately and this looks very promising. Look forward to learning more.
Your link to slush is borked. Looks like you have made it an org and such?
https://slushjs.github.io/