{"id":7862,"date":"2020-07-11T16:27:31","date_gmt":"2020-07-11T16:27:31","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=7862"},"modified":"2020-07-11T16:27:31","modified_gmt":"2020-07-11T16:27:31","slug":"creating-scaffolding-with-yeoman","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/creating-scaffolding-with-yeoman\/","title":{"rendered":"Creating scaffolding with yeoman"},"content":{"rendered":"<p><a href=\"https:\/\/yeoman.io\" rel=\"noopener noreferrer\" target=\"_blank\">Yeoman<\/a> is basically a tool for generating scaffolding, i.e. predefined projects (see <a href=\"https:\/\/yeoman.io\/generators\/\" rel=\"noopener noreferrer\" target=\"_blank\">generators<\/a> for a list of some existing generators). <\/p>\n<p><em>You could generate things other than code\/projects equally well using yeoman.<\/em><\/p>\n<p>There&#8217;s a fair few existing generators but you can also define your own generators and hence&#8230; Say for example you have a standard set of tools used to create your Node based servers, i.e. you want Typescript, express, eslint, jest etc. we could use yeoman to set everything up.<\/p>\n<p>Ofcourse you could create a shell script for this or a custom CLI, but yeoman gives you the ability to do all this in Javascipt with the power that comes from that language and it&#8217;s eco-system.<\/p>\n<p>Within a yeoman script, we can also interact with the user via the console, i.e. ask for input. Create templates for building code, configuration etc.<\/p>\n<p><strong>Installing the tooling<\/strong><\/p>\n<p>Before we start using yeoman we need to install it, so run either npm or yarn as shown below<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nnpm install -g yo \r\n<\/pre>\n<p>To check everything worked simply run<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nyo --version\r\n<\/pre>\n<p>At the time of writing, mine version is 3.1.1.<\/p>\n<p>Before we get onto the real topic of this post, lets just check out some yeoman commands <\/p>\n<ul>\n<li>Listing installed generators\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nyo --generators\r\n<\/pre>\n<\/li>\n<li>Diagnose yeoman issues\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nyo doctor\r\n<\/pre>\n<\/li>\n<\/ul>\n<p><strong>Creating our own generators<\/strong><\/p>\n<p>Okay so this is what we&#8217;re really interested in. I have a bunch of technologies I often use (my usual stack of tech.\/packages). For example, if I&#8217;m creating a Node based server, I&#8217;ll tend to use Typescript, express, jest and so on. Whilst we can, ofcourse, create things like a git repos with everything set-up and just clone it or write shell scripts to run our commands. As mentioned, with yeoman we can also template our code as well as interact with the user via the CLI to conditionally generate parts of our application.<\/p>\n<p>There appears to be a generator for producing generators, but this failed to work for me, but for completeness here it is<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nnpm install -g yo generator-generator\r\n<\/pre>\n<p>Now, let&#8217;s write our first generator&#8230;<\/p>\n<p>Run the following, to create our package.json file<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nyarn init -y\r\n<\/pre>\n<p>The first thing to note is, the generator name should be prefixed with <strong>generator-<\/strong>. Therefore we need to change our &#8220;name&#8221; within package.json, for example<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n&quot;name&quot;: &quot;generator-server&quot;\r\n<\/pre>\n<p>The layout of our files is expected to be a either (off of our root)<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npackages.json\r\ngenerators\/app\/index.js\r\ngenerators\/router\/index.js\r\n<\/pre>\n<p>OR <\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npackages.json\r\napp\/index.js\r\nrouter\/index.js\r\n<\/pre>\n<p>Whichever layout we choose should be reflected in package.json like this<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n&quot;files&quot;: &#x5B;\r\n    &quot;generators&quot;\r\n  ],\r\n<\/pre>\n<p>OR<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n&quot;files&quot;: &#x5B;\r\n    &quot;app&quot;,\r\n    &quot;router&quot;\r\n  ],\r\n<\/pre>\n<p>You might, at this point, wonder what the point of the <em>router<\/em> is, and whilst this is within the yeoman getting started guide, it appears ultimately any folder added alongside the app folder will appear as a &#8220;subcommand&#8221; (if you like) of your generator. In this example, assuming the app name is <em>generator-server<\/em> (see below) then will will also see that <em>router<\/em> can be run using <em>yo server:router<\/em> syntax. Hence you can create multiple commands under your main yeoman application.<\/p>\n<p>We&#8217;ll also need to add the yeoman-generator package before we go too much further, so run<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nyarn add yeoman-generator\r\n<\/pre>\n<p>So here&#8217;s a minimal example of what your package.json might look like<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n{\r\n  &quot;name&quot;: &quot;generator-server&quot;,\r\n  &quot;version&quot;: &quot;0.1.0&quot;,\r\n  &quot;description&quot;: &quot;&quot;,\r\n  &quot;files&quot;: &#x5B;\r\n    &quot;generators&quot;\r\n  ],\r\n  &quot;keywords&quot;: &#x5B;&quot;yeoman-generator&quot;],\r\n  &quot;dependencies&quot;: {\r\n    &quot;yeoman-generator&quot;: &quot;^1.0.0&quot;\r\n  }\r\n}\r\n<\/pre>\n<p><strong>Writing our generator code<\/strong><\/p>\n<p>In the previous section we got everything in place to allow our generator to be recognised by yeoman, so let&#8217;s now write some code.<\/p>\n<p>Here&#8217;s an example of a starting point from the yeoman website.<\/p>\n<p>In generator\/app\/index.js we have a simple example <\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nvar Generator = require(&quot;yeoman-generator&quot;);\r\nmodule.exports = class extends Generator {\r\n   method1() {\r\n      this.log('method 1 just ran');\r\n   }\r\n   method2() {\r\n      this.log('method 2 just ran');\r\n   }\r\n};\r\n<\/pre>\n<p>Sadly this is not using ES6 syntax, maybe I&#8217;ll look into that in a future post, but for now it&#8217;s not too big of a deal. There is a <em>@types\/yeoman-generator<\/em> package if you want to work with Typescript, but I&#8217;ll again leave that for another possible post.<\/p>\n<p>When we get to run this generator, you&#8217;ll find that both methods are run hence we get the following output<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nmethod 1 just ran\r\nmethod 2 just ran\r\n<\/pre>\n<p>All the methods we add to the Generator class are public as so are run by yeoman. We can make them private by prefixing with the method name with an underscore (fairly standard Javascript style to suggest a field or method to be private or ignored).<\/p>\n<p>The order that the methods appear is the order they&#8217;re executed in, hence switching these two methods around will result in <em>method2<\/em> running first, followed by <em>method1<\/em>.<\/p>\n<p>We&#8217;re not going to write any further code at this point, I&#8217;ll leave coding the generator for another post.<\/p>\n<p><strong>Testing our generator<\/strong><\/p>\n<p>At this point we don&#8217;t want to deploy our generator remotely, but want to simply test it locally. To do this we run the following command from the root folder of our generator<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nyarn link\r\n<\/pre>\n<p>This will create a symbolic link for npm\/yarn and now we can run<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nyo --generators\r\n<\/pre>\n<p>which should list our new generator, named <em>server<\/em>.<\/p>\n<p>Now we have our generator available to yeoman, we simply type<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nyo server\r\n<\/pre>\n<p>Obviously <em>server<\/em> is replaced by the name of your generator.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Yeoman is basically a tool for generating scaffolding, i.e. predefined projects (see generators for a list of some existing generators). You could generate things other than code\/projects equally well using yeoman. There&#8217;s a fair few existing generators but you can also define your own generators and hence&#8230; Say for example you have a standard set [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[45,284],"tags":[],"class_list":["post-7862","post","type-post","status-publish","format-standard","hentry","category-javascript","category-yeoman"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7862","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=7862"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7862\/revisions"}],"predecessor-version":[{"id":8427,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7862\/revisions\/8427"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=7862"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=7862"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=7862"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}