A YAGNI ReactJS Architecture: Part 1

The Why

React is awesome. 11/10. In my opinion, the best UI library currently in the ecosystem. It streamlines UI componentization, reusability, UI state, and a ton of other client side headaches devs have been mitigating for years. React's greatest flaw, in my opinion, isn't even really a React flaw as much as a "new stuff hype" flaw, where the infrastructure surrounding React changes almost hourly and can be extremely difficult to keep up with. What libraries are required, which ones will make devs' lives easier, which will bring performance gains?  

Over the past two years I've thought a lot about React, and many times I've been lead to the "YAGNI" principle. In short, You Ain't Gonna Need It. As in, "library X was just released and claims to streamline React application development. Should I do a complete rewrite to implement X?" My answer is almost always "Probably not." If your app is anything short of a SAAS product, you're probably better off/just as well off using 1/10th of the existing React tooling.

Note: This is not a criticism of the React infrastructure. It's awesome that so much innovation is happening so quickly on such a great tool. JavaScript's ecosystem is thriving right now, which is great. The problem is simply: most of the tools being created solve problems most of us will never face, and are creating a lot of noise around learning and developing React applications.

With the YAGNI Architecture, the idea is to strip out all but the required tooling. This enables a developer to master a small set of tools and build out components/apps quickly and efficiently.  It also serves as an excellent jumping off point for exploring more React tooling later.

The What

Most client-side apps implement a handful of universal tools to solve problems. I think you can generate boatloads of value with just a Router, an HTTP request wrapper (although you don't even really need it), some form of DOM Manipulation, and a build tool. You can get a lot fancier (and you almost certainly will), but the idea is that you don't have to.  In the sample architecture I've built we use ES6 (also not required), React-Bootstrap for styling and grids, and SASS, because obviously.

So my tools are:

Superagent and Director can be replaced with pretty much any HTTP and client-side routing library, they're just the ones I was most familiar with.  With this architecture there's a lot of room for "Nice to Haves" if a dev wants to implement more features, but this core allows for a Single Page App that implements DOM manipulation, a build processor, routing, and an HTTP wrapper. 

The How: Part 1

This post is predominantly an introdction to the architecture as well as some backround as to why I like it. I'll also include the first chunk of configuration, Webpack, as it's probably the new-hip-coolest piece of the architecture.

I recommend starting with the tutorials on the Webpack site, as they're far better at explaining the What's and the Why's of Webpack, but the gist is "create one/two/some build artifacts that contain source modules that can be required (es5)/imported (es6)".  My implementation outputs two files, a compiled ES6>ES5 JS file, and a compiled SCSS>CSS file.

Webpack requires an entry.js file to configure the app and load in dependencies. In entry.js you can configure director to use default routes/match to react components/create a datastore/do whatever you want.

Chunked/annotated source:


//Imports the ExtractTextPlugin module to output multiple files
var ExtractTextPlugin = require('extract-text-webpack-plugin');
 
module.exports = {
    entry: "./entry.js",   //The entrypoint to your app. Configure React/React Bootstrap/Director here
    output: {
        path: __dirname,
        filename: "bundle.js"  //The outputted JS file to be included in index.html
    },
    plugins: [
    	new ExtractTextPlugin('app.css')  //The outputted JS file to be included in index.html
    ],
    module: {
      loaders: [  //Loaders are Webpack's way of understanding what to do with various files.
        {           //We use two loaders, one for ES6 JS and one for SCSS
            test: /\.js?$/,  //Any file ending in .js will use this loader
            exclude: /(node_modules|bower_components)/,
            loader: 'babel', // Babel is the ES6 to ES5 compiler
            query: {
              presets: ['react', 'es2015']  //Loader presets
            }
        },
        {
    	      test: /\.scss$/,  //Any .scss file runs through this loader
    	      loader: ExtractTextPlugin.extract(
    	        'style', // backup loader when not building .css file
    	        'css!sass' // loaders to preprocess CSS
  	      )
        }
     ]
  }
};
 

With this Webpack bundle config (stored in webpack.config.js), a valid entry.js file and the required node_modules installed, you'll be able to start building out components with React/React-Bootstrap/Superagent.

In the next post we'll get into configuring Director to work with React Components.
Thanks for reading!

Comments

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <cpp>, <java>, <php>. The supported tag styles are: <foo>, [foo].
  • Web page addresses and email addresses turn into links automatically.
  • Lines and paragraphs break automatically.

Ready for transformation?