Web Development at Margo Bank
Creating a bank from scratch is a big challenge. First and foremost, we need to think long term. Bootstrapping a web application in 2018 that must last for years, decades even, requires thoughtful consideration. The web ecosystem is teeming with new and exciting technologies, so it’s important to have a clear set of objectives and to make educated choices. This article is about how and why we selected the key technical elements that we did.
Decisions were ultimately based on the following criteria (in order of importance):
- Maintainability. Since being able to maintain and upgrade the application for years to come is paramount, it is only natural that we give particular importante to decoupling, reusability and testability.
- Productivity. Just like everyone else, we need to get things done and to feel comfortable with what we’re doing; however, productivity should not come at the expense of maintainability.
- Community and support. Any new technology requires new tools, new best practices, etc., and a strong community makes it easier to find help. As the team needs to scale up, using common practices makes hiring and onboarding of new developers easier as well.
Language and framework
As you can see below, React clearly stands out in the community.
Productivity is a pillar argument for all of them, so we settled the matter on the basis of maintainability and chose to use React.
Flow can be easily integrated in IDEs such as Atom or Visual Studio Code. It can give us instant feedback on type errors while we are typing. Combined with tools like ESlint and stylelint to prevent potential errors and Prettier to format the code automatically, it provides an optimal developer experience.
React is an open source library created by Facebook in 2013. As stated in the official documentation, it is used internally on more than 50 thousand components, and also in big companies like Twitter, Airbnb, Instagram, WhatsApp, Netflix, etc. Thus, breaking changes are very unlikely and always thoughtfully considered.
Like most of its competitors, React is component-based. You can think of a component as a
render function that takes properties and returns HTML. Thanks to JSX, HTML is now a first-class citizen; it can be assigned to variables and returned from functions.
JSX offers many advantages. The view and logic, typically separated in different files due to different technologies, are now reunited. Everything about the component is housed in the same file and is compiled with compilation checks. Also, there are no new attributes to learn — like
ng-something in Angular or
v-something in _Vue — _just plain old HTML and
The strength of component-based architectures lies in composition. A component can use other components to render itself, ending up in a hierarchy of components, just like a DOM hierarchy, but with less noise and more semantics.
React is a library rather than a framework. Compared to Angular for example, which admittedly is very complete, but is also rather opinionated about how to structure your app, React is very flexible and doesn’t impose anything.
To get started quickly, Facebook maintains create-react-app. It offers a default build configuration including Webpack, Babel, etc. and doesn’t clutter up our project. If needed, there are different ways to customize it, like eject or react-app-rewired.
As we’ve seen, React offers a good way to separate the app into small components, but it doesn’t give a lot of guidance on how to make these components communicate.
A component can easily pass down properties to its own children in the hierarchy tree, and these properties can be callbacks to communicate information up to the ancestors. However, communicating with neighbors tends to be complicated, involving a common ancestor, making it hard to follow and debug.
This case is quite trivial, but already adds a lot of noise. This will accumulate with each new feature and eventually make the app a big mess.
Inspired by Flux, Elm, and CQRS/ES which we follow on the backend side as well, Redux is the most common way to manage the state of a React application. Described as a predictable state container, it promises to keep the application state in one place and provide a safe and consistent way to update it.
With React and Redux in place, we now have small and reusable components with clear responsibilities and a very decoupled way to communicate between them.
We still have one major concern: how do we manage the style of our application? On a large project, this task can be tedious; we want our CSS code to be modular and reusable, and we don’t want any conflicts between our style rules. Classic solutions would be to use some CSS pre-processors like Sass or Less and to follow some naming conventions like BEM or SMACSS to prevent class name collisions. That said, in the React ecosystem, other solutions emerged to deal with those problems, namely Radium, Aphrodite, Glamorous, as well as the most popular, styled-components. We decided the latter was a good candidate for us.
The name of this library is quite self-explanatory. It allows the creation of components that possess their own encapsulated style. This removes the need to map styles and components together. In other words, we don’t need to define class names anymore!
Styled-components is based on Tagged Template Literals, a new feature of ES6. This allows us to use real CSS syntax in a JS file to define our component’s style while keeping the ability to write JS within this CSS code if needed.
We can extend existing styled-components using
extend() or convert any regular component using
styled(MyComponent). Our JSX code can now consist solely of components like
<MyComponent>, instead of using
<div> with class names everywhere, which makes it easier to read.
Now that the whole component, including its style, is bundled in a single JS file, it’s easier to grasp, and also easier to share.
We wanted to have the same notion of a ‘components library’ in our code. They needed to be easily browsable and documented in a single place. Also, we have two codebases (back-office and front-office), and we need a way to reuse the components in both places.
First, we extracted some of our components in a library and deployed it to NPM. Then, we looked for ways to make those components browsable directly in the browser.
There are two popular libraries to help with that, styleguidist and storybook. Styleguidist offers more flexibility by letting us write the documentation exactly the way we want in markdown. Snippets in this markdown are turned into live interactive views of our components:
Note that when we edit the code displayed in the browser, the live view updates itself automatically.
By carefully documenting all our shared components, we lay the groundwork for all future developments.
Speaking of the future, it would be even better to generate this shared library based on the design. A few weeks ago at ReactEurope, Airbnb announced Lona Studio, a component-oriented design tool. It directly exports code in multiple languages and frameworks, including React. This is very exciting, but also very experimental at the moment.
All of this combined allows us to keep a maintainable code base, be productive and remain invested in a strong development community.