Front End Development with Gulp, Twig, and SCSS

Gulp can help boost your front-end project productivity. It includes running, compiling, and automating tasks that usually take repetitive work.

Code Road
7 min readNov 2, 2018
Gulp, Twig and SCSS HTML front-end project
Gulp, Twig, and SCSS

Gulp, Twig, and SCSS are the highlights of this story. I'm writing the story down for projects that use these tools. This is part of my HTML and SCSS development series.

Building on top of NodeJS and NPM ecosystem, Gulp gaining popularity among front-end developers. Gulp is a streaming task runner that involved automating and optimizing your project. When your projects get very big and difficult to maintain, Gulp eases you with helpful and handy tasks built-in. For example, splitting your project file into smaller chunks and modular will save time on your production.

Twig is a modern templating engine for PHP language, but it also could be used outside of PHP language itself and basic HTML tag-based.

SASS is completely compatible with all versions of CSS. SCSS files are a part of SASS syntax that is compiled to generate the CSS and which they have their slogan “CSS with superpowers”.

Getting Started

I assume you are already familiar with NodeJS and the first thing we are going to install is the node modules package that is necessary for this project. List all the packages and install them manually for the Gulp environment below:

$ npm install browser-sync gulp gulp-autoprefixer gulp-concat gulp-data gulp-plumber gulp-sass gulp-sourcemaps gulp-twig gulp-watch

Highlights

  1. gulp-autoprefixer : gulp cross-browser tool for autoprefixer css property.
  2. gulp-concat : for concatenate files by directory.
  3. gulp-data : for attaching data to the file object for other plugins to consume, in this case, our HTML from the Twig templating system.
  4. gulp-plumber : for restarting the gulp stream if an error occurs.
  5. gulp-sass : for our CSS preprocessor written in SASS lang.
  6. gulp-sourcemaps : for source mapping of our source codes in the dev tool.
  7. gulp-twig : for our HTML templating system from sensiolabs.org.
  8. gulp-watch : for watching file changes and emit events if occur.

This command will set up our Gulp projects all with the dependencies, or you can add the project dependencies in the package.json file at the document root.

{
"name": "gulp-twig-scss",
"version": "1.0.0",
"description": "Frontend development using Gulp, Twig and SCSS",
"main": "gulpfile.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/dyarfi/gulp-twig-scss"
},
"keywords": [
"twig",
"gulp",
"HTML",
"frontend",
"SCSS"
],
"author": "Dykraf",
"license": "ISC",
"homepage": "https://dykraf.com",
"dependencies": {
"browser-sync": "^2.26.3",
"gulp": "^3.9.1",
"gulp-autoprefixer": "^6.0.0",
"gulp-concat": "^2.6.1",
"gulp-data": "^1.3.1",
"gulp-plumber": "^1.2.0",
"gulp-sass": "^4.0.2",
"gulp-sourcemaps": "^2.6.4",
"gulp-twig": "^1.2.0",
"gulp-watch": "^5.0.1"
}
}

Or you could just clone the project and run npm install to get started.

Creating a project directories root structure:

— project_root/
— — build/
— — — assets/
— — — — css/
— — — — — main.css
— — — — js/
— — — — — script.js
— — client/
— — — data/
— — — — index.twig.json
— — — templates/
— — — — index.twig
— — — — blocks/
— — — — — block-main-top.twig
— — — — — block-main-bottom.twig
— — — — includes/
— — — — — footer.twig
— — — — — head.twig
— — — — —header.twig
— — — — — scripts.twig
— — — — —styles.twig
— — — — layouts/
— — — — — default.twig
— — gulpfile.js
— — node_modules/
— — package.json
— — scss/
— — — vendors/
— — — — bootstrap/
— — — — — bootstrap.scss
— — — — main.scss

Create a gulpfile.jsin the project root and add these Gulp file setting for the project:

/*global require*/
"use strict";
var gulp = require('gulp'),
path = require('path'),
data = require('gulp-data'),
twig = require('gulp-twig'), // Decided to use twig instead of pug, because already familiar with it
prefix = require('gulp-autoprefixer'),
sass = require('gulp-sass'),
plumber = require('gulp-plumber'),
concat = require('gulp-concat'),
sourcemaps = require('gulp-sourcemaps'),
browserSync = require('browser-sync'),
fs = require('fs');
/*
* Directories here
*/
var paths = {
build: './build/',
sass: './scss/',
css: './build/assets/css/',
data: './client/data/'
};
/**
* Compile .twig files and pass data from json file
* matching file name. index.twig - index.twig.json into HTMLs
*/
gulp.task('twig', function () {
return gulp.src(['./client/templates/*.twig'])
// Stay live and reload on error
.pipe(plumber({
handleError: function (err) {
console.log(err);
this.emit('end');
}
}))
.pipe(data(function (file) {
return JSON.parse(fs.readFileSync(paths.data +
path.basename(file.path) + '.json'));
}))
.pipe(twig())
.on('error', function (err) {
process.stderr.write(err.message + '\n');
this.emit('end');
})
.pipe(gulp.dest(paths.build));
});
/**
* Recompile .twig files and live reload the browser
*/
gulp.task('rebuild', ['twig'], function () {
// BrowserSync Reload
browserSync.reload();
});
/**
* Wait for twig, js and sass tasks, then launch the browser-sync Server
*/
gulp.task('browser-sync', ['sass', 'twig', 'js'], function () {
browserSync({
server: {
baseDir: paths.build
},
notify: false,
browser:"google chrome"
});
});
/**
* Compile .scss files into build css directory With autoprefixer no
* need for vendor prefixes then live reload the browser.
*/
gulp.task('sass', function () {
return gulp.src(paths.sass + 'vendors/main.scss')
.pipe(sourcemaps.init())
// Stay live and reload on error
.pipe(plumber({
handleError: function (err) {
console.log(err);
this.emit('end');
}
}))
.pipe(
sass({
includePaths: [paths.sass + 'vendors/'],
outputStyle: 'expanded'
}).on('error', function (err) {
console.log(err.message);
this.emit('end');
})
)
.pipe(prefix(['last 15 versions', '> 1%', 'ie 8', 'ie 7'], {
cascade: true
}))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(paths.css));
});
/**
* Compile .js files into build js directory With app.min.js
*/
gulp.task('js', function(){
return gulp.src('build/assets/js/script.js')
.pipe(sourcemaps.init())
.pipe(concat('script.min.js'))
.on('error', function (err) {
console.log(err.toString());
this.emit('end');
})
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('build/assets/js'));
});
/**
* Watch scss files for changes & recompile
* Watch .twig files run twig-rebuild then reload BrowserSync
*/
gulp.task('watch', function () {
gulp.watch(paths.build + 'assets/js/script.js', ['js', browserSync.reload]);
gulp.watch(paths.sass + 'vendors/main.scss', ['sass', browserSync.reload]);
gulp.watch([
'client/templates/**/*.twig',
'client/data/**/*.twig.json'
],
{cwd:'./'},
['rebuild']);
});
// Build task compile sass and twig.
gulp.task('build', ['sass', 'twig']);
/**
* Default task, running just `gulp` will compile the sass,
* compile the project site, launch BrowserSync then watch
* files for changes
*/

gulp.task('default', ['browser-sync', 'watch']);

SCSS files

Vendors
./scss/vendors/main.scss
will be compile into ./build/assets/css/main.css

We can include SCSS library such as Bootstrap SCSS in our project by imports on the main.scss:

// ****** Our base variables ******* //$font-family-base : 'Raleway', sans-serif;
$font-family-head-base : 'Nothing You Could Do', cursive; // Custom
$font-family-lead-base : 'Montserrat', sans-serif; // Custom
// Font Weight Base
$font-weight-light: 100 !default;
$font-weight-normal: 500 !default;
$font-weight-bold: 700 !default;
@import "_variables"; // --- Vendors Variables
@import "bootstrap/bootstrap"; // --- Vendors Bootstrap 4

Twig templates

Layouts
./client/templates/layouts/default.twig

<!doctype html>
<html lang="zxx">
<head>
{% include "../includes/head.twig" %}
</head>
<body>
<!-- HEADER -->
{% include "../includes/header.twig" %}

<!-- MAIN -->
<main>
{% block content %}
{% endblock %}
</main>

<!-- FOOTER -->
{% include "../includes/footer.twig" %}

<!-- SCRIPTS -->
{% include "../includes/scripts.twig" %}
</body>
</html>

Include Tags
./client/templates/includes/head.twig

   <title>{{ title }}</title>
{% include "../includes/styles.twig" %}

./client/templates/includes/styles.twig

   <!-- fonts.googleapis.com/css --> 
<style>@import url('https://fonts.googleapis.com/css?family=Nothing+You+Could+Do%7CRaleway:100,200,300,400,500,600,700,800,900%7CMontserrat:100,200,300,400,500,600,700,800,900');</style>
<!-- main.css -->
<link rel="stylesheet" href="assets/css/main.css">

./client/templates/includes/header.twig

   <header>
<!-- insert your header here -->
</header>

./client/templates/includes/footer.twig

   <footer>
<!-- insert your footer here -->
</footer>

HTML Blocks
./client/templates/blocks/block-main-top.twig

<!-- insert your top html blocks here -->

./client/templates/blocks/block-main-bottom.twig

<!-- insert your bottom html blocks here -->

Index HTML Page
./client/templates/index.twig

{% extends "layouts/default.twig" %}{% block content %}    <!-- =============== Block Main Top =============== -->
{% include 'blocks/block-main-top.twig' %}
<div class="container">
<div class="col-lg-7 text-center mx-auto border border-warning py-4 px-5 my-5">
<h1 class="display-1 text-warning">Gulp, Twig and SCSS</h1>
<span class="text-secondary">{{description}}</span>
</div>
</div>
<!-- =============== Block Main Bottom =============== -->
{% include 'blocks/block-main-bottom.twig' %}
{% endblock %}

Json Data for index page
./client/data/index.twig.json will be directly injected and processed into our HTML tags, this will be done by Gulp on gulp-data section, see thegulpfile.js for more information.

{    
"title":"Web title page",
"description":"A Gulp setup by <a href=\"https://github.com/dyarfi\">@dyarfi</a>"
}

After the setup you can begin the project by typing $ gulpin your terminal at the project root and Gulp will watch and compile all the files.

Terminal console output in Gulp, Twig and SCSS front-end HTML project.
Gulp tasks running on port 3002

Gulp will open up a browser automatically in this case “chrome browser” just like in the “browser-sync” gulpfile.js setting.

Preview of the HTML in Gulp, Twig and CSS project.
Chrome browser fired up on port 3002

The development workflow is to create HTML pages with the .twig template pages inside the client/templates/ folder and then create the JSON data twig file on each created twig page in the client/data/ folder. All *.twig.json and *.twig files created will be processed and automatically reload and produces the HTML pages in the build/ folder that Gulp serves.

Gulp will automatically reload browser if there is any changes on the .twig, .json, .scss, and .js files and build/assets/ folders. All your final HTML project production ready will be all compiled in ./build/ directory.

Live preview on the project how Gulp builds all the files.

You can see the whole project here https://github.com/dyarfi/gulp-twig-scss

Cheers and happy coding!

[Updated: 01–14–2019]: The complete HTML pages project link or preview
[Updated: 24–04–2020]: Add link for upgrading Gulp 3 to Gulp 4 workflow

--

--

Code Road

I write topics such as React/NextJS, Vue/NuxtJS, GraphQL, Laravel, TailwindCSS, Bootstrap, SEO, Headless CMS, Fullstack, and web development.