[GUIDE] Gulpfile for React.js projects

[GUIDE] Gulpfile for React.js projects main picture
FEB05

Architecture

When it goes to React.js web application development, we usually work with legacy Redux or new and shiny MobX state management libraries, our gulpfile.js includes options for both libraries.

If React.js app is not isomorphic than the best option for faster website load time would be to compile and serve 1x CSS file, 1x JavaScript file and 1 HTML file.

Here is project tree structure we use on React.js projects: project tree

gulpfile.js

var gulp = require('gulp');
var sass = require('gulp-sass');
var rename = require('gulp-rename');
var util = require('gulp-util');
var size = require('gulp-size')
var uglify = require('gulp-uglify')
var cleanCSS = require('gulp-clean-css');
var browserify = require('browserify');
var babelify = require('babelify');
var watchify = require('watchify');
var buffer = require('vinyl-buffer');
var source = require('vinyl-source-stream');
var browserSync = require('browser-sync');

// No matter what URL query - serve ./index.html
var historyApiFallback = require('connect-history-api-fallback')

// Init JS bundler
var bundler = watchify(browserify('src/js/app.js', watchify.args));
// Use ES6, React, Object rest spread (3 dots syntax)
bundler.transform(babelify, {
  presets: ["es2015", "react", "stage-1"],
  plugins: ["transform-decorators-legacy", "transform-object-rest-spread"]
})

function bundle() {
  return bundler.bundle()
    .on('error', util.log.bind(util, 'Browserify Error'))
    .pipe(source('app.js'))
    .pipe(buffer())
    .pipe(size())
    .pipe(gulp.dest('dist'))
    .pipe(browserSync.stream({ once: true }));
}

function minBundle() {
  process.env.NODE_ENV = 'production';
  browserify('src/js/app.js')
    .transform(babelify, {
      presets: ["es2015", "react", "stage-1"],
      plugins: ["transform-decorators-legacy", "transform-object-rest-spread"]
    })
    .bundle()
    .pipe(source('app.js'))
    .pipe(buffer())
    .pipe(size({ title: 'JS before uglify' }))
    .pipe(uglify())
    .pipe(size({ title: 'JS after uglify' }))
    .pipe(gulp.dest('dist'));
  }

// Rebundle JS for development (fast, big file)
gulp.task('js', bundle);

// Rebundle JS for production (slow, small file)
gulp.task('min-js', minBundle);

// Rebuild SASS for development
gulp.task('sass', function() {
  gulp.src('src/css/app.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(gulp.dest('dist'))
    .pipe(browserSync.stream());
});

// Rebuild SASS for production
gulp.task('min-sass', function() {
  gulp.src('src/css/app.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(size({ title: 'SASS before cleanCSS' }))
    .pipe(cleanCSS())
    .pipe(size({ title: 'SASS after cleanCSS' }))
    .pipe(gulp.dest('dist'));
});

// Copy HTML files (single index.html) to dist folder
gulp.task('copy-html', function() {
  gulp.src('src/index.html')
    .pipe(gulp.dest('dist'))
    .pipe(browserSync.stream({ once: true }));
});

// Copy constants depending on environment
gulp.task('copy-constants-development', function() {
  gulp.src('src/js/constants-development.js')
    .pipe(rename({ basename: 'constants'}))
    .pipe(gulp.dest('src/js'));
});
gulp.task('copy-constants-production', function() {
  gulp.src('src/js/constants-production.js')
    .pipe(rename({ basename: 'constants'}))
    .pipe(gulp.dest('src/js'));
});

gulp.task('default', ['copy-constants-development', 'js', 'sass', 'copy-html'], function() {
  browserSync({
    server: {
      baseDir: 'dist',
      middleware: [ historyApiFallback() ]
    },
    browser: 'google chrome'
  });
  gulp.watch('src/js/**/*.*', ['js']);
  gulp.watch('src/css/**/*.*', ['sass']);
  gulp.watch('src/index.html', ['copy-html']);
});

gulp.task('build', ['copy-constants-production', 'min-js', 'min-sass', 'copy-html'], function() {});

Description

As you can see, we have 2 main tasks for Gulp:

  • constantly rebuild development version by running gulp in Terminal;
  • build production version of website by running gulp build in Terminal.

Thank you for reading! Hope that this article will help you make your Gulp development environment work as you desire.

P.S. This article is actually internal App Dev Academy guide and will be constantly updated with changes required for existing and future projects.