Structuring Your Gulp WorkflowWritten by Larry Botha |
There are a lot of great articles out there on how to use Gulp to improve your workflow, but something that one seldom comes across is how to effectively manage your workflow.
In this article, I’ll build a small workflow that will watch
.scss files, compile Sass to CSS, and inject changes into your page using BrowserSync, while focusing on a clean and maintainable structure.
BrowserSync is similar to LiveReload, but on steroids. If you don’t yet know what BrowserSync can do to improve your workflow, take a gander at Tuts+’s Intro To BrowserSync.
This article assumes you are familiar with installing and requiring npm packages.
Gulp Folder Structure
Many Gulp workflows are managed via a single Gulpfile. Gulpfiles can quickly become unwieldy.
Large files are a nightmare when writing any sort of code. Splitting concerns to their own files makes navigating and maintaining projects easier.
The following is the go-to structure we’ve found excellent for managing Gulp tasks at Fixate, and will form the basis for our workflow here:
What we’ve got here can be outlined as follows:
- our Gulpfile sits in the root of our project
gulp/folder contains our gulp-specific files
- inside this folder we keep a config that our tasks will share to keep our settings DRY
- we also store our tasks in their very own
- each category of task gets its own file, properly separating concerns
With this structure in place, we’re ready to get down to building workflow zen.
This Gulpfile is responsible for creating a global instance of BrowserSync that we can access in tasks, requiring all the files in the
gulp/tasks/ folder, and creating the
default gulp task, which will fire up our currently non-existent
watch task. If you’re not keen on implicitly loading all the tasks with
require-dir, you can always explicitly require them.
Note: I’m not a fan of anything implicit in code, nor global properties, but since this isn’t the actual production code, we let it slide in favour of being pragmatic.
And that’s it! Short and sweet, and we know exactly what our Gulpfile is responsible for.
Before we get into our tasks, it’s important that repeated configurations and options are managed in their own file to make tasks manageable, and eliminate hard-coding the same values in multiple places.
Most gulp tasks expect a
src – a file or list of files on which to operate, and a
dest – a location to which to output the result of the task.
Let’s add these to our
What we’re implying from this config is that we have
src/scss/ directory where our
.scss files can be found, and a destination at
built/css/ – likely where we want our css to be built and served from.
Any configs can be added to this object, and accessed by our tasks.
The Watch Task
In our Gulpfile we added the
default Gulp task. It has one dependency: run the
Now that we have our config ready, let’s take a look at our
gulp-watch, and our
We then create the actual
watch task, which first starts BrowserSync, and then watches for changes to
.scss files at the path we defined in our config. When a
.scss file is changed, a
css:watch task will be run, which we are yet to create.
css:watch? We’re going to be splitting our CSS tasks into their own concerns, too.
Gulp is great for creating tasks that perform only one job, and we’re going to lead with that in mind.
The CSS Tasks
So far we’ve got our watch task that will watch for changes to CSS files, and then run a
Now we can put together our CSS tasks to build our CSS for us.
We now have two tasks.
css task, is dedicated to compiling
.scss files from our src, automatically adding our prefixes using the excellent Autoprefixer, and writing files out to our destination.
css:watch task, is responsible for running our first task, and then following up by telling BrowserSync to reload any CSS files. The reason we can tell BrowserSync to reload is because we have access to the global object we defined in our Gulpfile.
Splitting our tasks like this ensures that our tasks are responsible for as little as possible, making them easy to reuse, and easy to understand.
We’re almost done! The only thing missing is our BrowserSync task.
watch task is elegantly linked to our CSS compilation and BrowserSync reloading.
As in the
css:watch task, we’re going to leverage the global instance of BrowserSync, instantiated in our Gulpfile.
Remember, too, that the
browser-sync task is a dependency on our
watch task – BrowserSync starts up before any watching even begins.
Let’s get our BrowserSync task up and running.
browser-sync task initialises our BrowserSync instance for the first time, allowing us to notify it when it should reload from other tasks. This is distinct from instantiating it – the BrowserSync instance doesn’t do anything until we explicitly initialise it with
In BrowserSync’s options, we tell it to serve a site from our
built/ folder, defined in our config. If we had an
index.html linking our compiled CSS, we would be all set to begin working efficiently on our new project.
With everything set up, the last thing to do is to run gulp, and get to work!
In a few seconds we’ll have a server running at
built/, watching for changes to our
.scss files, and live injecting those changes into our site.
Creating a manageable automated workflow is an easy task with Gulp. Not only can we improve the maintainability by refactoring our folder structure, but we can also think about tasks in a focused way, making it easy to reason about how our tasks work together and on their own, and making adding new tasks effortless.