Bundling React with Gulp

Bundling React with Gulp

What is ReactJs?

ReactJs is one of the most trending Javascript libraries open-sourced by Facebook for creating fluent apps. ReactJs makes most of ECMAScript6 specification and hence the need for transforming the code into something that can run across browsers/devices, this is where Gulp comes to the rescue.

Before we dive in to React and Gulp, let us go back where UI consisted of plain HTML-CSS and Javascript (ECMAScript5) files. They first created an HTML page and injected the corresponding Javascript file in a <script> tag that contains all the action events and other event driven tasks. So when the HTML page loads on the browser, it also loads the corresponding Javascript file. Once the page is ready, the user then interacts with the web page and the functions registered in the javascript file are invoked on the relevant actions.

Since React is built on top of Javascript, the basic bootstrap of Application is similar to that we used to do earlier i.e <Bundle broadly explain>. There are other ways to create and build react app such as with Webpack, but in this post we will focus on making things work with help of Gulp.

What is Gulp.js or Gulp Javascript?

Gulp is a Javascript tool that lets you automate tasks like Builds, Minification, Bundling, Compilations, etc. (Visit here for more info https://gulpjs.com/)

We will be creating a React application bundled using Gulp ground-up. Alternatively, if you want to create an ExpressJs app that uses ReactJs for Frontend, this guide will still help.

Also Read: Sitecore Platform Inspection – How To Get Most Out Of It.

Consider a HelloWorld app with below structure:

HelloWorld
├──
client
| └──
components
| | └──
HomePage
| | ├──
home-page.jsx

| | ├── homepage.css
| | └──
index.js
| └──
app.jsx
├──
server

| └── server.js
├──
static
├──
.babelrc
├──
Gulpfile.js
└──
package.json

/* app.jsx */

import React from ‘react’;
import ReactDOM from ‘react-dom’;
import HomePage from ‘./components/HomePage’;

let root_node = document.getElementById(“root”);
ReactDOM.render(
<HomePage/>, root_node);

/* home-page.jsx */

import React, { Component } from ‘react’;

export default class HomePage extends Component {
render() {
return (
<div>

Hello World!!

<br/>
This content is from HomePage!!!
</div>
)
}
}

/* index.js */

export { default } from ‘./home-page.jsx’;

/* Gulpfile.js */
var gulp = require(‘gulp’); // 1
var browserify = require(‘browserify’); //2
var babelify = require(‘babelify’); //3
var source = require(‘vinyl-source-stream’); //4

Let’s take a closer look

1. We first import the “gulp” task runner.

2. Import “browserify”.
     Browserify does the job of combining multiple files into one file. Let’s say you have a main.js file, which uses different modules from other folders like module-1.js and module-2.js, Browserify will merge main.js, module-1.js and module-2.js and output a single js file.

3. Module “babelify” is used for transpiling JS code from ES6 to ES5.

4. Import “vinyl-source-stream”.

When we transpile javascript from ES6 to ES5, we follow a chain of process. But in the end we need a single output file. (bundle.js)

Mostly the output returned from first process might not be of the same type that is expected by the next process. In our case the output returned by browserify is in the form of Stream, so “vinyl-source-stream” helps in converting from stream to string, so that it can be saved as a file.

/* Gulpfile.js */

var paths = {

main_js : [ ‘client/app.jsx’ ]

};

gulp.task(‘js’, function() {
//Browserify bundles the JS.
return browserify(paths.main_js)
.transform(babelify) //———–> transpiles es6 to es5
.bundle()
.on(
‘error’, (err)=>{
console.log(‘JS Error’, err);
})
.pipe(source(
‘bundle.js’))
.pipe(gulp.dest(
‘static/js’));
});

To transform & make it work across browsers we used below babel packages.

@babel/core”
Provides core functionality to transform the code into given specification.

@babel/preset-env”
@babel/preset-env support various available versions of ECMA-Script. Like “es2015” does the transpilaltion of stuff that are new in ES6 to ES5, and “es2016” transpiles what’s new in ES2016 to ES6, etc.

“@babel/preset-react”
This converts JSX content to JS.

Babel needs a configuration file, from which it identifies the input and output specifications for transpilation.

/* .babelrc */

{
“presets”: [“@babel/preset-react”, “@babel/preset-env”]
}

Before going ahead, lets install “gulp-cli” globally, since this gulp-cli will be used to run our tasks written in Gulpfile.js from a terminal.
Note: You can also use locally installed gulp for running task from package.json’s scripts

npm i gulp-cli -g

Install the required dev-dependencies

npm i @babel/core @babel/preset-env @babel/preset-react -SD

npm i gulp browserify babelify vinyl-source-stream -SD

Install the application dependencies

npm i react react-dom -S

Let’s build our React components:

gulp js

And this creates an output file in the folder “static/js/bundle.js”.

Create an index.html in static folder and add bundle.js url in it.

#index.html
<!DOCTYPE html>
<html>
<head>
<title>React App</title>
</head>
<body>
<div id=“root”></div>
<script src=“js/bundle.js” ></script>
</body>
</html>

Since the HTML file must be hosted on a server, lets create an http server to serve this file to browser, you can also use any other HTTP Server or Apache, etc.

I’ll be using ExpressJs to create a server,

/* server/server.js */
/* server.js */

let express = require(‘express’);
let app = express();

app.use(express.static(__dirname+‘/../static’));

let server = app.listen(3000, ()=>{
console.log(`Server started listening on 3000`);
});

Install ExpressJS from npm

npm i express -S

Start the server

node server/server.js

Now load the URL: “http://localhost:3000/” in browser

Awesome… We just completed creating our HelloWorld react app using gulp.

Engage Development Mode.
Let’s add some more features to our application and to its build process.

1. Adding stylesheets and its bundling in the build process.

2. Enable auto build mode for development.

3. Adding Stylesheets

For this let’s enhance our current Gulpfile.js to capture css files.

/* Gulpfile.js */

var concat = require(‘gulp-concat’);

var paths = {
main_js : [
‘client/app.jsx’ ],
css : [
‘client/components/**/*.*css’ ]
};


gulp.task(
‘css’, function(callback) {
return gulp.src(paths.css)
.pipe(concat(
‘main.css’))
.pipe(gulp.dest(
‘static/css/’));
});


Now add your classes in html with “className” attribute. className is a special prop attribute in React for “class” for applying dynamic classes when rendering components.

/* home-page.jsx */
….
return (
<div className=“home-container”>

Hello World!!

<br/>
This content is from HomePage!
</div>
….

Create your new stylesheet file.

/* client/components/HomePage/homepage.css */
.home-container{
background: #DCDCDC;
height:
100%;
width:
100%;
}

Import the generated “main.css” in the index.html

/* index.html */
….
<head>
<title>React App</title>
<link rel=
“stylesheet” href=“css/main.css”>
</head>
….

Lets install newly added dependency.

npm i gulp-concat -SD

Build the app with below commands and start the server.

gulp js

gulp css

node server/server.js

Gulps’s Watch Begins…. For this file, and all the files to come…

Moving to the next part now, “Enabling auto build mode” for development…

While you code, assign the task of “retriggering the build and starting up the http server” once you save the modifications in jsx or css file. This is achievable with Gulp.

Lets modify the Gulpfile.js file and add one more task to it.

/* Gulpfile.js */
….
var gls =
require(‘gulp-live-server’);
….
….

var paths = {
main_js : [
‘client/app.jsx’ ],
css : [
‘client/components/**/*.*css’ ],
js : [
‘client/**/*.js*’ ]
};
….

gulp.task(‘dev’, gulp.series(‘css’, ‘js’ , function () {
// Generic watch tasks for SASS and Browserify
gulp.watch(paths.css, gulp.series(
‘css’ ));
gulp.watch(paths.js, gulp.series(
‘js’));

// Start the app server.
var server = gls(‘server/server.js’, { stdio : ‘inherit’ });
server.start();

// Reload server when backend files change.
gulp.watch([
‘server/**/*.js’ ], function() {
server.start.bind(server)();
});

// Notify server when frontend files change.
gulp.watch([
‘static/**/*.{css,js,html}’ ], function(file) {
server.notify(file);
});
}));

To see how this works install “gulp-live-server” and run the new gulp task “dev”

npm i gulp-live-server -SD

gulp dev

and now once the server is started, try to modify any JSX or CSS file and save it.

Once you save the file, the gulp watch task rebuilds the required files for you, you just need to refresh the browser to see the changes without restarting the server.

Also read: The Future Ready Enterprise eCommerce Business

Bonus Trick….
Production Build Tasks With Gulp..

Lets see how to minify your code for production environment.

/* Gulpfile.js */

var buffer = require(‘vinyl-buffer’);

var uglify = require(‘gulp-uglify’);

gulp.task(‘prod’, function() {
// Browserify/bundle the JS.
return browserify(paths.main_js)
.transform(babelify)
.bundle()
.on(
‘error’, (err)=>{
console.log(‘JS Error’, err);
})
.pipe(source(
‘bundle.js’))
.pipe(buffer())
.pipe(uglify())
.pipe(gulp.dest(
‘static/js’));
});

Install the dependency

npm i gulp-uglify vinyl-buffer -SD

Now when you verify the size of the bundle now it would be smaller than what we had in develop mode.

gulp prod

Now if you start the server and check the size of bundle js it would be way smaller than it was earlier.

node server/server.js

Now you have minified version of the react app. Minification reduces the time to load bundle in a browser.

That’s all folks…
We just created react app along with required bundling process for development and production environment.

Contact us to know more about reactjs, react native, gulp.js, gulpifile and more.

Apexon’s expert consulting services help enterprises to support their digital initiatives across various aspects of their businesses, including engineering, talent, and governance. Check out Apexon’s Digital Commerce services or get in touch with us directly using the form below.

Interested in our Digital Commerce Services?

Please enable JavaScript in your browser to complete this form.
Checkboxes
By submitting this form, you agree that you have read and understand Apexon’s Terms and Conditions. You can opt-out of communications at any time. We respect your privacy.