I developed json-formatter directive to use it in Swagger Editor. It’s a simple component for rendering JSON in HTML nicely. Inspired by how WebKit renders JSON in developer tools.

    <!-- This will result in an infinite loop -->
    <json-formatter ng-repeat="key in keys"></json-formatter>

It’s an AngularJS directives, so you can’t use simple recursion by just repeating the directive in directive template, instead you have to do some tricks to go around it. This StackOverflow answer elegantly defines a factory that overrides AngularJS’ compile method to allow recursive directives.

When rendering large JSON objects, this directive was responding very slowly. For example for a large JSON file which would result in 24,453 HTML nodes it took 3.34 seconds to render. It’s a lot of time for rendering ~25K nodes. Take a look at the HAR file1.

AngularJS recursive $digest calls

AngularJS groups $digest calls to minimize DOM manipulations and triggering change events but with our recursive helper factory we’re avoiding that optimization and running a lot of $digests. That’s why we end up with such slow component.

Since AngularJS has no good way of building recursive components I went ahead and rebuilt json-formatter in pure JavaScript. It’s available here. This component uses no framework and everything is in plain JavaScript. Recursion happens in a simple for loop. It’s much faster compared to the AngularJS directive. Look at HAR file, the same JSON renders in 981 milliseconds.

AngularJS recursive $digest calls

Further optimization

Our component is appending new children to parent DOM node and installing separate event listeners for each child. This is an artifact of porting the code from AngularJS to pure JavaScript. We should really do the iteration in template level without any DOM manipulation and use event delegation to have only one click event listener for entire component.

Even though without those optimization we’re getting a 3X performance boost I will redactor this component with above ideas to perform better.

  1. Open HAR files in Timeline of Chrome Developer Tools by right clicking and selecting “Load Timeline Data”