Things I’ve learnt with React.js; ES6 and Browserify

React.js has been the front-end developer’s buzzword for many months now, and it seems that when Facebook eventually release Relay, React will get the framework it needs to truly take off.  I’m just at the point now where I’m looking to build perhaps the most complicated front-end build I’ve done to date.  What better way to get to grips with React?

The joy of React, and presumably Relay when it arrives, is that there’s are no major teething problems at its release, chiefly because it has been used long before this point in Facebook’s production code.  Not a bad testimonial.  Having said that is is new so, in comparison to many frameworks that are production ready, there is relatively little documentation (or more accurately StackOverflow questions) out there aside from the official stuff (although it is relatively comprehensive).

One of the issues I initially saw with React was the fact that, if you were going to use it as was recommended, you’d need a build step that would transpile Reacts JSX into pure JS e.g.:

JSX


var HelloMessage = React.createClass({
    render: function() {
        return <div>Hello {this.props.name}</div>;
    }
});

React.render(<HelloMessage name="John" />, mountNode);

JS


var HelloMessage = React.createClass({displayName: "HelloMessage",
    render: function() {
        return React.createElement("div", null, "Hello ", this.props.name);
    }
});

React.render(React.createElement(HelloMessage, {name: "John"}), mountNode);

Obviously there’s isn’t too much more work in writing the JS in the first place but when it comes to syntax highlighting and writing what still feels like HTML it becomes much easier to manage.  I also decided to opt for JSX as it includes a build step; something I’d done may times for my Sass/CSS but not had much experience with for my Javascript.  Up to now you could manage mid-sized projects in JS – with anything from Angular to Three – without the need for a build step.  In addition, of the large scale projects I’ve done most have been in Rails, which allows you to leave most of the building to the asset pipeline.  This is similarly true here with the react-rails gem, but I wasn’t in need of a Rails setup just yet.

After doing a bit of reading around and scrutinising some sample apps, it was clear that best practice for React was to separate everything, à la CommonJS, using Gulp + Browserify + Babel.  Browserify allows you to use CommonJS on the front end by compiling all of the CommonJS require("foo") statements into one bundled output file, Babel is the transpiler I that I picked to convert JSX into Javascript and Gulp would be the tool I would use to actually run these.

Firstly, if you’re not au fait with Gulp (and hence probably the whole idea of build systems) check out this article on Gulp and it’s main competitor: Grunt.  I’ve used Gulp many times before, both as a build step for my Sass and also for Browsersync; the latter of which allows CSS changes to appear immediately in the browser without a page refresh (among many other things).  Thus, it wasn’t too out of my comfort zone.

After using npm to grab Gulp, React, Browserify and Babelify (the “transformer” used in Browserify to run Babel on the all of the required files) and setting up a gulpfile I found I was up and running pretty quickly.  I’d set up a Gulp watch task to monitor file saves of my JS and rebuild the JS each time.  However, one thing I had noticed was that build times were relatively long for the small project I was working on; not much more than a “Hello World!”.  After yet more reading I found that the Watchify module was a better optimised watch setup for Browserify and would only rebuild what was needed, nicely cutting down the build time (Gist).  My current Gulpfile looks like this:

Gulpfile.js


var gulp = require('gulp');
var browserify = require('browserify');
var watchify = require('watchify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var sourcemaps = require('gulp-sourcemaps');
var uglify = require('gulp-uglify');
var gutil = require('gulp-util');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');

var b = browserify({
    cache: {},
    debug: true,
    entries: './src/js/app.js',
    extensions: ['.jsx'],
    packageCache: {},
    paths: ['./node_modules','./src/js/'],
    transform: [babelify]
});
var w = watchify(b);

gulp.task('js', bundle);
gulp.task('default', ['js', 'sass', 'sass:watch']);
w.on('update', bundle);
w.on('log', gutil.log);

gulp.task('sass', function () {
  gulp.src('./sass/**/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(autoprefixer({
        browsers: ['last 2 versions'],
        cascade: false
    }))
    .pipe(gulp.dest('./css'));
});

gulp.task('sass:watch', function () {
  gulp.watch('./sass/**/*.scss', ['sass']);
});

function bundle() {
    return w.bundle()
        .on('error', gutil.log.bind(gutil, 'Browserify Error'))
        .pipe(source('app.js'))
        .pipe(buffer())
        .pipe(sourcemaps.init({loadMaps: true}))
        // Add transformation tasks to the pipeline here.
        .pipe(uglify())
        .on('error', gutil.log)
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest('./dist'));
}

All good!

As a happy side effect to all this, Babel also transpiles Javascript written in ES6 syntax to ES5.  Ok, ok, that’s actually its main purpose but not what I was intending to use it for …  This allowed me to require all of my React components etc. with the ES6 syntax (good link).  And there is even React documentation on how to setup your components to work with class ES6 syntax, so I turned my components into classes (and then Babel turned them back!):

import React from 'react';

export default class ProgressCircle extends React.Component {

	render() {
		let stroke = this.getStrokeProperties();
		let text = this.props.progress * 100 + '%';
		return (
			<div className="pc">
				<div className="pc__i">
					<div className="pc__ii">
						<div className="pc__tw">
							<span className="pc__t">{text}</span>
						</div>
						<svg className="pc__s"viewBox="0 0 200 200" perserveAspectRatio="xMinYMid">
							<circle className="pc__bc" r="95" cx="100" cy="100"></circle>
							<path
								className="pc__c"
								d="
								M 100, 100
								m 0, -95
								a 95,95 0 1,0 0,190
								a 95,95 0 1,0 0,-190
								"
								style={{strokeDasharray: stroke.dasharray, strokeDashoffset: stroke.dashoffset}}
							/>
						</svg>
					</div>
				</div>
			</div>

		);
	}

	getStrokeProperties() {
		let length = Math.PI * 2 * 95;
		let dasharray = length + ' ' + length;
		let dashoffset = "" + ((length * this.props.progress) - length);
		return {
			dasharray: dasharray,
			dashoffset: dashoffset
		};
	}

}

N.B. I have read a few articles worrying about the syntactic sugar of ES6 and that newer / less experienced developer will miss out on the way in which javascript allows closures etc. However, I think for something generally uncomplicated like a React component there is very little reason not to tidy it up with class syntax.

Aside from many other things, the thing I was surprised that React gave me was a clearer idea about the broader idea of “components”; especially with regard to BEM CSS.  Sometimes, when writing an HTML template / partial its not always easy to decide how to delineate BEM Blocks.  Well, it is easy, but you just don’t really think about it perhaps in the way you should.  At least I don’t.  However, when splitting a UI into React components it forces you into creating such components, and generally I have found these as being useful starting points for BEM Blocks.  As you start to turn one component into two, so might you consider doing the same with your BEM.  For example the progress circle in the above example is a perfect candidate for a BEM block; this is the case much of the time in react.  It’s another nice way of keeping everything encapsulated.

This was a rather quick and tangential post on how React has kicked me into “ES2015” as well as help streamline my thoughts on components and with Rails 5 on the horizon with fully baked in API mode it shouldn’t be long before we all start getting round to heavy JS sites.

Advertisements

Published by

richieahb

A full stack web developer working with PHP, Ruby and Node.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s