JayChase / angular2-highlight-js

highlight.js integration with Angular
MIT License
21 stars 9 forks source link

The performance of the directive is extremely poor when other content on the page is updating #9

Closed sbabeal closed 7 years ago

sbabeal commented 7 years ago

I am creating a site similar to swagger where you can see the query and results on the web page. Since the directive doesn't test to see if the content hasn't changed it causes the element to rerender when anything on the page changes. Additionally, if anything else, like a web socket connection, is inside ngzone this will cause a change detection cycle also and will force all containers to update again. To fix this i changed all the components to onPush and call this.ref.markForCheck(). But this still doesn't work very well. To display 1 hz data in this format eventually the directive will take 99% of the cpu time and will crash the browser. The directive needs to check to see if the content has changed before running it though the highlight js utility. I would like to know your thoughts on how to address this.

image

sbabeal commented 7 years ago

The other issue is that the original text is never preserved. So every time a CD cycle is run it passes in the already converted highlight nodes into the highlight js converter. This is where the performance really takes a hit. You only want to convert nodes that haven't been converted when using the directive. Is there a way to tell if the nodes have already been converted and then skip the call to highlight.js if this is the case?

sbabeal commented 7 years ago

so I created a different directive and added a check to see if the html content already had the hljs classes added to them and if they did then the data wouldn't be passed to the highlight. This solved my issue and now only code that has changed repaints. We will see if any other performance problems crop up.

ngAfterViewChecked() {
        let selector = this.highlightSelector || 'code';

        if (this.elementRef.nativeElement.innerHTML &&
            !this.elementRef.nativeElement.innerHTML.includes("hljs")    ) {
JayChase commented 7 years ago

I will have a review of the design for the directive for the next version. In the mean time to have full control on when the markup gets highlighted it is best to use the service.