In my previous post, I showed that Polymer has a significant performance advantage over Angular. If you are trying to make your app fast (you should be), you are probably wondering if it would make sense to build it with Polymer.
The potential problem with building an app with Polymer is that Polymer was not initially designed for building applications. It’s a library to help developers work with Web Component APIs (think jQuery for the Web Components APIs).
Fortunately, the component-based development model offered by Web Components is flexible enough that you can build complex applications using the browser as your framework. But while it’s possible to create complex apps with Polymer, it’s still missing the structure and guidance a framework gives you.
In this post, I will compare the development experiences in building the same application in both Angular and Polymer.
Tools and languages
Polymer is still fairly limited when it comes to IDE support. The Polymer team is working on improving that through the Polymer IDE plugin that can be used with editors like VS Code and Atom. The Polymer IDE plugin helps developers avoid common mistakes, and offers some autocomplete help. Because Polymer uses plain ES6, there are no type checks.
The use of TypeScript in Angular also makes it easier for IDEs to offer development time help and checks. Visual Studio Code and WebStorm both have good support for TypeScript, the latter even helping the developer with including imports, making Angular development in an IDE fast despite the amount of boilerplate.
Debugging Polymer applications is straightforward. You can use the browser developer tools to set breakpoints and inspect the running code just like you would with any other front-end technology.
Most often, debugging the Angular app boiled down to a series of console.log statements
Angular is much more complex to debug due to the build steps between your code and the code that is running in the browser. The Angular CLI build creates source maps that should allow you to debug the TypeScript code in the browser. In practice, this didn’t work well as the source maps didn’t match the running code and breakpoints didn’t work. There is also a Chrome plugin for debugging Angular apps called Augury that allows you to inspect the hierarchy and status of your components. I did not find the plugin to be very useful in pinpointing issues. Most often, debugging the Angular app boiled down to a series of
console.log statements. Error messages in the browser console were cryptic, and stack traces rarely include identifiable code, only Angular internal calls.
Application structure and routing
Since both Angular and Polymer are component-based, the general application structure is similar. The UI is constructed out of components that get combined into successively more complex components, which are nested until an app emerges. In Angular, you can additionally bundle related components into modules that are used to scope dependencies, and that can be loaded lazily when needed.
Larger applications are organized into views. The views are typically bound to URLs so that users can link to different parts of the application and use browser navigation buttons to move back and forth. This mapping between view components and URLs is handled by a router.
Polymer ships an optional router that can be used to map between URLs and components. Using the router requires several steps and a lot of repetitive code. You need to add an
app-location and an
app-route element to your app to listen for URL changes. Using this information, you can decide what components to show, and optionally (manually) hook up lazy loading of those components.
By default, Polymer components are only lazily loaded into the DOM, but not removed. This leads to the DOM growing over time in large applications which may result in performance issues, especially on devices with limited memory.
The lack of a good router is the single biggest factor making it difficult to build large applications in Polymer
The Polymer router also supports nested routes. In practice, however, using nested routes gets very complicated as the router doesn’t know which view is active so sub-routes will get triggered on all views regardless if they are visible. The router does not either hook up to the build tools, so you need to separately configure views for lazy loading.
Based on my experience, I feel that the lack of a good router is the single biggest factor making it difficult to build large applications in Polymer.
Working with data
Data binding and data flow are important aspects of building apps. One of the functionalities that Polymer provides on top of the Web Components standards is a simple data binding system that supports both one-way and two-way binding of data. One-way data binding is preferred over two-way binding to make it easier to integrate the components with other frameworks and to enable uni-directional data flow patterns like Redux.
Angular also comes with support for both one-way and two-way data binding. In addition to data binding, it also comes with a Dependency Injection (DI) system that makes it easier to hook up services, especially when testing. Angular builds heavily on RxJS and Observables for handling data, especially for asynchronous HTTP communication. The reactive programming model will take some getting used to if you don’t have experience from before, but enables you to build elegant UI code.
Editing data in forms is somewhat different in Polymer and Angular. Polymer has a form element that extends the HTML form. All validation is handled by the form elements themselves, which is a bit limiting at times. In Angular, the validation is handled by the framework which makes it easier to combine different components but still have consistent validation.
Making it look nice
When it comes to customizing the look and feel of your app, Angular is much easier to work with than Polymer. Angular works together with existing CSS libraries like Bootstrap or Semantic UI and you can easily write global CSS to give your app a cohesive look.
Polymer is harder to customize in terms of look and feel because Web Components are designed to encapsulate their implementations, which means that you need to declare CSS variables and mixins that you import in your components. This means that you cannot use something like Boostrap easily and that it’s hard to get third party components fit your applications look and feel.
Angular also makes working with dynamic styles easier than polymer, as the template syntax includes a helper for setting style names based on a condition. In Polymer, you need to rely on basic data binding and custom methods which adds a lot of boilerplate.
Mobile support: Progressive Web Apps, native apps, or both?
Angular and Polymer have different approaches when it comes to mobile support. Angular is more focused on today’s needs, so it includes support for building both Web applications and native applications (although native support requires you to write a separate implementation of the view). They also added support for creating Progressive Web Applications (PWA) recently.
For Polymer, PWA is the only mobile strategy. This is in line with Polymer’s goal of building on Web standards to expand what you can do on the Web.
Maintainability and stability
Angular and Polymer both have a less than stellar track record when it comes to API stability. Polymer had a very rough transition period leading from version 0.5 until 1.0. Likewise, Angular 2 went through an extended period of API changes during development, lasting throughout the release candidates. There have even been some smaller breaking changes within the “stable” 2.x version.
The good news is that both teams have taken note and are planning for smoother upgrade paths in the future. Polymer 2, currently in release candidate, includes support for legacy components so you can migrate applications piece by piece. The Angular team has also promised that breaking changes in Angular 2+ will be easier to migrate, and have hinted several times at a migration tool to streamline the changes.
While it’s hard to predict the future, I think that Polymer and the W3C standards it builds on will provide a more stable foundation for apps that need to be maintained for longer periods.
Choosing development comfort over performance
We know that Polymer allows us to create fast web apps. But it turns out that Polymer by itself is too low-level to easily build big applications. There is clearly still a reason developers are selecting a framework like Angular instead of Polymer. Frameworks help developers structure applications and take care of things like routing, dependency injection, localization and other things you need to deal with when building a large application. Unfortunately, this developer convenience comes at a runtime performance cost to the end user.
A good first step towards making Web Components suitable for building bigger and more performant apps would be an improved router. It would both help to give structure to apps and make it easier to create apps with tens or hundreds of views.