<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Mark Goodyear — Front-end developer and designer</title>
    <description>I'm Mark Goodyear, a front-end developer and designer. Creative director at Big Bite Creative.</description>
    <link>http://markgoodyear.com/</link>
    <atom:link href="http://markgoodyear.com/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Wed, 15 Nov 2017 00:10:57 +0000</pubDate>
    <lastBuildDate>Wed, 15 Nov 2017 00:10:57 +0000</lastBuildDate>
    <generator>Jekyll v3.6.2</generator>
    
      <item>
        <title>Polling with Redux</title>
        <description>
</description>
        <pubDate>Mon, 06 Nov 2017 00:00:00 +0000</pubDate>
        <link>http://markgoodyear.com/2017/11/polling-with-redux/</link>
        <guid isPermaLink="true">http://markgoodyear.com/2017/11/polling-with-redux/</guid>
        
        
      </item>
    
      <item>
        <title>Using ES6 with gulp</title>
        <description>&lt;div class=&quot;callout  callout--info  callout--small&quot;&gt;
  &lt;em&gt;&lt;strong&gt;Nov 2nd, 2015&lt;/strong&gt;&lt;/em&gt;&lt;br /&gt;
  &lt;ul class=&quot;callout__list&quot;&gt;
    &lt;li&gt;
      As of node 4, we're now able to use ES2015 without the need for Babel. However modules are not currently supported so you'll need to use `require()` still. Checkout the &lt;a href=&quot;https://nodejs.org/en/docs/es6/&quot;&gt;node docs&lt;/a&gt; for more info on what's supported. If you'd like module support and to utilise Babel, read on.
    &lt;/li&gt;

    &lt;li&gt;
      Post updated to use Babel 6.
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

&lt;p class=&quot;lead&quot;&gt;With gulp 3.9, we are now able to use ES6 (or ES2015 as it's now named) in our gulpfile—thanks to the awesome Babel transpiler.&lt;/p&gt;

&lt;p&gt;Firstly make sure you have at least version 3.9 of both the CLI and local version of gulp. To check which version you have, open up terminal and type:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;gulp &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This should return:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;CLI version 3.9.0
Local version 3.9.0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you get any versions lower than 3.9, update gulp in your &lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt; file, and run the following to update both versions:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;npm install gulp &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm install gulp &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;creating-an-es6-gulpfile&quot;&gt;Creating an ES6 gulpfile&lt;/h3&gt;
&lt;p&gt;To leverage ES6 you will need to install Babel (make sure you have Babel 6) as a dependency to your project, along with the es2015 plugin preset:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;npm install babel-core babel-preset-es2015 &lt;span class=&quot;nt&quot;&gt;--save-dev&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Once this has finished, we need to create a &lt;code class=&quot;highlighter-rouge&quot;&gt;.babelrc&lt;/code&gt; config file to enable the es2015 preset:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;touch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;babelrc&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And add the following to the file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;presets&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;es2015&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We then need to instruct gulp to use Babel. To do this, we need to rename the &lt;code class=&quot;highlighter-rouge&quot;&gt;gulpfile.js&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;gulpfile.babel.js&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;mv &lt;span class=&quot;s2&quot;&gt;&quot;gulpfile.js&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;gulpfile.babel.js&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can now use ES6 via Babel! An example of a typical gulp task using new ES6 features:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;s1&quot;&gt;'use strict'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'gulp'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sass&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'gulp-sass'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;autoprefixer&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'gulp-autoprefixer'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sourcemaps&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'gulp-sourcemaps'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dirs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'src'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'build'&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sassPaths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dirs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/app.scss`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dirs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/styles/`&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'styles'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sourcemaps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'error'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;logError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;autoprefixer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sourcemaps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'.'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here we have utilised ES6 &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import&quot;&gt;import/modules&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions&quot;&gt;arrow functions&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings&quot;&gt;template strings&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const&quot;&gt;constants&lt;/a&gt;. If you’d like to check out more ES6 features, &lt;a href=&quot;http://es6-features.org/&quot;&gt;es6-features.org&lt;/a&gt; is a handy resource.&lt;/p&gt;

</description>
        <pubDate>Wed, 24 Jun 2015 00:00:00 +0000</pubDate>
        <link>http://markgoodyear.com/2015/06/using-es6-with-gulp/</link>
        <guid isPermaLink="true">http://markgoodyear.com/2015/06/using-es6-with-gulp/</guid>
        
        
      </item>
    
      <item>
        <title>Introducing the vr unit to create simple vertical rhythm—using PostCSS</title>
        <description>&lt;p class=&quot;lead&quot;&gt;With Sass, I use a function to create simple vertical rhyhtm—generated from the base line-height—without the complexity of maintaining a baseline grid. With PostCSS, we can take this further and create a new unit.&lt;/p&gt;

&lt;h2 id=&quot;function-able-sass&quot;&gt;Function-able Sass&lt;/h2&gt;
&lt;p&gt;The Sass (SCSS) function I use is very simple. It essentially returns a multiple of the base line-height to help create vertical rhythm. The function looks a little like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;32px&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;@return&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line-height&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And we can use it in our stylesheet like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.selector&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;margin-bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This will multiply the line-height by the number passed in, so the result here would be &lt;code class=&quot;highlighter-rouge&quot;&gt;64px&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;extending-with-postcss&quot;&gt;Extending with PostCSS&lt;/h2&gt;
&lt;p&gt;After digging into PostCSS, I decided to re-create the Sass function with a PostCSS plugin. Because PostCSS is a post-processer, we are able to extend CSS. The result was &lt;a href=&quot;https://github.com/markgoodyear/postcss-vertical-rhythm/&quot;&gt;postcss-vertical-rhythm&lt;/a&gt;, which replicates the Sass function, but using a custom CSS unit—&lt;code class=&quot;highlighter-rouge&quot;&gt;vr&lt;/code&gt;—instead of a function. For example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.selector&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;margin-bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This method works more like using plain CSS.&lt;/p&gt;

&lt;h2 id=&quot;how-do-i-use-the-vr-unit&quot;&gt;How do I use the vr unit?&lt;/h2&gt;

&lt;p&gt;Firstly, install &lt;a href=&quot;https://github.com/markgoodyear/postcss-vertical-rhythm/&quot;&gt;postcss-vertical-rhythm&lt;/a&gt; via npm:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;npm install postcss-vertical-rhythm &lt;span class=&quot;nt&quot;&gt;--save-dev&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you’re using gulp, you can then add it to your project like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'styles'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'source.css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;postcss&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'postcss-vertical-rhythm'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'output.css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Next, we need to define the base font-size and line-height using the shorthand &lt;code class=&quot;highlighter-rouge&quot;&gt;font&lt;/code&gt; property:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;font&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1rem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sans-serif&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The font-size can be either &lt;code class=&quot;highlighter-rouge&quot;&gt;em&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;rem&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;px&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;%&lt;/code&gt; based. &lt;a href=&quot;https://github.com/markgoodyear/postcss-vertical-rhythm/&quot;&gt;postcss-vertical-rhythm&lt;/a&gt; will parse the property and calculate the &lt;code class=&quot;highlighter-rouge&quot;&gt;px&lt;/code&gt; line-height value automatically—no variable set up required. In the case above, the line-height would be &lt;code class=&quot;highlighter-rouge&quot;&gt;32px&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once this is set up, we can now use the &lt;code class=&quot;highlighter-rouge&quot;&gt;vr&lt;/code&gt; unit:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;padding-top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vr&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;margin-bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And with the line-height at &lt;code class=&quot;highlighter-rouge&quot;&gt;32px&lt;/code&gt; from the above font property, the output is:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;padding-top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;32px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;margin-bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;64px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/markgoodyear/postcss-vertical-rhythm/&quot;&gt;postcss-vertical-rhythm&lt;/a&gt; also supports decimal values so we can easily use half or quarter values, for example: &lt;code class=&quot;highlighter-rouge&quot;&gt;.5vr&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;.25vr&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;thoughts&quot;&gt;Thoughts&lt;/h2&gt;
&lt;p&gt;If you have any feedback, please leave a comment below or you can find me on &lt;a href=&quot;https://twitter.com/markgdyr&quot;&gt;Twitter&lt;/a&gt;. If you’d like to know more more about PostCSS, I wrote about it &lt;a class=&quot;external-link&quot; href=&quot;http://bigbitecreative.com/a-look-into-writing-future-css-with-postcss-cssnext/&quot;&gt;here&lt;/a&gt;. &lt;em&gt;Happy vertical rhythm-ing!&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 12 Jun 2015 00:00:00 +0000</pubDate>
        <link>http://markgoodyear.com/2015/06/introducing-the-vr-unit-to-create-simple-vertical-rhythm-using-postcss/</link>
        <guid isPermaLink="true">http://markgoodyear.com/2015/06/introducing-the-vr-unit-to-create-simple-vertical-rhythm-using-postcss/</guid>
        
        
      </item>
    
      <item>
        <title>A look into writing future CSS with PostCSS and cssnext</title>
        <description>
</description>
        <pubDate>Tue, 09 Jun 2015 00:00:00 +0000</pubDate>
        <link>http://markgoodyear.com/2015/06/a-look-into-writing-future-css-with-postcss-cssnext/</link>
        <guid isPermaLink="true">http://markgoodyear.com/2015/06/a-look-into-writing-future-css-with-postcss-cssnext/</guid>
        
        
      </item>
    
      <item>
        <title>Retinafy your Craft site with Retinafy plugin</title>
        <description>&lt;p class=&quot;lead&quot;&gt;Retinafy is a small plugin for Craft CMS. Its aim is to provide a simple way to generate the required images and markup for a retina screen.&lt;/p&gt;

&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;Retinafy uses the &lt;code class=&quot;highlighter-rouge&quot;&gt;srcset&lt;/code&gt; attribute, which lets us define different sized images to display depending what screen the user is browsing with. It uses the common &lt;code class=&quot;highlighter-rouge&quot;&gt;2x&lt;/code&gt; definition which lets us display a higher resolution image for retina screens.&lt;/p&gt;

&lt;p&gt;To let Retinafy know which images are intended to be used for retina purposes, they will need to have an &lt;code class=&quot;highlighter-rouge&quot;&gt;@2x&lt;/code&gt; suffix, e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;image-name@2x.png&lt;/code&gt;. This signifies the intent of the image, and allows us to still upload non-retina images if a higher resolution isn’t available.&lt;/p&gt;

&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;/h2&gt;
&lt;p&gt;Once installed, there are two ways to call Retinafy. The first is via a Craft variable, and the second being a Twig filter. Firstly, the Craft Variable:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ craft.retinafy.image(assetFieldName) }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And the Twig filter:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ assetFieldName | reftinafy }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Both ways perform exactly the same function, so it’s a matter of preference for which method to use.&lt;/p&gt;

&lt;p&gt;By default, Refinafy will create the 1x non-retina version of the uploaded &lt;code class=&quot;highlighter-rouge&quot;&gt;@2x&lt;/code&gt; image. This  will be used as the &lt;code class=&quot;highlighter-rouge&quot;&gt;src&lt;/code&gt; attribute and the original &lt;code class=&quot;highlighter-rouge&quot;&gt;@2x&lt;/code&gt; image will be used as the &lt;code class=&quot;highlighter-rouge&quot;&gt;srcset&lt;/code&gt;. For example if we upload a 500 x 500 &lt;code class=&quot;highlighter-rouge&quot;&gt;@2x&lt;/code&gt; image, Retinfafy will create a 250 x 250 version, and the markup generated would be:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[generated-image-250x250]&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;srcset=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[original-image-500x500] 2x&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Any browser supporting &lt;code class=&quot;highlighter-rouge&quot;&gt;scrset&lt;/code&gt; will then display the correct image based upon the display. A handy place to find out what browser support for this is at &lt;a href=&quot;http://caniuse.com/#search=srcset&quot;&gt;caniuse&lt;/a&gt;. Retinafy doesn’t provide any polyfills, however it gracefully degrades as any browser that doesn’t support &lt;code class=&quot;highlighter-rouge&quot;&gt;srcset&lt;/code&gt; will get the non-retina version. Polyfills can be added manually if desired.&lt;/p&gt;

&lt;h3 id=&quot;using-transforms&quot;&gt;Using transforms&lt;/h3&gt;
&lt;p&gt;Transforms are a powerful feature of Craft. Retinafy can utilise existing transforms, and if the image is big enough to display a 2x version of the transform, it will be added to the &lt;code class=&quot;highlighter-rouge&quot;&gt;srcset&lt;/code&gt; attribute. To use a transform, we can pass it into the Craft variable, or Twig filter:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Craft variable --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ craft.retinafy.image(assetFieldName, 'transformHandle') }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Twig filter --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ assetFieldName | reftinafy('transformHandle') }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Providing the uploaded image is equal too—or larger than—2x the transform size, it will create the &lt;code class=&quot;highlighter-rouge&quot;&gt;@2x&lt;/code&gt; version. As an example, if we have a transform set at 250 x 250, it will create a 500 x 500 image, and the generated markup would be:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[transform-250x250]&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;srcset=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[transform-2x-500x500] 2x&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;download&quot;&gt;Download&lt;/h2&gt;
&lt;p&gt;You can find the plugin on &lt;a href=&quot;https://github.com/markgoodyear/craft-retinafy&quot;&gt;GitHub&lt;/a&gt;, and is also available to install through the &lt;a href=&quot;https://dukt.net/craft/directory&quot;&gt;Directory&lt;/a&gt; plugin. If you have any questions, let me know in the comments below or give me a &lt;a href=&quot;http://twitter.com/markgdyr&quot;&gt;Tweet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Enjoy Retinafying!&lt;/p&gt;
</description>
        <pubDate>Sat, 14 Mar 2015 00:00:00 +0000</pubDate>
        <link>http://markgoodyear.com/2015/03/retinafy-your-craft-site-with-retinafy-plugin/</link>
        <guid isPermaLink="true">http://markgoodyear.com/2015/03/retinafy-your-craft-site-with-retinafy-plugin/</guid>
        
        
      </item>
    
      <item>
        <title>Create an on-demand sticky header with Headhesive.js</title>
        <description>&lt;p class=&quot;lead&quot;&gt;Headhesive.js is a lightweight, fully customisable JavaScript plugin for creating an on-demand sticky header.&lt;/p&gt;

&lt;ul class=&quot;post-actions&quot;&gt;
  &lt;li&gt;&lt;a class=&quot;btn&quot; href=&quot;http://markgoodyear.com/labs/headhesive&quot;&gt;Demo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a class=&quot;btn&quot; href=&quot;https://github.com/markgoodyear/headhesive/archive/master.zip&quot;&gt;Download&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a class=&quot;btn&quot; href=&quot;https://github.com/markgoodyear/headhesive&quot;&gt;Fork&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a recent project I needed to create a sticky header that was only visible after a certain point on the page. I found a few plugins available, some relied on jQuery, some had many extra features that weren’t necessary. Whilst jQuery isn’t always a bad thing, I was looking for a lightweight, dependency-free solution. Headhesive.js was created.&lt;/p&gt;

&lt;h2 id=&quot;what-does-it-do&quot;&gt;What does it do?&lt;/h2&gt;
&lt;p&gt;Headhesive.js creates an &lt;em&gt;on-demand&lt;/em&gt; sticky header that will appear after a specific scroll distance, or at a certain element. No dependancies and no fancy extra frills to get in your way. It works exactly how you tell it.&lt;/p&gt;

&lt;h2 id=&quot;how-to-use&quot;&gt;How to use&lt;/h2&gt;
&lt;p&gt;First of all you’ll need to include the &lt;code class=&quot;highlighter-rouge&quot;&gt;headhesive.min.js&lt;/code&gt; file in your footer, then create an instance using any element:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Headhesive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'.header'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This instantiates Headhesive.js on the &lt;code class=&quot;highlighter-rouge&quot;&gt;.header&lt;/code&gt; element, using the default options—&lt;em&gt;see the &lt;a href=&quot;https://github.com/markgoodyear/headhesive.js/blob/master/README.md#options&quot;&gt;readme&lt;/a&gt; for more info on options&lt;/em&gt;. Upon instantiating, the &lt;code class=&quot;highlighter-rouge&quot;&gt;.header&lt;/code&gt; element will be cloned with the class &lt;code class=&quot;highlighter-rouge&quot;&gt;.headhesive--clone&lt;/code&gt;. In this example, the cloned element will look like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;header headhesive--clone&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- header elements will be cloned inside --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;No styles are injected via the plugin, keeping the plugin lightweight and as user customisable as possible. To create a basic hide/show effect we need to add some CSS magic to the cloned element:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.headhesive--clone&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fixed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                   &lt;span class=&quot;c&quot;&gt;/* fix the element */&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                            &lt;span class=&quot;c&quot;&gt;/* make sure it's at the top */&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;translateY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;-100%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;/* move it off screen */&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;300ms&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ease-in-out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;/* add animation */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We shift the element off-screen by setting the &lt;code class=&quot;highlighter-rouge&quot;&gt;transform: translateY&lt;/code&gt; property to &lt;code class=&quot;highlighter-rouge&quot;&gt;-100%&lt;/code&gt;. Alternatively, we could use a negative margin to move the element off-screen. I prefer &lt;code class=&quot;highlighter-rouge&quot;&gt;transform&lt;/code&gt; as there is no need to define any heights, and it works perfectly in IE9.&lt;/p&gt;

&lt;p&gt;When reaching the target scroll distance, the class &lt;code class=&quot;highlighter-rouge&quot;&gt;.headhesive--stick&lt;/code&gt; is added. We can use this and create some styles to show the element:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.headhesive--stick&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;translateY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;/* move it back on screen */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We now have an on-demand sticky header!&lt;/p&gt;

&lt;h2 id=&quot;further-customisation&quot;&gt;Further customisation&lt;/h2&gt;
&lt;p&gt;Please check out the &lt;a href=&quot;https://github.com/markgoodyear/headhesive.js/&quot;&gt;Headhesive.js project on GitHub&lt;/a&gt; for an always up-to-date guide on the options, methods, along with a downloadable demo.&lt;/p&gt;

&lt;p&gt;If you have any questions or find an issue, please leave a comment below, or you can find me on &lt;a href=&quot;https://markgoodyear.com/markgdyr&quot;&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;ul class=&quot;post-actions&quot;&gt;
  &lt;li&gt;&lt;a class=&quot;btn&quot; href=&quot;http://markgoodyear.com/labs/headhesive&quot;&gt;Demo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a class=&quot;btn&quot; href=&quot;https://github.com/markgoodyear/headhesive/archive/master.zip&quot;&gt;Download&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a class=&quot;btn&quot; href=&quot;https://github.com/markgoodyear/headhesive&quot;&gt;Fork&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Mon, 07 Apr 2014 00:00:00 +0000</pubDate>
        <link>http://markgoodyear.com/2014/04/create-an-on-demand-sticky-header-with-headhesive-js/</link>
        <guid isPermaLink="true">http://markgoodyear.com/2014/04/create-an-on-demand-sticky-header-with-headhesive-js/</guid>
        
        
      </item>
    
      <item>
        <title>Better development environments with Vagrant</title>
        <description>&lt;p class=&quot;lead&quot;&gt;Having a properly configured development environment is important to any project; Vagrant does just that.&lt;/p&gt;

&lt;p&gt;Before we start, I’m going to assume you are using a Mac for development, but the principles are the same if you’re using Windows. It’s worth noting Linux users may not have the issues I cover in the post.&lt;/p&gt;

&lt;h2 id=&quot;but-mamp-rocks&quot;&gt;But MAMP rocks!?&lt;/h2&gt;
&lt;p&gt;I’m a long term user of MAMP, and still use it if I need to quickly fire up a PHP server to test something, though it’s not without its limitations. One in particular is that everything may seem perfect on your local machine, but as soon as it’s deployed to production, things could break. Why? The main difference here would be the Operating System. As you’ll likely be deploying to a Linux server and not OSX/Windows, there may be some compatability issues to iron out. Software (such as Apache, PHP, MySQL etc.) version differences can also cause big problems. From experience, it’s best to develop on the same versions of everything to avoid any potential hiccups. The last thing you want is to be fixing unexpected bugs that appear in a different version of PHP—especially after a launch.&lt;/p&gt;

&lt;p&gt;Mirroring the production environment as much as possible is an important step to ensure as little as possible can go wrong. As they say; if it can go wrong, it will.&lt;/p&gt;

&lt;h2 id=&quot;other-options&quot;&gt;Other options&lt;/h2&gt;
&lt;p&gt;Another route I tried is to use the built-in Apache on OSX, along with installing MySQL and multiple PHP versions. Whilst this freed me from MAMP, it was a fairly complicated process and came across a few issues along the way. Replicating the same process on different machines isn’t an easy task, not to mention time consuming—especially in a team where everyone would need to have the same setup. If you had two projects with two different software requirements, things start to get complicated, too. So how do we solve these issues?&lt;/p&gt;

&lt;h2 id=&quot;meet-vagrant&quot;&gt;Meet Vagrant&lt;/h2&gt;
&lt;p&gt;Vagrant solves all these issues by allowing us to create portable virtual development environments. This means you can have as many environments as you need, each configured differently to suite the project requirements. So if you need PHP 5.4 on one project and PHP 5.3 on another, Vagrant makes it easy to manage. Replicating an environment on a different machine is as simple as running &lt;code class=&quot;highlighter-rouge&quot;&gt;$ vagrant up&lt;/code&gt;, saving you the hard work and time of installing and configuring everything manually. Awesome!&lt;/p&gt;

&lt;p&gt;Vagrant is easy to configure, so whether you need Apache or Nginx with a specific version of PHP, setting it up is a breeze.&lt;/p&gt;

&lt;h3 id=&quot;getting-started-with-vagrant&quot;&gt;Getting started with Vagrant&lt;/h3&gt;
&lt;p&gt;To get started, you’ll first need to install &lt;a href=&quot;https://www.virtualbox.org/wiki/Downloads&quot;&gt;VirtualBox&lt;/a&gt;. Once installed, head over to &lt;a href=&quot;http://downloads.vagrantup.com/&quot;&gt;Vagrant Downloads&lt;/a&gt; and grab the latest version.&lt;/p&gt;

&lt;p&gt;I won’t go into the depths of setting up a project from scratch as there is a great &lt;a href=&quot;http://docs.vagrantup.com/v2/getting-started/index.html&quot;&gt;getting started&lt;/a&gt; guide on the Vagrant website. I’d recommend taking a look through the documentation to familiarise yourself with Vagrant and its commands. Rather than learning about dev-ops and creating your own provisioning scripts to provision a Vagrant box, there are many tools out there to get you up and running in minutes. One of my favourites is &lt;a href=&quot;http://fideloper.github.io/Vaprobash/index.html&quot;&gt;Vaprobash&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Vaprobash uses a collection of Bash scripts to install everything you need to set up your environment. Choosing what you need with Vaprobash is as simple as uncommenting a few lines in the provided &lt;code class=&quot;highlighter-rouge&quot;&gt;Vagrantfile&lt;/code&gt;, then running a &lt;code class=&quot;highlighter-rouge&quot;&gt;$ vagrant up&lt;/code&gt;. That’s all there is to it, you’re ready to code.&lt;/p&gt;

&lt;p&gt;Another tool is &lt;a href=&quot;https://puphpet.com/&quot;&gt;PuPHPet&lt;/a&gt;, an online GUI generator providing a wide range of options. Enter some project info, tick a couple of boxes and &lt;code class=&quot;highlighter-rouge&quot;&gt;$ vagrant up&lt;/code&gt;. If Vaprobash doesn’t offer everything you need, I recommend giving PuPHPet a try.&lt;/p&gt;

&lt;p&gt;Both are great options to get started without needing to learn any more than what you would using MAMP. If you need any more flexibility, you can get your hands dirty with provisionging tools—such as &lt;a href=&quot;http://puppetlabs.com/&quot;&gt;Puppet&lt;/a&gt; or &lt;a href=&quot;http://www.opscode.com/chef/&quot;&gt;Chef&lt;/a&gt;—to completely customise your environment.&lt;/p&gt;

&lt;h3 id=&quot;vagrant-workflow&quot;&gt;Vagrant workflow&lt;/h3&gt;
&lt;p&gt;A typical Vagrant workflow would be something like:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Initiate a project and &lt;code class=&quot;highlighter-rouge&quot;&gt;$ vagrant up&lt;/code&gt;. This starts up and configures the virtual machine first time round. Vagrant will take a short while to install everything on this first instance, so grab yourself a coffee while you wait.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;When everything has installed, fire up your favourite editor and code like a ninja.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;At the end of the day, either &lt;code class=&quot;highlighter-rouge&quot;&gt;$ vagrant [suspend|halt|destroy]&lt;/code&gt;. &lt;a href=&quot;http://docs.vagrantup.com/v2/cli/suspend.html&quot;&gt;Suspend&lt;/a&gt; will effectively pause the machine, &lt;a href=&quot;http://docs.vagrantup.com/v2/cli/halt.html&quot;&gt;halt&lt;/a&gt; will shutdown the machine, and &lt;a href=&quot;http://docs.vagrantup.com/v2/cli/destroy.html&quot;&gt;destroy&lt;/a&gt; will completely remove all traces of the machine like it never existed. Remember to dump the database before destroying so you don’t lose it—I’ve done that far too many times! You can even store it in version control for safe-keeping. Usually you’ll only need to destroy a box when a project is complete. Halting or suspending will be fine for the duration. By doing this, &lt;code class=&quot;highlighter-rouge&quot;&gt;$ vagrant up&lt;/code&gt; will be much quicker as everything is already installed in the box.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;in-summary&quot;&gt;In summary&lt;/h2&gt;
&lt;p&gt;Vagrant is a great way to create shareable development environments, avoiding the classic line:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I don’t know what you’re talking about; it works fine on &lt;strong&gt;my&lt;/strong&gt; machine!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
        <pubDate>Wed, 19 Mar 2014 00:00:00 +0000</pubDate>
        <link>http://markgoodyear.com/2014/03/better-development-environments-with-vagrant/</link>
        <guid isPermaLink="true">http://markgoodyear.com/2014/03/better-development-environments-with-vagrant/</guid>
        
        
      </item>
    
      <item>
        <title>Getting started with gulp</title>
        <description>&lt;div class=&quot;callout  callout--info  callout--small&quot;&gt;
  &lt;ul class=&quot;list-bare&quot;&gt;
    &lt;li&gt;&lt;em&gt;Updated Jan 28th, 2014 to reflect the advancement of gulp&lt;/em&gt;&lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Updated Apr 21st, 2014 to utilise updated `gulp-livereload`&lt;/em&gt;&lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Updated Aug 11th, 2014 Using `del` instead of `gulp-clean`, updated `gulp-livereload`&lt;/em&gt;&lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Updated May 20th, 2015 Update `gulp-ruby-sass` syntax&lt;/em&gt;&lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Updated Nov 2nd, 2015 Update `del` syntax&lt;/em&gt;&lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Updated Jan 12th, 2016 `gulp-minify-css` depreciated. Use `gulp-cssnano`&lt;/em&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

&lt;p class=&quot;lead&quot;&gt;Step aside Grunt, there's a new task runner in town. Gulp is an intuitive, code-over-configuration, streaming build system. It's &lt;em&gt;fast&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why should I be interested?&lt;/em&gt; Good question. Gulp’s code-over-configuration makes it not only easy to write tasks for, but also much easier to read and maintain.&lt;/p&gt;

&lt;p&gt;Gulp uses node.js streams, making it faster to build as it doesn’t need to write temporary files/folders to disk. If you want to learn more about streams—although not necessary—&lt;a href=&quot;https://github.com/substack/stream-handbook&quot;&gt;this article&lt;/a&gt; is a good read. Gulp allows you to input your source file(s), pipe them through a bunch of plugins and get an output at the end, rather than configuring each plugin with an input and output—like in Grunt. Let’s take a look at an example of what a basic Sass build could look like with both Grunt and gulp:&lt;/p&gt;

&lt;p&gt;####&lt;strong&gt;Grunt:&lt;/strong&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;dist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'expanded'&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;'dist/assets/css/main.css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'src/styles/main.scss'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;autoprefixer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;dist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;browsers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'last 2 version'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'safari 5'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'ie 8'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'ie 9'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'opera 12.1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'ios 6'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'android 4'&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'dist/assets/css/main.css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'dist/assets/css/main.css'&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;registerTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'styles'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'sass'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'autoprefixer'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Grunt requires each plugin to be configured separately, specifying source and destination paths for each plugin. For example, we input one file to the Sass plugin, which then saves the output. We then need to configure Autoprefixer to input Sass’s output, which then outputs another file. Let’s take a look at the same configuration with gulp:&lt;/p&gt;

&lt;p&gt;####&lt;strong&gt;Gulp:&lt;/strong&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'sass'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'src/styles/main.scss'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'expanded'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;autoprefixer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'last 2 version'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'safari 5'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'ie 8'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'ie 9'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'opera 12.1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'ios 6'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'android 4'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'dist/assets/css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;With gulp we only input one file. This gets modified by the Sass plugin, passed to the Autoprefixer plugin and modified, then we get one file out. This process speeds up the build process as we’re not reading and writing unnecessary files to end up with one.&lt;/p&gt;

&lt;p&gt;So you’re interested, now what? Let’s install gulp and create a basic gulpfile with some core tasks to get started.&lt;/p&gt;

&lt;h2 id=&quot;installing-gulp&quot;&gt;Installing gulp&lt;/h2&gt;

&lt;p&gt;Before we delve into configuring tasks, we need to install gulp:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm install gulp &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This installs gulp globally, giving access to gulp’s CLI. We then need to install it locally to the project. &lt;code class=&quot;highlighter-rouge&quot;&gt;cd&lt;/code&gt; into your project and run the following (make sure you have an existing &lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt; file):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm install gulp &lt;span class=&quot;nt&quot;&gt;--save-dev&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This installs gulp locally to the project and saves it to the &lt;code class=&quot;highlighter-rouge&quot;&gt;devDependencies&lt;/code&gt; in the &lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt; file.&lt;/p&gt;

&lt;h2 id=&quot;installing-gulp-plugins&quot;&gt;Installing gulp plugins&lt;/h2&gt;

&lt;p&gt;We are going to install some plugins to achieve the following tasks:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Sass compile &lt;em&gt;(&lt;a href=&quot;https://github.com/sindresorhus/gulp-ruby-sass&quot;&gt;gulp-ruby-sass&lt;/a&gt;)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Autoprefixer &lt;em&gt;(&lt;a href=&quot;https://github.com/Metrime/gulp-autoprefixer&quot;&gt;gulp-autoprefixer&lt;/a&gt;)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Minify CSS &lt;em&gt;(&lt;a href=&quot;https://github.com/jonathanepollack/gulp-cssnano&quot;&gt;gulp-cssnano&lt;/a&gt;)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;JSHint &lt;em&gt;(&lt;a href=&quot;https://github.com/wearefractal/gulp-jshint&quot;&gt;gulp-jshint&lt;/a&gt;)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Concatenation &lt;em&gt;(&lt;a href=&quot;https://github.com/wearefractal/gulp-concat&quot;&gt;gulp-concat&lt;/a&gt;)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Uglify &lt;em&gt;(&lt;a href=&quot;https://github.com/terinjokes/gulp-uglify&quot;&gt;gulp-uglify&lt;/a&gt;)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Compress images &lt;em&gt;(&lt;a href=&quot;https://github.com/sindresorhus/gulp-imagemin&quot;&gt;gulp-imagemin&lt;/a&gt;)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;LiveReload &lt;em&gt;(&lt;a href=&quot;https://github.com/vohof/gulp-livereload&quot;&gt;gulp-livereload&lt;/a&gt;)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Caching of images so only changed images are compressed &lt;em&gt;(&lt;a href=&quot;https://github.com/jgable/gulp-cache/&quot;&gt;gulp-cache&lt;/a&gt;)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Notify of changes &lt;em&gt;(&lt;a href=&quot;https://github.com/mikaelbr/gulp-notify&quot;&gt;gulp-notify&lt;/a&gt;)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Clean files for a clean build &lt;em&gt;(&lt;a href=&quot;https://www.npmjs.org/package/del&quot;&gt;del&lt;/a&gt;)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To install these plugins, run the following command:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm install gulp-ruby-sass gulp-autoprefixer gulp-cssnano gulp-jshint gulp-concat gulp-uglify gulp-imagemin gulp-notify gulp-rename gulp-livereload gulp-cache del &lt;span class=&quot;nt&quot;&gt;--save-dev&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This will install all necessary plugins and save them to &lt;code class=&quot;highlighter-rouge&quot;&gt;devDependencies&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt;. A full list of gulp plugins can be &lt;a href=&quot;http://gulpjs.com/plugins/&quot;&gt;found here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;load-in-the-plugins&quot;&gt;Load in the plugins&lt;/h2&gt;

&lt;p&gt;Next, we need to create a &lt;code class=&quot;highlighter-rouge&quot;&gt;gulpfile.js&lt;/code&gt; and load in the plugins:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'gulp'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;sass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'gulp-ruby-sass'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;autoprefixer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'gulp-autoprefixer'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;cssnano&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'gulp-cssnano'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;jshint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'gulp-jshint'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;uglify&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'gulp-uglify'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;imagemin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'gulp-imagemin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;rename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'gulp-rename'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'gulp-concat'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;notify&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'gulp-notify'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;cache&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'gulp-cache'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;livereload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'gulp-livereload'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'del'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Phew! That seems a lot more work than Grunt, right? Gulp plugins are slightly different from Grunt plugins—they are designed to do one thing and one thing well. An example; Grunt’s &lt;code class=&quot;highlighter-rouge&quot;&gt;imagemin&lt;/code&gt; uses caching to avoid re-compressing images that are already compressed.  With gulp, this would be done with a cache plugin, which can also be used to cache other things too. This adds an extra layer of flexibility to the build process. Pretty cool huh?&lt;/p&gt;

&lt;p&gt;We can &lt;a href=&quot;https://github.com/jackfranklin/gulp-load-tasks&quot;&gt;auto load&lt;/a&gt; all installed plugins like in Grunt, but for the purpose of this post we’ll stick to the manual method.&lt;/p&gt;

&lt;h2 id=&quot;creating-tasks&quot;&gt;Creating tasks&lt;/h2&gt;

&lt;h3 id=&quot;compile-sass-autoprefix-and-minify&quot;&gt;Compile Sass, Autoprefix and minify&lt;/h3&gt;
&lt;p&gt;Firstly, we will configure Sass compiling. We’re going to compile Sass as expanded, run it through Autoprefixer and save it to our destination. We’ll then create a minified &lt;code class=&quot;highlighter-rouge&quot;&gt;.min&lt;/code&gt; version, auto-refresh the page and notify that the task is complete:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'styles'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'src/styles/main.scss'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'expanded'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;autoprefixer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'last 2 version'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'dist/assets/css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.min'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cssnano&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'dist/assets/css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;notify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Styles task complete'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;A little explanation before moving on.&lt;/em&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'styles'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is the &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp.task&lt;/code&gt; API which is used to create tasks. The above can run from Terminal with &lt;code class=&quot;highlighter-rouge&quot;&gt;$ gulp styles&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'src/styles/main.scss'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'expanded'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is the new &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp-ruby-sass&lt;/code&gt; API where we define the source file(s) and pass in any options. For many other plugins, you would use the &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp.src&lt;/code&gt; API which we use later in this post (&lt;code class=&quot;highlighter-rouge&quot;&gt;return gulp.src(...)&lt;/code&gt;). It also can be a glob pattern, such as &lt;code class=&quot;highlighter-rouge&quot;&gt;/**/*.scss&lt;/code&gt; to match multiple files. By returning the stream it makes it asynchronous, ensuring the task is fully complete before we get a notification to say it’s finished.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;autoprefixer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'last 2 version'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We use &lt;code class=&quot;highlighter-rouge&quot;&gt;.pipe()&lt;/code&gt; to pipe the source file(s) into a plugin. Usually the options for a plugin are found on their respective GitHub page. I’ve linked them above for convenience. Pipes are chainable so you can add as many plugins as you need to the stream.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'dist/assets/css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp.dest&lt;/code&gt; API is where we set the destination path. A task can have multiple destinations, one to output the expanded version and one to output the minifed version. This is demonstrated in the above &lt;code class=&quot;highlighter-rouge&quot;&gt;styles&lt;/code&gt; task.&lt;/p&gt;

&lt;p&gt;I’d recommend checking out the gulp &lt;a href=&quot;https://github.com/gulpjs/gulp/blob/master/docs/API.md&quot;&gt;API documentaiton&lt;/a&gt; to get a better understanding of these methods. It’s not as scary as it sounds!&lt;/p&gt;

&lt;h3 id=&quot;jshint-concat-and-minify-javascript&quot;&gt;JSHint, concat, and minify JavaScript&lt;/h3&gt;

&lt;p&gt;Hopefully you’ll now have a good idea of how to create a task for gulp. Next, we’ll set up the scripts task to lint, concat and uglify:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'scripts'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'src/scripts/**/*.js'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jshint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'.jshintrc'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jshint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reporter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'default'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'main.js'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'dist/assets/js'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.min'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;uglify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'dist/assets/js'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;notify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Scripts task complete'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here we use the &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp.src&lt;/code&gt; API to specify our input files. One thing to note is that we need to specify a reporter for JSHint. I’m using the default reporter, which should be fine for most people. More on this can be found &lt;a href=&quot;http://www.jshint.com/docs/reporters/&quot;&gt;on the JSHint website&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;compress-images&quot;&gt;Compress Images&lt;/h3&gt;

&lt;p&gt;Next, we’ll set up image compression:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'images'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'src/images/**/*'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;imagemin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;optimizationLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;progressive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;interlaced&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'dist/assets/img'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;notify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Images task complete'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This will take any source images and run them through the &lt;code class=&quot;highlighter-rouge&quot;&gt;imagemin&lt;/code&gt; plugin. We can go a little further and utilise caching to save re-compressing already compressed images each time this task runs. All we need is the &lt;a href=&quot;https://github.com/jgable/gulp-cache&quot;&gt;gulp-cache&lt;/a&gt; plugin—which we installed earlier. To set this up, we need to change this line:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;imagemin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;optimizationLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;progressive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;interlaced&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;imagemin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;optimizationLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;progressive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;interlaced&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now only new or changed images will be compressed. &lt;em&gt;Neat!&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;clean-up&quot;&gt;Clean up!&lt;/h3&gt;
&lt;p&gt;Before deploying, it’s a good idea to clean out the destination folders and rebuild the files—just in case any have been removed from the source and are left hanging out in the destination folder:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'clean'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;del&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'dist/assets/css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'dist/assets/js'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'dist/assets/img'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We don’t need to use a gulp plugin here as we can take advantage of Node modules directly within gulp. We use a return to ensure the task finishes before exiting.&lt;/p&gt;

&lt;h3 id=&quot;the-default-task&quot;&gt;The default task&lt;/h3&gt;

&lt;p&gt;We can create a default task, ran by using &lt;code class=&quot;highlighter-rouge&quot;&gt;$ gulp&lt;/code&gt;, to run all three tasks we have created:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'default'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'clean'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'styles'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'scripts'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'images'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Notice the additional array in &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp.task&lt;/code&gt;. This is where we can define task dependencies. In this example, the clean task will run before the tasks in &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp.start&lt;/code&gt;. Tasks in Gulp run concurrently together and have no order in which they’ll finish, so we need to make sure the &lt;code class=&quot;highlighter-rouge&quot;&gt;clean&lt;/code&gt; task is completed before running additional tasks.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; It’s advised against using &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp.start&lt;/code&gt; in favour of executing tasks in the dependency arrary, but in this scenario to ensure &lt;code class=&quot;highlighter-rouge&quot;&gt;clean&lt;/code&gt; fully completes, it seems the best option.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;watch&quot;&gt;Watch&lt;/h3&gt;
&lt;p&gt;To watch our files and perform the necessary task when they change, we firstly need to create a new task, then use the &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp.watch&lt;/code&gt; API to begin watching files:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'watch'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Watch .scss files&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'src/styles/**/*.scss'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'styles'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Watch .js files&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'src/scripts/**/*.js'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'scripts'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Watch image files&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'src/images/**/*'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'images'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We specify the files we want to watch via the &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp.watch&lt;/code&gt; API and define which task(s) to run via the dependency array. We can now run &lt;code class=&quot;highlighter-rouge&quot;&gt;$ gulp watch&lt;/code&gt; and any changes to &lt;code class=&quot;highlighter-rouge&quot;&gt;.scss&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;.js&lt;/code&gt; or image files will run their respective tasks.&lt;/p&gt;

&lt;h3 id=&quot;livereload&quot;&gt;LiveReload&lt;/h3&gt;

&lt;p&gt;Gulp can also take care of automatically refreshing the page on file change. We’ll need to modify our &lt;code class=&quot;highlighter-rouge&quot;&gt;watch&lt;/code&gt; task, configuring the LiveReload server.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'watch'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Create LiveReload server&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;livereload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Watch any files in dist/, reload on change&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'dist/**'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'change'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;livereload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;changed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To make this work, you’ll need to install and enable the LiveReload browser plugin. You can also &lt;a href=&quot;http://feedback.livereload.com/knowledgebase/articles/86180-how-do-i-add-the-script-tag-manually-&quot;&gt;place the snippet in manually&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;putting-it-all-together&quot;&gt;Putting it all together&lt;/h2&gt;

&lt;p&gt;Here we have the full gulpfile, embedded from &lt;a href=&quot;https://gist.github.com/markgoodyear/8497946#file-01-gulpfile-js&quot;&gt;this gist&lt;/a&gt;:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/markgoodyear/8497946.js?file=01-gulpfile.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;I’ve also put together a Gruntfile that accomplishes the same tasks, so you have take a look for a comparison, in the &lt;a href=&quot;https://gist.github.com/markgoodyear/8497946#file-02-gruntfile-js&quot;&gt;same gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have any questions or issues, please leave a comment below or you can find me on &lt;a href=&quot;https://twitter.com/markgdyr&quot;&gt;Twitter&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Sun, 19 Jan 2014 00:00:00 +0000</pubDate>
        <link>http://markgoodyear.com/2014/01/getting-started-with-gulp/</link>
        <guid isPermaLink="true">http://markgoodyear.com/2014/01/getting-started-with-gulp/</guid>
        
        
      </item>
    
      <item>
        <title>Simplify form testing with Populatr</title>
        <description>&lt;p class=&quot;lead&quot;&gt;Populatr is a JavaScript plugin that will populate any form with pre-defined data to help reduce testing time.&lt;/p&gt;

&lt;ul class=&quot;post-actions&quot;&gt;
  &lt;li&gt;&lt;a class=&quot;btn&quot; href=&quot;http://markgoodyear.com/labs/populatr&quot;&gt;Demo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a class=&quot;btn&quot; href=&quot;https://github.com/markgoodyear/populatr/archive/master.zip&quot;&gt;Download&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a class=&quot;btn&quot; href=&quot;https://github.com/markgoodyear/populatr&quot;&gt;Fork&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-is-populatr&quot;&gt;What is Populatr?&lt;/h2&gt;
&lt;p&gt;On a recent project I needed to handle multiple large forms and monitor how the data handled each step of the way. Going through the forms manually is not only tedious, but very time consuming. To overcome this I decided to write a small, lightweight JavaScript plugin which will auto-fill form inputs based on given data.&lt;/p&gt;

&lt;h2 id=&quot;getting-started&quot;&gt;Getting started&lt;/h2&gt;
&lt;p&gt;Populatr is very simple to use. We can use CSS selectors to target a form (ID, class, etc) and for inputs—including selects—it targets the &lt;code class=&quot;highlighter-rouge&quot;&gt;name&lt;/code&gt; attribute. Take the following form for example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;form&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;demo-form&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;first-name&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;last-name&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;email&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;email&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To populate this form we need to initiate Populatr and then feed in some data:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;Populatr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'#demo-form'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;             &lt;span class=&quot;c1&quot;&gt;// CSS selector to select the form&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;'first-name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Mark'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;// 'Input name': 'Input value'&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;'last-name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Goodyear'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;'email'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'hello@markgoodyear.com'&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We initialise Populatr with &lt;code class=&quot;highlighter-rouge&quot;&gt;Populatr.init()&lt;/code&gt; then pass in if it’s active using either &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;false&lt;/code&gt;. Following this, we set the data to be used. The data can be passed in as a standard JavaScript object—as above—or we can specify an external JSON file, keeping the form data separate and to prevent bloating template files. Using the example above, initiate Populatr with a file to use:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;Populatr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'populatr.json'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then &lt;code class=&quot;highlighter-rouge&quot;&gt;populatr.json&lt;/code&gt; would look like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;#demo-form&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;first-name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Mark&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;last-name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Goodyear&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;email&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hello@markgoodyear.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;Note: double quotes are required for JSON.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;multiple-forms&quot;&gt;Multiple forms&lt;/h3&gt;
&lt;p&gt;Defining multiple forms is possible by passing in multiple objects:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;Populatr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'#form-one'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Form one data...&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'#form-two'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Form two data...&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'#form-three'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Form three data...&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;input-types&quot;&gt;Input types&lt;/h3&gt;
&lt;p&gt;Most input types are supported, including newer HTML5 inputs. See the &lt;a href=&quot;%= current_page.data.demo %&quot;&gt;demo&lt;/a&gt; for the full range along with an example on populating them.&lt;/p&gt;

&lt;h2 id=&quot;thoughts&quot;&gt;Thoughts?&lt;/h2&gt;
&lt;p&gt;If you have any thoughts, suggestions or issues, please leave a comment below.&lt;/p&gt;

&lt;ul class=&quot;post-actions&quot;&gt;
  &lt;li&gt;&lt;a class=&quot;btn&quot; href=&quot;http://markgoodyear.com/labs/populatr&quot;&gt;Demo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a class=&quot;btn&quot; href=&quot;https://github.com/markgoodyear/populatr/archive/master.zip&quot;&gt;Download&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a class=&quot;btn&quot; href=&quot;https://github.com/markgoodyear/populatr&quot;&gt;Fork&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Mon, 09 Sep 2013 00:00:00 +0000</pubDate>
        <link>http://markgoodyear.com/2013/09/simplify-form-testing-with-populatr/</link>
        <guid isPermaLink="true">http://markgoodyear.com/2013/09/simplify-form-testing-with-populatr/</guid>
        
        
      </item>
    
      <item>
        <title>Automating your workflow with Grunt</title>
        <description>&lt;p class=&quot;lead&quot;&gt;Learn how to automate your workflow with Grunt, reducing all those tedious tasks you repeat multiple times a day.&lt;/p&gt;

&lt;h2 id=&quot;the-need-for-automation&quot;&gt;The need for automation&lt;/h2&gt;

&lt;p&gt;Recently I’ve been looking to improve my workflow to automate the tasks I repeat on a day-to-day basis. I also wanted to standardise projects across a team, set up a project structure and make sure the necessary tasks are done correctly. CodeKit has served me well, however there remain a few issues I wanted to address; the ability to automate more and be able to work cross-platform without needing to configure different apps to match a project structure. Say hello to &lt;a href=&quot;http://gruntjs.com/&quot;&gt;Grunt&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-is-grunt&quot;&gt;What is Grunt?&lt;/h2&gt;
&lt;p&gt;To sum up Grunt, it’s a task runner built on &lt;a href=&quot;http://nodejs.org/&quot;&gt;Node.js&lt;/a&gt;—&lt;em&gt;don’t let this put you off!&lt;/em&gt; Node.js is simple to install—just visit the site, download the install package and run it. If you’re on Mac, you can also install it with &lt;a href=&quot;http://brew.sh/&quot;&gt;Homebrew&lt;/a&gt;. You’ll then want to install the Grunt CLI. I won’t go into great detail as they have a great &lt;a href=&quot;http://gruntjs.com/getting-started&quot;&gt;getting started guide&lt;/a&gt;, so to summarise:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Make sure Node.js is installed. This will also install the Node Package Manager (NPM).&lt;/li&gt;
  &lt;li&gt;Install the Grunt CLI globally. &lt;code class=&quot;highlighter-rouge&quot;&gt;npm install -g grunt-cli&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;You’ll then need to create two files in the root of your project, &lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Gruntfile.js&lt;/code&gt;. I’ll explain what these two files do next.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Before I continue, it’s worth noting you may need to run some install commands as admin. For example, Mac users will need to use &lt;code class=&quot;highlighter-rouge&quot;&gt;sudo&lt;/code&gt;:&lt;/em&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;npm install &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; grunt-cli&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;setting-up-your-project&quot;&gt;Setting up your project&lt;/h2&gt;
&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt; file contains all the information about the project, such as the name and version. It also lists the dependancies used by the project. A basic &lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt; will look like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'project-name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'version'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'0.1.0'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'devDependencies'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;'grunt'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'~0.4.1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is basically telling us the project name, version number (using the &lt;a href=&quot;http://semver.org/&quot;&gt;Semantic Versioning&lt;/a&gt; system) and that &lt;code class=&quot;highlighter-rouge&quot;&gt;grunt&lt;/code&gt; is a required dependency. To install dependencies, simply run:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;npm install&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This installs all dependencies to the &lt;code class=&quot;highlighter-rouge&quot;&gt;node_modules&lt;/code&gt; folder.&lt;/p&gt;

&lt;h2 id=&quot;configuring-grunt-tasks&quot;&gt;Configuring Grunt tasks&lt;/h2&gt;
&lt;p&gt;Now we move onto setting up the &lt;code class=&quot;highlighter-rouge&quot;&gt;Gruntfile.js&lt;/code&gt; file. It can become quite a large file if there are lot of tasks, so to start off I’ll demonstrate a basic task which will compile your Sass (.scss) files. Firstly, you will need to install the &lt;a href=&quot;https://github.com/gruntjs/grunt-contrib-sass&quot;&gt;Sass plugin&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;npm install grunt-contrib-sass &lt;span class=&quot;nt&quot;&gt;--save-dev&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Adding &lt;code class=&quot;highlighter-rouge&quot;&gt;--save-dev&lt;/code&gt; to the command automatically adds it to your &lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt; file so you don’t need to worry about adding it manually. Below is a basic configuration to compile Sass—including a development config and a distribution config.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Wrapper function&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Read package.json&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readJSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'package.json'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;//Initialize grunt&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;initConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Sass task&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;// Sass development options&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'expanded'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;s1&quot;&gt;'css/main.css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'css/sass/global.scss'&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;// Sass distribution options&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;dist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'compressed'&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;s1&quot;&gt;'css/main.css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'css/sass/main.scss'&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;



  &lt;span class=&quot;c1&quot;&gt;// Load tasks&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loadNpmTasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'grunt-contrib-sass'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;


  &lt;span class=&quot;c1&quot;&gt;// Create Default Task&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;registerTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'default'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;'sass:dev'&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Compile Sass with dev settings&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Create Distribution Task&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;registerTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'dist'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;'sass:dist'&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Compile Sass with distribution settings&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you’re familiar with JavaScript and JSON, it should be simple enough to understand. If not, it’s not as scary as it may look! Let’s take a closer look at what’s going on…&lt;/p&gt;

&lt;h3 id=&quot;the-wrapper-function&quot;&gt;The wrapper function&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Wrapper function&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Read package.json&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readJSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'package.json'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;//Initialize grunt&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;initConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[...]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The wrapper function contains two key parts. Firstly to read the project details we specified earlier in &lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt; and then to initialize the Grunt configuration. This is where we configure Grunt tasks.&lt;/p&gt;

&lt;h3 id=&quot;task-configuration&quot;&gt;Task configuration&lt;/h3&gt;

&lt;p&gt;So, our Sass task looks a little like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Sass task&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Sass development options&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'expanded'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;'css/main.css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'css/sass/global.scss'&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Sass distribution options&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;dist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'compressed'&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;'css/main.css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'css/sass/global.scss'&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here we have two tasks configured within the Sass task, &lt;code class=&quot;highlighter-rouge&quot;&gt;dev&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;dist&lt;/code&gt;. Both these are able to have custom options passed through, meaning it’s possible to compile Sass differently based on its environment. &lt;em&gt;How awesome is that?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Keeping it simple, I’ve only set up one option which is basically telling Grunt how to compile for each environment. Of course, there are many more options available which can be found at the plugins &lt;a href=&quot;http://github.com/gruntjs/grunt-contrib-sass&quot;&gt;GitHub&lt;/a&gt; page. This is the same for all Grunt plugins—be sure to check their respective GitHub pages for a full list of options.&lt;/p&gt;

&lt;p&gt;After setting up the options, we tell Grunt the destination file &lt;code class=&quot;highlighter-rouge&quot;&gt;css/main.css&lt;/code&gt; and the source file &lt;code class=&quot;highlighter-rouge&quot;&gt;css/sass/global.css&lt;/code&gt;. You can use the &lt;code class=&quot;highlighter-rouge&quot;&gt;css/sass/global.scss&lt;/code&gt; to import all other Sass files in the project:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'css/main.css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'css/sass/global.scss'&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;loading-the-tasks&quot;&gt;Loading the tasks&lt;/h3&gt;

&lt;p&gt;Before Grunt can run the tasks, we need to load them—each dependency will need to be loaded in the same way. This is simply done by the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loadNpmTasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'grunt-contrib-sass'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;creating-the-tasks&quot;&gt;Creating the tasks&lt;/h3&gt;

&lt;p&gt;Next, we create the actual tasks which we run from Terminal. Below is a set up for both development and distribution tasks.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Create Default Task&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;registerTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'default'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'sass:dev'&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Compile Sass with dev settings&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Create Distribution Task&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;registerTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'dist'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'sass:dist'&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Compile Sass with distribution settings&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As the development settings are likely to be used often, I use the &lt;code class=&quot;highlighter-rouge&quot;&gt;default&lt;/code&gt; task to run any development settings. The default task is run by typing &lt;code class=&quot;highlighter-rouge&quot;&gt;grunt&lt;/code&gt;, which is shorter to type than, say, &lt;code class=&quot;highlighter-rouge&quot;&gt;grunt dev&lt;/code&gt;. Saves a few characters!&lt;/p&gt;

&lt;p&gt;When your project is ready for deploying, run &lt;code class=&quot;highlighter-rouge&quot;&gt;grunt dist&lt;/code&gt; and voila! Your code is now ready to go.&lt;/p&gt;

&lt;h2 id=&quot;watch-it&quot;&gt;Watch it!&lt;/h2&gt;
&lt;p&gt;Now we have our tasks set up, we can get Grunt to watch files for changes, execute tasks and then reload the page for us. Firstly, install &lt;a href=&quot;https://github.com/gruntjs/grunt-contrib-watch&quot;&gt;Grunt watch&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;npm install grunt-contrib-watch &lt;span class=&quot;nt&quot;&gt;--save-dev&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Configure the task:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Watch files&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Watch .scss files&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'css/sass/**/*.scss'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'sass:dev'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Live reload files&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;livereload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;livereload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;'css/**/*.css'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;'**/*.html'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Load the plugin:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;grunt.loadNpmTasks&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'grunt-contrib-watch'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now we can simply type &lt;code class=&quot;highlighter-rouge&quot;&gt;grunt watch&lt;/code&gt; into Terminal and it will watch for changes to any &lt;code class=&quot;highlighter-rouge&quot;&gt;.scss&lt;/code&gt; files, then run the &lt;code class=&quot;highlighter-rouge&quot;&gt;sass:dev&lt;/code&gt; task automatically. To reload the browser, &lt;a href=&quot;http://livereload.com&quot;&gt;LiveReload&lt;/a&gt; is configured to watch any changes to &lt;code class=&quot;highlighter-rouge&quot;&gt;.css&lt;/code&gt; files. I’ve also specified to reload any &lt;code class=&quot;highlighter-rouge&quot;&gt;.html&lt;/code&gt; files so you can see how it works. You will need to install the &lt;a href=&quot;http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-&quot;&gt;LiveReload extension&lt;/a&gt; for either Safari, Chrome or Firefox.&lt;/p&gt;

&lt;h2 id=&quot;taking-it-further&quot;&gt;Taking it further&lt;/h2&gt;
&lt;p&gt;This is only a very small amount of what Grunt is capable of. I’d recommend reading through the documentation and checking out the &lt;a href=&quot;http://gruntjs.com/plugins&quot;&gt;Grunt plugins&lt;/a&gt; available (there are lots!) to see what else Grunt can do.&lt;/p&gt;

&lt;p&gt;I’ve set up a Grunt starter project which I use as a base—you can find it on &lt;a href=&quot;https://github.com/markgoodyear/grunt-starter&quot;&gt;GitHub&lt;/a&gt;. Feel free to adapt it, improve it and learn from it. Currently, it includes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;JavaScript linting, concatenation and minification&lt;/li&gt;
  &lt;li&gt;Sass compiling with development and production options&lt;/li&gt;
  &lt;li&gt;Sass sourcemaps (requires Sass 3.3.0)&lt;/li&gt;
  &lt;li&gt;Rasterizing .svg files&lt;/li&gt;
  &lt;li&gt;Compress .jpg/.jpeg, .png and .svg files&lt;/li&gt;
  &lt;li&gt;Reload the browser on file changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;What are you waiting for? Get Grunting!&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Tue, 30 Jul 2013 00:00:00 +0000</pubDate>
        <link>http://markgoodyear.com/2013/07/automating-your-workflow-with-grunt/</link>
        <guid isPermaLink="true">http://markgoodyear.com/2013/07/automating-your-workflow-with-grunt/</guid>
        
        
      </item>
    
  </channel>
</rss>
