On Angular 2 and HTML Spec Compliance

Posted by EisenbergEffect on February 3, 2016

The other day I participated in a public AMA (Ask Me Anything) on Aurelia. As usual, when doing something like this, there are questions about other frameworks, such as Angular 2, React and Cycles.

There was one question in particular that resulted in a twitter stream and a post by Brad Green, the manager of Angular 2. Here's the question a community member asked of me:

Do you believe Angular 2.0 is deviating from standards?

My answer (truncated for brevity) was this:

...As of Beta 2, they've (Angular 2) actually adopted ... syntax which involves case-sensitivity constraints. HTML is not case sensitive and thus this breaks with the specification. As a result, it is actually not possible to get Angular 2 to work natively with the browser's parser, the DOMParser API or even innerHTML because those mechanisms "normalize" casing in different ways depending on the browser and thus casing can't be "trusted". This means that, if Angular 2 depends on casing (ie ngFor and ngModel attrs) then the browser won't be able to natively handle that. To solve this problem, it is my understanding that the Angular 2 team had to implement their own proprietary markup parser...

On Twitter Brad Green asserted that I was wrong in saying this about spec-compliance. I was having a hard time understanding this, especially with the HTML specification right in front of me.

Today, Brad responded with this blog post . I'm grateful that he took time to do that. The article does a great job of explaining the problem they were trying to solve and the benefits of their parser. In his post, Brad says:

Browsers don't differentiate tags by case. Solving the problem required Angular to do its own HTML parsing, so that we could retain the case-sensitive version...

Brad clarifies that the Angular team wrote a custom parser which would retain the casing information. He calls this an HTML parser, but a parser that differentiates case doesn't seem like a true HTML parser to me. The HTML spec says that the language doesn't do that. That's the simple point I was making.

To understand this, I took some markup from the Angular 2 homepage, and tried the following experiment. You can even run this on the console of this page if you want to try it out for yourself:

    var test = document.createElement('div');
    test.innerHTML = '<input type="text" [(ngModel)]="yourName">';

What browser you use will dictate what the actual output is. In Chrome, you will see something like this in the console:

    <input [(ngmodel)]="yourName" type="text">

Notice that the casing information (ngModel) is gone (ngmodel). Let's look at another example:

    var parser = new DOMParser();
    var doc = parser.parseFromString('<input type="text" [(ngModel)]="yourName">', 'text/html');

Again, depending on the browser, but in Chrome I see this:

    <input [(ngmodel)]="yourName" type="text">

The casing information is gone. You will see this behavior consistently because the HTML specification says that HTML is case-insensitive. It's really that simple.

So, does Angular 2 deviate at all from web standards? I would still say so, yes. Angular 2's markup requires developers to write case-sensitive HTML. The JavaScript library enforces a constraint which isn't present in the spec or supported by browsers. Because it won't work with standard browser APIs developers must use a custom parser with rules changed from the HTML specification.

That's it. That's all I'm saying here. Is it a deviation? Yes. Whether they should have done this or not, whether that matters to you or not...those are separate questions. I'm not trying to deal with those here.

But on that note, it does bring up a series of questions you should at least take some time to think about:

  • Do I want my "HTML" codebase to be written in this style?
  • Do I want to tie my codebase to a specific parser implementation which differs from those supported by browsers?
  • How will all this work with upcoming Web Components? Will Angular components be usable as Web Components if they can potentially have case-sensitive APIs? Will this introduce an additional set of rules developers have to remember?
  • Will having a custom parser hold my app back from adopting new standards or technologies as soon as they are available? Will I have to wait on Angular 2 to update their custom parser to take advantage of future capabilities?
  • Will new web developers learning HTML for the first time while learning Angular be confused or learn HTML incorrectly?
  • How does the custom parser interact with Polyfills that could patch HTML to enable new features in the future?
  • Will there be any problems using Web Components, such as those available through Polymer, with Angular's parser?
  • Could there be performance enhancements in the future DOM that I can't take advantage of because of this?
  • Are there any interoperability concerns with other libraries?
  • What is the maintenance cost of maintaining this custom parser (I'm thinking a little bit of AtScript here...)?
  • Does this create a technology "silo" that separates Angular 2 devs from the rest of the web development community?

As a developer, these are a few questions I would have immediately. Maybe the answers make everything ok. You might not even care about these things. Maybe its insignificant for your business. Personally, I do care about these types of questions. I survived (mostly) the IE6 browser disaster. I'm not sure that will happen again with browsers, but could it happen with frameworks that don't stick to standards? I don't know. I do know that some times "little" things can make a big difference and that these sorts of things shouldn't be taken lightly.