Inside Onsen UI: Web Components
Onsen UI 2.0 final release is around the corner. We’ve come a long way since we started implementing this version and we want to explain you here what were our reasons and issues. This is a short article that breaks down Onsen UI and some of the technologies behind it.
From AngularJS directives to Web Components
Onsen UI 1.x was built on top of AngularJS, a revolutionary framework for its time that is getting replaced nowadays by some more lightweight and newer ones. In AngularJS it is possible to define directives
, markers on a DOM element (mostly as element names or attributes) that allows attaching a specified behavior to them. While this was great to make an HTML-Elements based framework, it carried a few drawbacks. Being built on top of AngularJS meant that every developer had to adapt to this framework in some way or another. Even if it was not used for the main part of the app, the dependency is still there running under the hood and compiling everything. Also, AngularJS is a great framework but we all know it doesn’t help too much with performance. Even though performance mostly depends on the app developer’s skills, dropping a few hundred milliseconds by removing dependencies is quite significant for hybrid apps.
Due to these and some other reasons we decided that Onsen UI 2.0 should move on and divorce from opinionated frameworks. At that time we found the Web Components project and in the team we all agreed it would be interesting to try it out.
With this technology are able to create real and reusable HTML components that behave in the way we want. As everything, this technology also has some minor drawbacks such as not being able to create custom attributes. That’s the reason why we have now, for example, <ons-lazy-repeat>
element instead of an attribute as we had before with the directives. However, over all of this, we thought the swap would still be worth it.
Web Components standard
Web Components is actually a set of different and separate technologies: Custom Elements, HTML Imports, Templates and Shadow DOM. These are browser standards still under development that hopefully soon will have a native implementation in every browser. Until then we just need a simple polyfill that implements the necessary features.
To be precise, we don’t need everything in the Web Components specification, just the Custom Elements. This is what allows us to create elements that inherits the original HTMLElement
with extended behavior. Thanks to it we are able to get an element by ID, tag name or class and directly use it as a normal DOM element:
var newItem = document.createElement('ons-list-item'); document.getElementById('my-list').appendChild(newItem);
We believe this makes Onsen UI super simple to use as you are working with real HTML Elements that have attributes, properties and methods just like in normal HTML5.They can be used with just pure JavaScript and it feels simple and easy.
Custom Elements reached its version 1.0 quite recently, improving their API and finalising some extra features. If you are curious about this technology you can read further about it here.
As a side note, Web Components is not the same as Polymer. This is just a project built on top of Web Components just like Onsen UI.
Not an easy change
While all of this sounds very cool, truth is that it was not a smooth change. We faced many issues that have been gradually fixed. Some of them still persist until now and force us to make adjustments to the core library from time to time.
At the beginning, Google Chrome was the only browser that natively supported Custom Elements and everything worked just right. However, other browsers without native implementation that were using the 0.x version of the polyfill presented several timing issues: Components were not loaded when they were supposed to be since they needed some extra cycles (remember that JavaScript is asynchronous). Fortunately, all of this was fixed with the version 1.0 of the polyfill (the one made by WebReflection) and now every browser is consistent in terms of Web Components (cross browser CSS is a whole different topic).
Moreover, the biggest issue we had is likely related to DOM manipulations. Some components need to create inner elements and move their content around in order to work properly. For example, when you create <ons-page>
with some content, another <div class="page__content">
is actually created internally and the content is moved there. This allows us to provide a simple API and a way to use our components but it comes with a high trade off. This is just fine if we only use Custom Elements with Vanilla JavaScript or libraries like jQuery. However, more complex frameworks such as React or Angular 2 want to manage the DOM tree by themselves. Therefore, making any modification to the inner structure from the element itself is not very advisable.
In addition, every framework has its own peculiarities when it comes to element creation. Some of them allow creating elements directly with attributes on them whereas others will first create the element and then add the attributes afterwards. The same happens with the element content and some other things. We had a hard time resolving all of these problems and sometimes we still need to address related issues from time to time.
In any case, Onsen UI 2.0 has definitely improved in both performance and ease of use after all of these changes.
Becoming framework agnostic
Probably you have already heard about Onsen UI support for React, Angular 1 & 2 and recently Vue.js. For these frameworks we wanted to release a small wrapper that we call bindings. These small “add-ons” allow us to fix some timing issues described in the previous section and, most importantly, we can tailor our core library for specific groups of developers. For instance, nobody wants to do document.addEventListener('prepush', fn)
in AngularJS if you can directly use an attribute <... ons-prepush="fn">
in your element. This sort of features is what we implement in the bindings in order to make Onsen UI feel more natural for Angular, React or Vue.js developers.
Still some work to do. But it looks good!
We are aware of some parts that still need to improve. For example, we want to expose and document an API for extending the core library so everyone can easily create custom bindings for other frameworks. We are also working on exposing an API for animations in order to make it easier to plug an external router and let Onsen UI handle the page transition animations.
These are, however, changes that will come after the final release as we don’t consider them urgent enough to delay the big day anymore. Onsen UI is quite robust already and we consider it ready for real world apps. You can expect the final version to arrive quite soon.
We are very thankful for the feedback we get in our forum and Github repo. This allows us to keep improving and expanding Onsen UI. We’d like Onsen UI developers to spread the word about our framework now that we are about to release the final version. Let’s make this a big framework with a big community.
You can leave comments and questions on our forum; issues and 🌟 on Github. Happy coding!