JP's Musings

Recent Posts


Recent Comments


Archives


Categories


Meta


Launching an Enterprise React & Redux App – Part 1

John Paul NarowskiJohn Paul Narowski

This is the first post in a 6 part series walking you through the process of building an enterprise application in React and Redux.

We found TodoMVC (and other examples like that) to be far too lacking when it came down to building real, scalable applications. We needed examples of paging, how to organize our code so we weren’t bogged down 1 year in, and how the heck to add pagination to redux.

Oh yeah, and we’re pretty opinionated.

Part 1: Getting Setup

We consider this a work in progress and plan to extract a sample functioning project out of this once we’re all finished, complete with a full CRUD system organized for enterprise development.

We’ll walk you our design decisions, and please feel free to contribute. We consider this a living style guide and will be updated as we learn more about the best practices when it comes to large scale enterprise React/Redux development.

Webpack

I’m not going to go into the Webpack VS Gulp VS Grunt debate, or how to configure webpack. We’ve started our project with a fantastic react/redux starter kit that handles most of the design decisions for us.

I did want to mention however one awesome configuration detail of this starter kit is using resolve.root! This has been a lifesaver for us and allowed us to reorganize our code a good amount without breaking trillions, yes TRILLIONS of relative require paths.

resolve: {
    root: [path.resolve(__dirname, 'src'), path.resolve(__dirname, 'node_modules')],
    extensions: ['', '.js', '.jsx', '.coffee']
},

This is a lifesaver when avoiding code like this:

import Bojangles from "../../../../shared/bojanges"
import Firewater from "../../../firewater"

Instead you can do:

import Bojangles from "components/shared/bojanges"
import Firewater from "components/firewater"

CSS

We’ll be using modular CSS which already comes baked in free with our starter kit. You can import your CSS stylesheet just like you would another component

import style from "./index.scss"

Then you can access your CSS properties like a javascript object. The css-modules configuration automatically adds the component name and a unique hash to prevent any conflict.

import style from "./index.scss"
import React, { Component, PropTypes } from 'react'

export default class Tabs extends Component {
  render (){
    return (
      
) } }

Benefits

React

Organizing our Components

For this project, we’ll be following the principles of atomic design. What is Atomic design? – Atomic design is a methodology used to construct web design systems. – http://patternlab.io/about.html

Here’s an awesome post by Joey Di Nardo about applying atomic design to React.

Icons made by Yannick, Freepik from www.flaticon.com

Icons made by Yannick, Freepik from www.flaticon.com

One Folder Per Component

Yeah I know it sounds crazy, that’s a TON of folders. I was apprehensive myself until I tried it out and felt it really cleaned things up.

Screen Shot 2016-01-31 at 3.46.32 PM

Benefits

Redux

What is Redux? It’s a Predictable state container for JavaScript apps. Redux has become the industry darling as far as Flux implementations go. I’d say it’s safe to say Redux has won in terms of support. Thank God, because my eyes were starting to bleed with all the competing flavors of flux.

Organizing your Redux Code

We’ve taken a cue from the NuclearJS guys (another solid framework) and decided to implement our domain logic in modules.

Screen Shot 2016-01-31 at 3.47.58 PM

Then you can import the module where you need it.

import Entities from "modules/entities"

There’s a few other proposals for code structure around a redux app, another one from redux-form creator Erik Rasmussen being “ducks“. I personally found that when dealing with a large app with many domains, modules just made more sense.

Reducer Structure

We’ve decided to organize our reducers in terms of function, instead of domain. We started off making a reducer per domain. Something like “contacts reducer”, “companies reducer”, “tasks reducer” etc. We quickly found ourself replicating a lot of the base logic in each reducer (pagination, filtering, editing etc), and decided to instead reorganize our reducers to be named according to the function they perform.

More like

-- entities
-- pagination
-- filters
-- sorts

This allowed us to keep the reducers light, simple, focused and testable. Within each of our function focused reducers, we scope entities by domain, so something like:

entities
-- contacts
-- companies
pagination
-- contacts
-- companies

We often have multiple reducers listening to the same actions like FETCH_ENTITIES_SUCCESS and once the data is received, spread the responsibility to the relevant reducers.

Immutability

We’re going to commit to Immutable-js. I know it’s scary, it’s somewhat big and it turns pretty vanilla javascript objects into monsters, but it’s worth it.

We won’t have our entire reducer state immutable, but they will always be immutable at the second level. We choose immutable because it takes the guesswork out of keeping things immutable, and allows for fast shallow comparison in react components

Getting Your Hands Dirty

If you want to get started, we recommend this starter kit! It’s very well configured and has a solid set of dependencies.

https://github.com/davezuko/react-redux-starter-kit

Here’s a few more things we’ve installed on top.

npm install react redux react-redux reselect immutable-js redux-thunk redux-promise-middleware redux-form superagent normalizr reselect classnames --save
npm install chai-immutable json-server --save-dev

Part 1 Recap

CSS
— Use Modular CSS

React
— Organize your components with Atomic Design
— One folder per component

Redux
— Organize your code into domain specific modules
— Think of naming reducers in terms of their specific function, not the domain they serve

What’s Next?

The next post we’ll write about mocking up our application, what tool we used and how it’s helped our workflow.

— Part 1: Getting setup
— Part 2: Mocking up the project
— Part 3: Slicing it to React component-friendly HTML/CSS
— Part 4: Converting to Atomic Design React Components
— Part 5: Adding Redux (with a mocked API responses)
— Part 6: Adding the backend server

Hope you enjoyed it. Part 1: Mocking up the project coming soon!

I’ve been hacking at various business ideas since I was 16. I’m a full stack developer and love crafting user experiences. I’ve been nose deep in code since I put the legos down, and built several successful businesses in the process. I’ve lost some hair, gained some experience and throughly enjoyed the journey.

Comments 9
  • Sean
    Posted on

    Sean Sean

    Reply Author

    Hi, great first post. One query from my side, how do you handle the webpack resolve.root case within your unit tests etc? I hate being dependent on webpack to be able to execute code independent of the browser. Personally I’ve resorted to a lesser evil and have started using the babel alias plugin which allows me to alias root folders in a similar fashion. I then also follow the convention that anything which is aliased should begin with a ‘_’ character. So a path of ‘./src/components’ is aliased as ‘_components’, and then import like “import foo from ‘_components/shared/foo’.
    Executing my code still depends on an external tool doing some source massaging, but I’ve found that doing it at the babel level is much easier swallow as babel integrates with various workflows, where webpack is tailored towards producing bundled output.


    • Sean
      Posted on

      Sean Sean

      Reply Author

      Pardon my broken english. I should have given that a read over before posting. 🙂


    • John Paul Narowski
      Posted on

      John Paul Narowski John Paul Narowski

      Reply Author

      Hi Sean,

      That’s a really good point. I haven’t done much testing yet with this framework, but I think it makes sense to try and use Babel instead of Webpack if possible. I’m going to give it a go shortly and report back what I find in terms of ease of referencing tests.


      • Sean
        Posted on

        Sean Sean

        Reply Author

        No problem. I would be interested to hear your experience of it.

        Another pain point in the test arena is when you use something like the CSS Modules approach (or any similar CSS import strategy). This obviously has a hard dependency on the respective Webpack loaders, however there is a semi-agreeable workaround for this. The babel webpack loader plugin (https://github.com/istarkov/babel-plugin-webpack-loaders) allows you to integrate specific webpack loaders into your babel configuration. I expose a specific “env” config section within my .babelrc that contains this additional plugin. Makes testing lovely again.


  • sulliwane
    Posted on

    sulliwane sulliwane

    Reply Author

    Thanks for the article! Can’t wait for the next one 🙂


  • nvojnovic
    Posted on

    nvojnovic nvojnovic

    Reply Author

    Next part?


    • John Paul Narowski
      Posted on

      John Paul Narowski John Paul Narowski

      Reply Author

      We’re on a big push to get this app developed, will be working to release the next posts in the series soon! Thanks for asking!


  • Pouya
    Posted on

    Pouya Pouya

    Reply Author

    Thanks for the article. Is this series still on?


  • Jonathan Tobe
    Posted on

    Jonathan Tobe Jonathan Tobe

    Reply Author

    Any word on the next articles in the series?