Scaling React Applications: Containers vs Components, Feature‑Based Code Organization, CSS Modules, PostCSS Auto Reset, and Redux‑Saga
This article shares lessons learned from releasing React Boilerplate 3.0, covering the importance of front‑end scalability, the distinction between container and presentational components, feature‑based code organization, CSS Modules and PostCSS Auto Reset for style isolation, and using redux‑saga for readable, testable asynchronous flows.
We recently released React Boilerplate 3.0 and, after talking with hundreds of developers, distilled the key practices for building and scaling large web applications on the front end.
Containers and components : A container manages state and data connections without styling, while a presentational component handles only UI rendering. Separating these concerns prevents mixing data logic with visual styles.
Code structure : Traditional type‑based folders (actions/, components/, containers/, etc.) become unwieldy at scale. Organizing by feature keeps all files related to a specific UI element together. For example, the NavBar feature can be arranged as:
react-app-by-feature
├── css
├── containers
│ └── NavBar
│ ├── NavBar.jsx
│ ├── actions.js
│ ├── constants.js
│ └── reducer.js
└── components
└── App.jsxThis layout reduces navigation overhead and minimizes merge conflicts when multiple developers work on the same feature.
Style management : Global CSS naming collisions are solved with CSS Modules . Each component’s styles live next to the component and are imported as a JavaScript object, guaranteeing unique class names:
/* Button.jsx */
var styles = require('./styles.css');To reset inherited CSS properties per component, the PostCSS Auto Reset plugin rewrites inheritable properties to their defaults, avoiding unexpected differences between components such as line‑height.
Data fetching : While Redux Thunk allows async actions, it mixes data fetching with action creators, making testing harder. redux‑saga uses ES6 generators to write asynchronous flows that look synchronous and are easily testable.
Typical saga effects include:
put() – dispatch an action
take() – pause until a specific action occurs
select() – read a slice of state
call() – invoke a function with arguments
Because sagas run independently, they can act as glue middleware, decoupling components. For instance, a Clock component can trigger a Timer component via saga without each component knowing about the other.
Summary :
Distinguish container (stateful) and presentational (stateless) components.
Organize code by feature rather than by type.
Use CSS Modules and PostCSS Auto Reset for isolated, conflict‑free styling.
Adopt redux‑saga to obtain readable, testable asynchronous flows and to glue decoupled components together.
Hujiang Technology
We focus on the real-world challenges developers face, delivering authentic, practical content and a direct platform for technical networking among developers.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.