I'm currently building a Yeoman generator, and although I seem to have mastered the basics, I'm struggling to figure out how to include various dependencies only when the user chooses to include them.
After looking at some existing generators, I've worked out that a checkbox prompt is the standard way of allowing users to select which dependencies they'd like to include in their new app:
var prompts = [{
type: 'checkbox',
name: 'features',
message: 'What more would you like?',
choices: [{
name: 'Sass',
value: 'includeSass',
checked: true
}, {
name: 'Bootstrap',
value: 'includeBootstrap',
checked: true
}, {
name: 'Modernizr',
value: 'includeModernizr',
checked: true
}]
}];
From here on in though, I'm stumped. What I'd like is to allow users to choose what dependencies they'd like to include both using bower, and NPM (through the package.json file).
How would I go about doing this?
Thanks in advance for any help!
Making sure to only include the dependencies the user needs is a good practice!
The easiest way - and also the way the official generators do it - is to make the package.json
you're generating a template. The template can then include arbitrary conditions to mix and match the packages you need.
The first step is to export the answers from the prompt, so they're available in the template:
this.prompt(prompts, function (answers) {
var features = answers.features;
function hasFeature(feat) {
return features && features.indexOf(feat) !== -1;
}
this.includeSass = hasFeature('includeSass');
this.includeBootstrap = hasFeature('includeBootstrap');
this.includeModernizr = hasFeature('includeModernizr');
}.bind(this));
The template for the example would then look something like this. The <% ... %>
syntax is actual JavaScript and is executed before the result is written to disk.
templates/_package.json
{
"name": "<%= _.slugify(appname) %>",
"dependencies": {
"my-dependency-a": "^0.4.5",<% if (includeModernizr) { %>
"modernizr": "^0.11.0",<% } %><% if (includeBootstrap) { %>
"bootstrap": "^3.3.4",<% } %>
"my-dependency-b": "^0.5.0"
},
"engines": {
"node": ">=0.10.0"
}
}
Back in your generator code, make sure to generate this file from the template:
packageJSON: function () {
this.template('_package.json', 'package.json');
}
And as a final step, you want to actually run npm install
in the generated directory. There's a helper available for Yeoman, that does this for you:
this.on('end', function () {
this.installDependencies();
});
If you look at the generator-webapp code that does this, there are a few more subtleties to handle cases where the user might not want to install the dependencies automatically and special handling for test frameworks. But for the case you describe, the above is completely sufficient.
I hope this helps. :)