본문 바로가기
Web/Etc

[Gulp] Getting Started

by llHoYall 2020. 9. 12.

Gulf is introduced as follows:

A toolkit to automate & enhance your workflow. Leverage Gulp and the flexibility of JavaScript to automate slow, repetitive workflows and compose them into efficient build pipelines.

Gulp has many useful plugins, we can use them with Gulp.

 

Let's learn the basics of Gulp.

Installation

You need to install nodejs first. You can find the posting about it.

2020/08/30 - [Web/JavaScript] - [Node] Node.js

 

If you are ready, let's start.

$ yarn add -D gulp gulp-cli
  or
$ npm i -D gulp gulp-cli

Now, add commands in the package.json.

{
  ...
  "scripts": {
    "build": "gulp build",
    "dev": "gulp dev"    
  },
  ...
}

Finally, create a Gulp configuration file gulpfile.js.

const gulp = require("gulp");

const build = (cb) => {
  console.log("building...");
  cb();
};

const dev = (cb) => {
  console.log("developing...");
  cb();
};

module.exports = {
  build: build,
  dev: dev,  
};

Test with command on terminal.

$ yarn build
$ yarn dev

Now, we are ready!!

I will configure the workflow with Gulp for HTML, CSS, JS, and images.

HTML (feat. Pug)

Let's create the Pug files for HTML. It contains the CSS, JS, and images that we will add after.

At first, create src/templates/layout.pug file.

<!DOCTYPE html>
html(lang="en")
  head
    meta(charset="UTF-8")
    meta(name="viewport", content="width=device-width, initial-scale=1.0")
    link(rel="stylesheet", href="css/styles.css")
    script(defer src="js/main.js")
    title Gulp: GettingStarted
  body
    block container

Next, create src/index.pug file. This file extends the previous one.

extends templates/layout

block container
  img(src="img/logo.svg")
  h1 This is a practice of Gulp
  button Random
  div#number Number:!{' '}

Now, install the gulp-pug plugin to handle the Pug with Gulp.

$ yarn add -D gulp-pug

Let's make a workflow!

Modify the gulpfile.js like this.

...

const gpug = require("gulp-pug");

const routes = {
  html: {
    src: "src/*.pug",
    dest: "build"
  }
}

const html = () =>
  gulp.src(routes.html.src).pipe(gpug()).pipe(gulp.dest(routes.html.dest));

const build = gulp.series(html);

const dev = gulp.series(build);

...

Define routes for the HTML.

src() function represents the source files. pipe() function connects the works. gpug() compiles the input pug files. dest() function represents the destination files.

In other words, the gulp files in the src folder are compiled and are put to the build folder.

 

It's time to build!

$ yarn build

Look at the build folder!!

Dev Server

Now, make a development server and check the result.

We need a gulp-webserver plugin, so install it.

$ yarn add -D gulp-webserver

Add it to the gulpfile.js again.

...

const gserver = require("gulp-webserver");

const routes = {
  ...
  watch: {
    html: "src/**/*.pug",
  },
};

const devServer = () => gulp.src("build").pipe(gserver({ livereload: true }));

const watcher = () => {
  gulp.watch(routes.watch.html, html);
};

const dev = gulp.series(build, devServer, watcher);

...

Add routes for watching. It will watch all the pug files in the src folder.

devServer() gets all files in the build folder and pass to the gulp-webserver. The livereload option is true, so if the build folder is changed, automatically reload it.

watch() watches specified files and if there are any changes, the given work is executed.

series() function executes works serial. In a similar way parallel() function executes works parallel.

 

Let's run it.

$ yarn dev

Open the browser and go http://localhost:8000/.

Try to change the pug files. The contents will be applied a few seconds later.

CSS (feat. SCSS)

This time is for CSS. Let's install the ingredients.

$ yarn add -D gulp-sass node-sass

Let's create the SCSS file for styling.

First one is src/scss/_variables.scss file. This file contains the variable for the background color of Gulp's official homepage.

$bgColor: #cf4647;

Next one is src/scss/styles.scss file.

@import "variables";

body {
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: white;
  background-color: $bgColor;
}

Now add a task for this. Modify the gulpfile.js.

...

const gsass = require("gulp-sass");

gsass.compiler = require("node-sass");

const routes = {
  ...
  css: {
    src: "src/scss/styles.scss",
    dest: "build/css",
  },
  watch: {
    ...
    css: "src/**/*.scss"
  }
}

const css = () =>
  gulp
    .src(routes.css.src)
    .pipe(gsass().on("error", gsass.logError))
    .pipe(gulp.dest(routes.css.dest));
    
const watcher = () => {
  ...
  gulp.watch(routes.watch.css, css);
}
    
const build = gulp.series(html, css);

...

Set node-sass as a compiler for gulp-sass.

Add routes for SCSS files. We don't need any other SCSS files, so add only styles.scss file.

And make a task that compiles the SCSS files to CSS files.

 

Now, run it again!

$ yarn dev

Great!! It's well applied.

JavaScript (feat. ES6+)

This time is for JavaScript.

Let's install packages for this.

$ yarn add -D gulp-bro babelify @babel/core @babel/preset-env

I tried to use many plugins and packages, but they were all complex.

I think this method is quite simple so far.

 

Let's some JS files.

The first is src/js/util.js file, which is responsible for generating a random number.

export const random = (max) => Math.floor(Math.random() * max);

The next is src/js/main.js file. This file adds a number to HTML when the button is clicked.

import { random } from "./util";

document.querySelector("button").addEventListener("click", () => {
  if (document.querySelector(".random")) {
    document.querySelector(".random").remove();
  }
  document.querySelector("#number").innerHTML += `<span class='random'>${random(
    10
  )}</span>`;
});

It's Gulp time again.

...

const gbro = require("gulp-bro");
cosnt babelify = require("babelify");

const routes = {
  ...
  javascript: {
    src: "src/js/main.js",
    dest: "build/js"
  },
  watch: {
    ...
    javascript: "src/js/**/*.js"
  }
}  
 
const javascript = () =>
  gulp
    .src(routes.javascript.src)
    .pipe(
      gbro({
        transform: [babelify.configure({ presets: ["@babel/preset-env"] })],
      })
    )
    .pipe(gulp.dest(routes.javascript.dest));
    
 const watcher = () => {
   ...
   gulp.watch(routes.watch.javascript, javascript);
 }
 
 const build = gulp.series(html, css, javascript);
 
 ...

gulp-bro can allow the browserify, which is the bundling JS files.

Moreover, we use babelify for using Babel.

The other parts are the same as before.

 

Let's run and click the Random button.

Image

Now that you've followed up to this point, the image part is incredibly easy.

Let's install gulp-image plugin.

$ yarn add -D gulp-image

This plugin compresses the image.

Let's add this to gulpfile.js.

...

const gimage = require("gulp-image");

const routes = {
  image: {
    src: "src/img/*",
    dest: "build/img"
  },
  watch: {
    ...
    image: "src/img/*"
  }
};

const image = () =>
  gulp.src(routes.image.src).pipe(gimage()).pipe(gulp.dest(routes.image.dest));
  
const watcher = () => {
  ...
  gulp.watch(routes.watch.image, image);
};

const build = gulp.series(html, css, javascript, image);

...

Build again and check the compressed image.

I added the Gulp logo image.

How easy to use gulp!

Detail Up

Let's make a more detailed up.

I'll three more things.

  1. Setup: Clean up the build folder.
  2. CSS: Minify for network usage and support old browsers.
  3. JavaScript: Minify for network usage.

Let's start!! Install plugins.

$ yarn add -D gulp-autoprefixer gulp-clean-css gulp-uglify

Modify gulpfile.js file.

...

const gautoprefixer = require("gulp-autoprefixer");
const gcleancss = require("gulp-clean-css");
const guglify = require("gulp-uglify");
const fs = require("fs");

const removeBuild = (cb) => {
  fs.existsSync("build") && fs.rmdirSync("build", { recursive: true });
  cb();
};

const css = () =>
  gulp
    .src(routes.css.src)
    .pipe(gsass().on("error", gsass.logError))
    .pipe(gautoprefixer())
    .pipe(gcleancss())
    .pipe(gulp.dest(routes.css.dest));

const javascript = () =>
  gulp
    .src(routes.javascript.src)
    .pipe(
      gbro({
        transform: [babelify.configure({ presets: ["@babel/preset-env"] })],
      })
    )
    .pipe(guglify())
    .pipe(gulp.dest(routes.javascript.dest));
    
const setup = gulp.series(removeBuild);

const build = gulp.series(setup, html, css, javascript, image);

..

removeBuild() task removes the build folder.

gulp-autoprefixer plugin adds browser-specific prefixes like "-webkit-" or "-ms".

gulp-clean-css plugin minifies the CSS files.

gulp-uglify plugin minifies and uglifies the JS files.

 

Now, let's enjoy the Gulp world!!

I'll provide you with a whole configuration as a service.

const gulp = require("gulp");
const gpug = require("gulp-pug");
const gsass = require("gulp-sass");
const gautoprefixer = require("gulp-autoprefixer");
const gcleancss = require("gulp-clean-css");
const gbro = require("gulp-bro");
const babelify = require("babelify");
const guglify = require("gulp-uglify");
const gimage = require("gulp-image");
const fs = require("fs");
const gserver = require("gulp-webserver");

gsass.compiler = require("node-sass");

const routes = {
  html: {
    src: "src/*.pug",
    dest: "build",
  },
  css: {
    src: "src/scss/styles.scss",
    dest: "build/css",
  },
  javascript: {
    src: "src/js/main.js",
    dest: "build/js",
  },
  image: {
    src: "src/img/*",
    dest: "build/img",
  },
  watch: {
    html: "src/**/*.pug",
    css: "src/**/*.scss",
    javascript: "src/js/**/*.js",
    image: "src/img/*",
  },
};

const removeBuild = (cb) => {
  fs.existsSync("build") && fs.rmdirSync("build", { recursive: true });
  cb();
};

const html = () =>
  gulp.src(routes.html.src).pipe(gpug()).pipe(gulp.dest(routes.html.dest));

const css = () =>
  gulp
    .src(routes.css.src)
    .pipe(gsass().on("error", gsass.logError))
    .pipe(gautoprefixer())
    .pipe(gcleancss())
    .pipe(gulp.dest(routes.css.dest));

const javascript = () =>
  gulp
    .src(routes.javascript.src)
    .pipe(
      gbro({
        transform: [babelify.configure({ presets: ["@babel/preset-env"] })],
      })
    )
    .pipe(guglify())
    .pipe(gulp.dest(routes.javascript.dest));

const image = () =>
  gulp.src(routes.image.src).pipe(gimage()).pipe(gulp.dest(routes.image.dest));

const devServer = () => gulp.src("build").pipe(gserver({ livereload: true }));

const watcher = () => {
  gulp.watch(routes.watch.html, html);
  gulp.watch(routes.watch.css, css);
  gulp.watch(routes.watch.javascript, javascript);
  gulp.watch(routes.watch.image, image);
};

const setup = gulp.series(removeBuild);

const build = gulp.series(setup, html, css, javascript, image);

const dev = gulp.series(build, devServer, watcher);

module.exports = {
  build: build,
  dev: dev,
};

'Web > Etc' 카테고리의 다른 글

[Nest] Create a simple backend server  (0) 2020.10.02
[Web] Testing Rest API on VS Code  (0) 2020.09.30
[Babel] Getting Started  (0) 2020.09.10
[Pug] Getting Started  (0) 2020.09.09
[Node] yarn  (0) 2020.08.30

댓글