“When creating user interfaces, you can take different approaches,” says Minko Gechev, an engineer on Google’s Angular team. “Individual frameworks are seeing it from all these different angles, and they’re building user interfaces differently.”
Angular uses two-way binding, which facilitates the model-view-controller (MVC) architecture. With this, when a view component changes, the state of the model changes too, with the opposite also being true, thus making for two-way data binding.
In contrast, React offers one-way data binding, which flows from an updated model to rendering the change in the view component. Implementing the opposite flow requires manually setting the value and change handler.
The changing needs of UI development
Keeping UIs in sync with the app state
“I think the biggest challenge solved by most front-end frameworks is the ability to manage the state and the interaction between the DOM and back-end services,” says O’Leary. “Those services may contain data or other critical items that are required for first-class user experience, and front-end frameworks provide a paradigm for delivering that into the DOM in a consistent way.”
React provides a virtual DOM—a lightweight, cached version of the real DOM—and updates it when the state of a component changes. Through a process known as reconciliation, React then computes the difference between the current version of the virtual DOM and its previous version, and applies those changes to the real DOM, allowing for effective DOM updates.
Vue.js utilizes a similar virtual DOM, as does Preact, which owes its speed and size to a virtual DOM implementation that’s as close to the actual DOM as possible. Meanwhile, Angular uses change detection to perform DOM updates, detecting changes to component data and automatically re-rendering the view to reflect those changes. Svelte takes a compiler approach, shifting the browser’s work of transforming declarative code into DOM operations to a compiler that builds the app and converts components into imperative structures that update the DOM.
To find a component-based, complete, and consistent solution
Certain frameworks, especially opinionated ones that support a set of design principles, provide an organized structure that allows for consistency and better code maintainability. “Another problem that frameworks solve is dividing the complexity into components—smaller units that you can reuse and test,” says Gimeno. “Using components helps with implementing atomic design.”
For instance, Angular employs a component architecture, in which building a web app entails defining components and composing them together. This modular approach even extends to the entire framework.
“We aim to provide the entire stack to build a production-ready application from end to end,” says Gechev. “We bring together all the pieces you need, starting with a command-line interface [CLI], a component toolkit, a router, a forms module, and progressive web application support through service workers, among others. We make sure these products integrate well so you won’t have to assemble different parts from across the web.”
Ember does the same with its complete front-end stack. It comprises its CLI, which provides an out-of-the-box development experience including auto-reloading, code generators, a standard file and directory structure, and a test runner; Ember Data to manage an app’s data layer; and the Glimmer rendering engine to speed up rendering performance.
But this adherence to convention over configuration means frameworks such as Angular and Ember lose out on the flexibility provided by less-opinionated ones such as React. “The kind of quiet productivity you get from Ember may not be as exciting as the cutting-edge features of other frameworks,” says Melanie Sumner, an Ember core team member and LinkedIn senior software engineer. “But we’re stable and a lot more in-depth.”
Collaboration and community
Most front-end frameworks have an established set of design patterns, which makes it easier for developers to learn a new code base and fosters collaboration, especially among large development teams or those building large-scale apps. Popular frameworks also have extensive documentation, as well as resources such as tutorials, forums, meetups, events, and a dedicated community to support developers.
Despite this, Greif notes that the language shouldn’t try to do what a framework does. “Frameworks can highlight needs that the language isn’t currently fulfilling, but that doesn’t mean the language should try to copy the framework’s features,” he says. “Frameworks aren’t so much a driving factor as what apps need to be complete, and the language will adapt to those needs. As apps become more complex and as we do more in the browser, requirements evolve. Then, the frameworks evolve to meet those requirements, and later on, the language can evolve in the same direction to streamline things.”
“There’s a challenge in having many solutions,” says Gechev. “It’s definitely a hard choice. I would recommend developers stick to the approach that seems more reliable to them in the long term and they feel most comfortable with.”
Hagemeister echoes this advice: “Each framework makes different choices and different trade-offs, but you can’t go wrong with any of them. It’s just a matter of picking one and going with it.”
This article is part of Behind the Code, the media for developers, by developers. Discover more articles and videos by visiting Behind the Code!
Want to contribute? Get published!
Follow us on Twitter to stay tuned!
Illustration by Victoria Roussel
- Add to favorites
- Share on Twitter
- Share on Facebook
- Share on LinkedIn