Learning Gulp
Tags: gulp, frontend, setup, beginners
Published: 2020-04-07 18:11:20

---
title: Learning Gulp
published: true
description: My simple Gulp setup explained
tags: gulp, frontend, setup, beginner
---

I have used Gulp for a while but I have never really understood everything in the gulpfile - it just seemed like magic to me. I have always just used examples from others and tweaked what I needed to *get it to work*. Which has been fine, but I decided that I want to learn it properly so for my personal website, I wrote my own gulpfile.

I have only used Gulp 3 before so I wanted learn Gulp 4. I googled my way through it all, I learned which plugins to use for what cause and how to write up my tasks. There are TONS of resources if you google `gulp 4 setup` but I made sure I wasn't just copying and pasting. I want to understand each line of code in my file.

My personal website is in HTML with Sass so I wrote a gulpfile for my needs right now. I want to compile my Sass, add source maps and have a better, easier workflow.

## BrowserSync
Here is how to setup BrowserSync with gulp: [BrowserSync docs](https://browsersync.io/docs/gulp)

## Styles 

### What I wanted
- Compile Sass to CSS
- Add source maps
- Minify my CSS file
- Use BrowserSync to see changes straight away. 

### Packages used
```
const sass = require('gulp-sass');
const cleanCSS = require('gulp-clean-css');
const sourcemaps = require('gulp-sourcemaps');
const browserSync = require('browser-sync').create();
```


### The code
```
function style() {
    return gulp.src('./assets/scss/main.scss')
        .pipe(sourcemaps.init())
        .pipe(sass().on('error', sass.logError))
        .pipe(cleanCSS())
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('./assets/css'))
        .pipe(browserSync.stream())
}
```

### What this method does 
When we do `gulp.src('./assets/scss/main.scss')`, it creates a node stream and reads our file. We can then use our plugins in `.pipe` methods to change the file how we like it until we save it to the final destination using `.pipe(gulp.dest('./assets/css'))`. 

### The plugins 
`sourcemaps.init()`: Initialise Source Maps - package [gulp-sourcemaps](https://www.npmjs.com/package/gulp-sourcemaps).

`sass().on('error', sass.logError)`: Compile my Sass to CSS - package [gulp-sass](https://www.npmjs.com/package/gulp-sass)

`cleanCSS()`: Minify my CSS - package [gulp-clean-css](https://www.npmjs.com/package/gulp-clean-css). I started with [uglify-css](https://www.npmjs.com/package/uglifycss) but noticed (after some debugging) that it broke my source maps! It basically removed the `/*# sourceMappingURL=main.css.map */` part once minified, but this package does not. 

`sourcemaps.write('.')`: Writes my source maps, `('.')` meaning the same directory so it sits next to my main.css file.

`browserSync.stream()`: This is my favourite part and I just learned about this! Instead of using `browserSync.reload()`, this "injects" the css without doing a page refresh. So you see your style changes straight away - it's beautiful. We need to run this after `gulp.dest()` so that the css file has been written.

## Watch
### What I wanted
- Notice when a .html or .scss file has changed
- Run BrowserSync and reload browser if necessary.

### Packages used
```
const browserSync = require('browser-sync').create();
```
### The code
```
function watch() {
    browserSync.init({
        server: {
            baseDir: "./"
        }
    });

    gulp.watch('./assets/scss/*.scss', style);
    gulp.watch('./**/*.html').on('change', browserSync.reload);
}
```
### What this method does 
I first initialise BrowserSync by setting the baseDir. This will set up an Access URL where you can view your website. I am setting this to the same folder my file is in, this is where my index.html is. But if you have a local setup, you can add your url here, eg. `my-site.dev`. 

Then we add our watch tasks.

`gulp.watch('./assets/scss/*.scss', style)` : It accepts 2 parameters, the files you want to watch and the function you want to run. This watches for a change in a `.scss` file that exists within my `assets/scss` folder, and calls my style method that I wrote before. This means that the Sass will automatically compile and BrowserSync will inject the css changes on my site straight away. 

`gulp.watch('./**/*.html').on('change', browserSync.reload)`: Here we are watching for a change in any .html in my project. When a .html file changes, it calls browserSync.reload that refreshes my browser so we will see the change straight away. 

## Set a Default task
Finally I set my default gulp task, which means it will run when I type `gulp` in the cmd line. I want it to use my watch function by default, however I could write `gulp watch` and it will do the same. But it's good for learning purposes and it is quicker to type.

```
exports.default = watch;
```

## Conclusion
I went back and forth a bit, fixing one thing, adding a new plugin that turned out breaking something else but it's all a part of learning. I learned more about npm-packages like I have installed tons but never uninstalled one before - it's just `npm uninstall my-package` who knew!? I know it sounds simple but I have come to a point now where if I get a problem and I solve it myself (by googling obvs), I feel soo good. Like I can figure it out by myself, it's ok. 

Another funny thing that happened is that once I pushed my new gulpfile to my repository on Github, Github was like oh no hun - you got security alerts. Long story short, I figured out that I was on an older node version, moved to a newer one, learned about `npm audit` and fixed the security flaws. [This article](https://itnext.io/fixing-security-vulnerabilities-in-npm-dependencies-in-less-than-3-mins-a53af735261d) helped me and `npm audit fix` worked like a dream. 

So, this was a great learning process for me and I can now use gulp (and npm) more confidently. Here is the final gulpfile if anyone is interested.

### The final gulpfile
```
const gulp = require('gulp');
const sass = require('gulp-sass');
const cleanCSS = require('gulp-clean-css');
const sourcemaps = require('gulp-sourcemaps');
const browserSync = require('browser-sync').create();
 
// Compile, SourceMaps and Minify CSS
function style() {
    return gulp.src('./assets/scss/main.scss')
        .pipe(sourcemaps.init())
        .pipe(sass().on('error', sass.logError))
        .pipe(cleanCSS())
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('./assets/css'))
        .pipe(browserSync.stream())
}

// Watch for file changes
function watch() {
    browserSync.init({
        server: {
            baseDir: "./"
        }
    });

    gulp.watch('./assets/scss/*.scss', style);
    gulp.watch('./**/*.html').on('change', browserSync.reload);
}

exports.style = style;
exports.watch = watch;

// Default function when you run gulp
exports.default = watch;
```