Gulpjs: watch and livereload
In the previous article, we talked about gulpjs and we managed to create a couple of gulp tasks. we agree that to access a task we either run gulp [Task name] for public tasks or just gulp to run the default flow.
But to be honest, it's a little bit tedious to run the command every time we modify a file, whether it's a big or a small change, don't worry gulp has an easy way to keep watching for files changes and run any task you specify.
in the last article we ended up with gulpfile.js that looks like this
const { series, src, dest } = require('gulp'); const uglify = require('gulp-uglify'); const cleanCSS = require('gulp-clean-css'); function minifyCSS(){ return src('src/css/*.css') .pipe(cleanCSS()) .pipe(dest('public/dist/css')); } function minifyJS(){ return src('src/js/*.js') .pipe(uglify()) .pipe(dest('public/dist/js')); } exports.minifyCSS = minifyCSS exports.default = series(minifyCSS, minifyJS);
We will use this file as a base, and we will modify it to achieve the intended behavior
Watch for file changes
Gulp provides an API to listen for files changes, the "watch" function is exported from gulp, that watches for changes to files that match a pattern and executes the task when a change occurs, it supports several actions such as 'add', 'change', 'unlink', etc...
watch('src/*.js', { events: 'all' }, function(cb) { cb(); });
The above code will watch for all events that will affect .js files in the src folder, then it will execute the function, the function could be a simple gulp task, or it could a group of tasks, executed as series or parallel.
it's worth mentioning, that watch function will not be executed upon the first call, instead it will wait for the first file change, to override this behavior, you can provide ignoreInitial: false option.
watch('src/*.js', { ignoreInitial: false },function(){})
I think now it's the time to modify our file, to do so, we add another export to our gulpfile.js, the first thing we will watch css files and run minifyCSS, and when a js file changes we will run minifyJS task.
exports.watch = function () { watch("src/css/*.css", minifyCSS); watch("src/js/*.js", series(minifyJS)); };
You notice that I wrapped the minifyJS in series execution, you can as well add any tasks you need.
Finally, let's try this by running the following command:
$ gulp watch
Integrating a server (optional)
Now it's the time to a run our app on a server if you are not already doing that.
I will use node static server for this example, you can use any other server you like.
First, I'll install it into my app directory by running the following following command:
$ npm i --save static-server
In you project root directory create a file and call it server.js, it should look like this:
const staticServer = require("static-server"); const server = new staticServer({ rootPath: "./public", port: 3000, }); server.start(function(){ console.log("server started on port "+ server.port) });
We are using the static-serve package, and pointing it to public folder where our index.html is placed, and making sure that the server is running on the port 3000, and finally calling the start to initiate the server.
Finally we run this server by executing the following command:
$ node server.js
Now we are ready to browse our app on localhost:3000.
Integrating livereload
Unfortunately, livereload is not a built in functionality in gulp, but there is a plugin that helps integrating it.
At first we need to install gulp-livereload plugin to able to use it our project.
$ npm i --save-dev gulp-livereload
Then we modify our gulpfile.js, by importing gulp-livereload.
const liveReload = require("gulp-livereload");
After that we modify our watch function, by triggering liveReload.listen function, wich accepts some options, for the time being I'll configure the port only cause we will need it later.
exports.watch = function () { liveReload.listen({ port: 8010, }); watch("src/css/*.css", minifyCSS); watch("src/js/*.js", series(minifyJS)); };
Now it's the time to decide which tasks should trigger the livereload, we do so by chaining pipe(liveReload()) when needed.
In our case we will trigger it in both minifyCSS and minifyJS tasks after moving the files to the dist folders.
function minifyCSS() { return src("src/css/*.css") .pipe(cleanCSS()) .pipe(dest("public/dist/css")) .pipe(liveReload()); } function minifyJS() { return src("src/js/*.js") .pipe(uglify()) .pipe(dest("public/dist/js")) .pipe(liveReload()); }
The last piece of the puzzle, is a javascript file that we need to add to our site, and we have two methods to make it happen, either by adding a livereload extension to your browser, such as chrome livereload, or by adding the javascript file directly to your index.html file.
<script src="https://localhost:8010/livereload.js"></script>
Note: the port I used here is the same port we configured in gulpfile.js in liveReload.listen function.
Finally, let's execute watch and see what happens :)
$ gulp watch
Our final gulpfile.js should look like this:
const { series, src, dest, watch } = require("gulp"); const uglify = require("gulp-uglify"); const cleanCSS = require("gulp-clean-css"); const liveReload = require("gulp-livereload"); function minifyCSS() { return src("src/css/*.css") .pipe(cleanCSS()) .pipe(dest("public/dist/css")) .pipe(liveReload()); } function minifyJS() { return src("src/js/*.js") .pipe(uglify()) .pipe(dest("public/dist/js")) .pipe(liveReload()); } exports.minifyCSS = minifyCSS; exports.default = series(minifyCSS, minifyJS); exports.watch = function () { liveReload.listen({ port: 8010, }); watch("src/css/*.css", minifyCSS); watch("src/js/*.js", series(minifyJS)); }
You can find the full code as an example on my git repo.