Let me start by saying this: I really love to code!
And I just hate those tasks!
Nothing is more tedious than reading your CSS file for the tenth time to make sure you didn’t duplicate something. And if you’re like me, your egoistic mind will trick you into believing that you can’t make such an error, and you’ll wind up overlooking a number of duplicates.
A couple years ago, I had a long list of services that I used for these tasks. I spent hours copying and pasting code into online generators every time I changed a couple lines of code or added assets. And then had to refresh my browser after every change… come on! I can’t tell you how many times I thought, “If only we could hire somebody to do this for us.” Well today we can—task runners FTW!
This is not a definitive tutorial for using Gulp with Craft, because one company’s configuration is not always right for another’s. There are manyarticles and screencasts about Gulp configuration for Craft out there, and the beautiful thing about task runners is that you can make them work however you like.
In this article, I will share how we use Gulp and encourage you to incorporate these tools into your own workflow.
Our team uses Craft for content management, which handles all of our templating, so we don’t require a template engine. But if you’re working on a front-end prototype, you can compile static HTML using template engines such as Twig, Liquid, Haml, or Jade.
What’s next? We need to give our website some style!
So let’s start with the process that includes most steps—the CSS pipeline.
Most developers today use CSS preprocessors. These give us the ability to make our CSS maintainable by breaking it into small “component” files. In our development process we are using Sass with SCSS syntax, but you could also use Less or Stylus.
The primary use for this is to compile SCSS files into our main CSS file, but we can find some additional uses depending on how we compile files for development or production environment.
During development, we need to quickly debug our errors. This can be difficult when using preprocessors because we see our compiled code, not source files. To debug in places where CSS is rule written, we use sourcemaps. Source maps provide information about what SCSS file holds the rule and on which line it’s written.
What about vendor prefixes?
After we‘re done with development, we need to optimize our code for production. For that, we use a Gulp plugin based on CSSO – CSS Optimizer.
JSCS is a code style linter/formatter, so it checks if we have the right indentation, spacing inside brackets, and how many blank lines we use in specific cases. You can configure coding rules to your needs—read more about this here.
JSHINT is used tool very similar to JSCS, but it provides a little bit more detection in the functionality of your code. Some JSCS and JSHINT functionalities overlap, but to get the best result we suggest using them both.
In the future, we plan to replace this JSCS/JSHINT combination with ESLint. ESLint covers everything we need in one tool, but we simply haven’t found the time to set up our workflow yet. It’s also worth mentioning that one of the cons of ESLint is that it’s configuration docs are a bit confusing.
Online services for optimizing images have been around for quite some time now, so that’s nothing new. But how much time is lost optimizing every image manually and how many times you need to repeat that task? And how can we check for and remove images that we don’t use any more?
Using a Gulp plugin for formatting images like gulp-imagemin, we can optimize all of images that we use for our project using one simple command.
If you’re a Grunt user, you’ll notice that I said “one command” and might ask why don’t we create a task that “watches” for image files. Well... Gulp has a built-in “watch” function that watches over changes in the present file, but doesn’t check for new files. So we can’t automate a task so that it works when a new file is added. However, if you set a task for watching changes inside CSS and JS files, you can add the image optimization task as a Gulp task dependency and just re-run the ‘watch’ command.
Every website today uses some kind of system for displaying icons. Most development teams already take advantage of an SVG sprite system and we are no different.
So let me give you a short explanation of how SVG sprites work. We start by creating one big SVG image containing a number of small SVG images. We include this big SVG image file as part of our HTML file and then we call to one of the icons using SVG xlink:href attribute.
To produce that sprite, we use the Gulp SVG sprite plugin, which optimizes and concatenates SVG images as desired, but we still need to add that markup inside our HTML.
For this, we use gulp-inject. Gulp inject is used to add add a string in our markup, so basically it converts our concatenated SVG sprite to a string that later gets added where we want it placed in our HTML.
In the previous version of our project setup, we injected SVG to partial called icons.html that we later included at top of the body element in markup. But in the latest version, we are storing icons to browser local storage. You can learn more benefits of using local storage in this great article by Osvaldas Valutis.
So now we only need to refresh our browser when we make some changes in our markup. Let me introduce you to Browsersync.
This plugin reloads the browser when we make changes in our HTML or JS and it injects CSS every time you make changes in SCSS files. It works in sync with all activated browsers, and tracks interactions across a website. For example, if you’re filling out a form on your desktop browser, you can check this same behavior on your tablet or mobile devices at the same time.
EditorConfig is not really used with Gulp but it’s still a very important part of our development setup. EditorConfig is a file that helps us define and maintain consistent coding styles between different editors and IDEs. So in short, it makes sure everybody in our team use the same indentations or charset.
Most text editors and IDEs have built-in native support for EditorConfig, but some of them (like my personal favorite Sublime Text) you’ll need to add a plugin.
Why choose Gulp over Grunt, or some newer tool like Webpack?
Ultimately, the choice is up to you. Every tool will have some pros and cons, but for us, Gulp hits the sweet spot.
We started with GruntJS as our first task runner and it was pretty great to use. But with GruntJS, you have a lot complicated configuration. Every step you make during one Gulp task, you need to write as a task. If you remember in my explanation about how Gulp works, I mentioned that everything is saved in a “stream” until we output it in a file. Unfortunately, Grunt requires a file for every step.
Webpack is very powerful and efficient. It includes advanced features like Hot Module Replacement, which is a real revolution. It also has the ability to import CSS files from your JS and other features not seen in Gulp and Grunt. However, the learning curve is much steeper, and I’m not convinced that these functionalities benefit website developers enough to compensate for the amount of learning required.
That said, if you’re primarily in the business of Web app development, I would strongly recommend using Webpack.
There are couple other steps in our development process that we didn’t build in our Gulp configuration, but we find them very interesting.
We created a bash script for downloading the newest version of Craft CMS and replacing Craft configuration files with ours. That is something we plan to move to Gulp so we don’t use too many tools in our process.
We’d also like to transfer our deployment/syncing process to Gulp from DeployHQ.
This way, we won’t have to set exclude files for every project on DeployHQ and we’ll reduce time for syncing databases.
As you can see, including Gulp in your workflow can save a ton of time on repeated tasks. But I want to highlight some other benefits that might not quite so obvious.
One, you don’t need to keep track of all the small, menial stuff. That helps your brain process more important questions, like “Do we use best practices when querying for data in Craft?” or “Do we need to make different components to make our code modular?”
A primary benefit for me is that I can maintain concentration, keeping my focus on the important tasks at hand, rather than having to think about optimizing a couple of images.
After that, you’ll wonder how you could have ever lived without it.
Josip Anić is a front-end developer at Pinkston Digital. Keen on making the most of modern web development techniques, he’s always improving our build processes, resulting in efficient, robust, and easily-maintained deployments. For more articles from Josip and the rest of our team, subscribe to our newsletter: