I have been working with React JS for a few days and I must say I am impressed. You can not really compare it to complete frameworks like Angular JS or Ember JS, but at the same time it is worth mentioning in the same context. A full framework increases your development speed and is a dream when it comes to prototyping, but building a high performance web application is easier when you control each part. More on that in a later post, lets dive into how I found an ideal way to work with React JS.
Update: I updated the boilerplate with better testing and better handling of dependencies. Wrote about it here, React JS and a browserify workflow, PART 2.
I really do not appreciate the simplicity of examples shown on probably all library/framework sites. Nobody builds an application in the global scope, nobody builds an application in a single file and everybody wants to make their code production ready. The React JS site is no different and it took me quite some time creating a good workflow. This is what I needed:
- Write my code in a module pattern
- Use the React JS chrome dev tool
- Run other tasks on file change, like CSS concat etc.
- It has to be extremely fast
This post will go through each step I did to find a solution. If you just want the solution, jump ahead.
So my first challenge was to solve the JSX transformation on the fly. Looking at the React JS guide I quickly figured out that the only thing I needed was to include an extra script tag in my HTML. It solves my problem, but it is not what I am looking for. The extra script tag is not something you want to put in production, so I would need to pre-transform my files containing JSX.
As the React JS guide states, you can install the react-tools globally and use a command line tool to watch files and convert them. It solves my problem, but it transforms each individual file and puts it in a different folder. This will create a messy project structure. I needed to change my strategy! I decided to look at some module tools instead, they would have to support the transformation of JSX anyways.
Having quite a bit of experience with requirejs I thought that would be a good bet, but it became more complex than I initially thought. A great job has been done on this plugin: jsx-requirejs-plugin, but you get extra dependenices like the "text" plugin for requirejs and you have to use a modified version of the "JSXTransformer", that does not feel good. There was also an issue with bundling the whole project on each file change, it was too slow.
After some research I found a grunt-concurrent task that would allow me to run two parallell watch tasks. This worked, but it was slow. And I still could not get my sourcemapping to work.
So the way I used Grunt was too slow, what about Gulp? Now Gulp is a build tool like Grunt, only it streams the process so that you can manipulate the build process in memory instead of creating temporary files that are picked up by the next step in the build process.
Searching the web for a solution for Gulp I hit this post on stackoverflow. It shows multiple solutions to the same problem and way down I found an example that also handled transforming JSX with reactify, but it had some steps I did not understand. Why all this require stuff? And why require specific react.js file? It feels a bit hacky. It also gave me an error when I ran it in the browser.
This led me to using gulp-browserify which worked beautifully. But what about the watchify part? Searching for gulp-watchify it states: "experimental". That does not feel right, so how could I get this stuff to work? Searching the web again I found the following statement: "gulp-browserify has been blacklisted". DOH!, what now?
Sometimes you just have to do it from scratch. Using what I had experienced so far I built my own build process using the browserify, watchify and reactify npm modules. I was glad to see that Gulp also handled watching both my CSS for one task and that watchify task in parallell without any issues.
So this is how my gulpfile.js file looks like:
So to summarize:
- Write my code in a module pattern (SOLVED)
- Use the React JS chrome dev tool
- Run other tasks on file change, like CSS concat etc. (SOLVED)
- It has to be extremely fast (SOLVED)
What about the REACT DEV-TOOLS?
The React DEV-TOOLS needs an instance of the React JS lib on the global scope to trigger. To fix this you simply have to add it to your main.js file.
/** @jsx React.DOM */ var React = require('react'); // Here we put our React instance to the global scope. Make sure you do not put it // into production and make sure that you close and open your console if the // DEV-TOOLS does not display window.React = React; var App = require('./App.jsx'); React.renderComponent(<App/>, document.body);
So that was my journey. I truly hope that the people at Facebook will put an example of this on the React JS site. React JS is truly awesome and its very sad if people leave it out because it is such a pain setting up a good workflow. Until then feel free to use an application boilerplate I have set up which also handles testing: react-app-boilerplate.
Thanks for listening to my story and have fun with React JS!