Front end Development with Gulp, Twig, and SCSS — HTML Pages
How to make automated HTML pages generated using GulpJS. A Javascript toolkit for front-end web development that helps your development workflow to automate the repetitive task and streams your build system.
After setting up our Gulp project, now we can create our HTML pages and block structures for the complete front-end development workflow. This is the preview of the end result project looks like.
So why did we start this project using a twig or other templates library as a template engine?
Well, can you imagine when your HTML project is getting bigger and bigger with many assets that are hard to maintain? Using a template engine is your answer. It allowed you to separate and include parts of your HTML tags so they can be included in the pages that used that parts only, instead of maintaining and updating your whole HTML page one by one.
We already set up our basic project using Gulp Version 3.9.* and next, we want to continue building other pages but we need some little adjustments so we could reduce repetitive tasks on our workflow.
Getting Started
Open your Gulp project, we should be continued where we left off to create the things needed to create an HTML’s based project. Or maybe for a reminder just type in the console:
$ npm install browser-sync gulp gulp-autoprefixer gulp-concat gulp-data gulp-plumber gulp-sass gulp-sourcemaps gulp-twig gulp-watch
Updated package.json file :
{
"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": "Defrian Yarfi",
"license": "ISC",
"homepage": "https://dyarfi.github.io",
"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"
}
}
Updated gulpfile.js file :
/*global require*/
"use strict";var gulp = require('gulp'),
path = require('path'),
data = require('gulp-data'),
twig = require('gulp-twig'), // Decided to use twig, 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/',
scss: './scss/',
data: './client/data/',
js: './client/js/'
};/**
* Compile .twig files and pass in data from json file
* matching file name. index.twig - index.twig.json
*/
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');
}})
)
// Load template pages json data
.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.scss + '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.scss + 'vendors/'],
outputStyle: 'compressed'
}).on('error', function (err) {
console.log(err.message);
// sass.logError
this.emit('end');
})
)
.pipe(prefix(['last 15 versions','> 1%','ie 8','ie 7','iOS >= 9','Safari >= 9','Android >= 4.4','Opera >= 30'], {
cascade: true
}))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(paths.build + '/assets/css/'));
});/**
* Compile script.js files into build assets js directory concat to script.min.js
*/
gulp.task('js', function(){
return gulp.src(paths.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(paths.build +'assets/js'));
});/**
* Watch scss files for changes & recompile
* Watch .twig files run twig-rebuild then reload BrowserSync
*/
gulp.task('watch', function () {
// Script JS
gulp.watch(paths.js + 'script.js', ['js', browserSync.reload]);
// SCSS files or main.scss
gulp.watch(paths.scss + '**/*.scss', ['sass', browserSync.reload]);
// Assets Watch and copy to build in some file changes
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']);
After that, we can run $ gulp
in the terminal and wait for the browser to load our project. I am including some external resources such as jQuery, Bootstrap JS, dependencies, fonts also images in this project. You could download v4.1.2 or the latest Bootstrap SCSS in their repository for use in this project.
1. Header
I am going to update my ./client/template/includes/header.twig
file by adding some navigation to the pages that we will create.
<header>
<!-- /.navbar -->
<nav class="navbar navbar-expand-md navbar-light bg-light shadow-sm">
<div class="container-fluid font-weight-bold">
<a class="navbar-brand ml-3" href="#"><i class="text-warning ">//</i> <span class="text-success">IOTA Connect</span></a>
<button class="navbar-toggler text-white" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ml-auto text-right">
<li class="nav-item active">
<a class="nav-link" href="index.html">Home<span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="about.html">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="service.html">Service</a>
</li>
<li class="nav-item">
<a class="nav-link" href="contact.html">Contact</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
2. Scripts
On the header, we already included the BS 4 navbar default for our navigation. Adding up another JS library for updates to our HTML pages. Modify and add the bootstrap JS and other dependencies on the scripts tags ./client/templates/includes/scripts.twig
:
<!-- jquery.slim.min.js -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<!-- popper.min.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<!-- bootstrap.min.js -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<!-- script.min.js -->
<script src="./assets/js/script.min.js"></script>
3. Creating the JSON Data for HTML template pages
In the client/data/
directory we create a new file called about.twig.json which looks like this client/data/about.twig.json and the browser will reload.
{
"title" : "About page title",
"description" : "About description content page"
}
4. Creating the HTML template pages
In the client/templates/ directory create a new file called about.twig or look like this code below on client/templates/about.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">{{title}}</h1>
<span class="text-secondary">{{description}}</span>
</div>
</div> <!-- ================== Block Main Bottom ================== -->
{% include 'blocks/block-main-bottom.twig' %}{% endblock %}
Gulp gulp-data
with gulp-twig
will automate the build HTML file after we create the about.twig
and injects data to the HTML file from the about.twig.json that we previously created.
The build folder will be the end result folder from automating generated HTML template pages from this gulp project :
$ tree build
build
├── about.html
├── assets
│ ├── css
│ │ ├── main.css
│ │ └── main.css.map
│ └── js
│ ├── script.min.js
│ └── script.min.js.map
├── contact.html
├── index.html
└── service.html
The complete and final source code project on this post: https://github.com/dyarfi/gulp-twig-scss/tree/development/
The preview on the automated build HTML pages :
https://dyarfi.github.io/gulp-twig-scss/development/
There are many ways to automate tasks with Gulp, this one was just a practical workflow that I already implement in my projects.
Read also:
Thank you for dropping by and happy coding!
References:
https://sass-lang.com/
https://gulpjs.com/
Closing
Please do follow me to get more tips and tricks from web development, thank you!