Skip to content

Component Based Development

sldavidson edited this page Aug 17, 2016 · 3 revisions

Intro

A lot of the major JS frameworks are headed towards component based architecture. Angular 2 is all about components. The benefits include reusability, composability, reduced complexity, encapsulation, easier to test, easier to modify without mangling the whole app, and so on.

The metaphor used to explain Atomic Design is a good way to think of component based development. Atomic design puts an emphasis on composability of components.

Smart (Container) and Dumb (Presentation) components

Dumb (Presentation) Components
  • Are concerned with how things look.
  • May contain both presentational and container components inside, and usually have some DOM markup and styles of their own.
  • Have no dependencies on the rest of the app, such as services or parental controllers.
  • Don’t specify how the data is loaded or mutated.
  • Receive data and callbacks exclusively via scope.
  • Rarely have their own state (when they do, it’s UI state rather than data).
  • Example: Think of simple HTML DOM elements like an anchor tag. It knows nothing about the app and relies on the app setting the href, title, etc.
Smart (Container) Components
  • Are concerned with how things work.
  • May contain both presentational and container components inside but usually don’t have any DOM markup of their own except for some wrapping divs, and never have any styles.
  • Provide the data and behavior to presentational or other container components.
  • Provide app events or actions as callbacks to dumb components.
  • Are often stateful, as they tend to serve as data sources.
  • Need access to external app-level state.

Whenever possible, build reusable dumb components, not only because of the re-usability, for by removing application awareness and state, the complexity of the component is reduced. When a component knows nothing about the app, there are fewer parts of the code which may break when making app-level changes.

If you are creating smart components often, think about whether the state should be managed at a higher level instead of within the component itself; many things which may initially seem like they should be aware of app-level state can be a dumb component included within a higher-level smart component.

Further reads (still good even thought these are React based):

Routes are Components too

Routes are smart components that configure UI-Router. This means the index.js file for a route will be short and sweet:

// src/desktop/routes/home/index.js

module.exports = ngModule => {
  // Include the component for the route
  ngModule.component('home', require('./home.component.js'));

  // Configure UI-Router
  ngModule.config($stateProvider => {
    $stateProvider.state('home', {
      url: '/',
      template: '<home></home>'
    });
  });
};

This structure can be generated automatically by running $ plop route.

Since each route is a smart component, it should focus on getting data for services but not presentation. It should create a simple layout with child components and pass scope data to them. Its CSS file should be very short.

Folder Structure

These files and folders will exist when you clone starter-kit.

src/

  common/
    components/
    filters/
    services/
    styles/
    index.js (creates a common module)

  desktop/
    components/
    containers/
    routes/
    desktop.config.js
    desktop.css
    desktop.html
    desktop.init.js
    index.js (bootstraps the desktop app)

  responsive/
    (similar to desktop)

This is an opinionated setup that is optimized for our team's style of development. Here are some of the benefits:

  • Easy to automate workflows with da-plop
  • Easy to define guidelines (harder to mess up!)
  • Allows for automatic module importing

What goes in a components folder?

  • In General
    • Components that we could potentially pull out into da-bits or other shared code
    • Dumb components: just inputs and outputs
    • Reusable components that aren't tied to specific data queries, etc.
  • common/components
    • For loading purposes: don't include anything you don't intend to use on both platforms
  • desktop/components and responsive/components
    • Components that are reusable on that platform, but not the other
    • Example: You reuse a chart component on several desktop views, but don't use the chart on mobile

What goes in a containers folder?

  • Smart components: they depend on data or services from other places