title: Angular 4 codemirror performance issue (detaching zone)
body: <p>I've run into big performance problem when I tried to implement codemirror, firstly I used <a href="https://github.com/chymz/ng2-codemirror" rel="nofollow noreferrer">ng2-codemirror</a> but it's killed my application which has only list of scripts and codemirror component. I found out that creating <code>instance</code> (by instance i mean <code>CodeMirror.fromTextArea(...)</code>) should be run outside angular so I copied component from <code>ng2-codemirror</code> (code attached below) to my project and wrap init method with <code>NgZone.runOutsideAngular</code>, it helps but just a bit. So I've started profiling my angular project with <code>Javascript profiler in chrome debugger</code> and vanilla js codemirror with the same <code>code</code> to edit. My small research shows me that without <code>zone.js</code> codemirror is executing same function with about 8% of my CPU resources however with <code>zone.js</code> in angular project it takes 48%. So I've started to completly detach zone from <code>codemirror component</code>, So I tried with <code>ChangeDetectionRef.detach()</code> but the zone still is attached to <code>codemirror</code> (checked with JS profiler again).</p>
  
  <p>Summary:
  <code>runOutsideAngular</code> does not help to detach codemirror source code from zone, same is for <code>detaching</code> changeDetector for codemirror component</p>
  
  <p>Code for my modified codemirror component</p>
  
  <pre><code>export class MpCodemirrorComponent implements AfterViewInit, OnDestroy {
  
    @Input() config;
    @Output() change = new EventEmitter();
    @Output() focus = new EventEmitter();
    @Output() blur = new EventEmitter();
    @Output() cursorActivity = new EventEmitter();
  
    @ViewChild('host') host;
  
    @Output() instance = null;
  
    _value = '';
  
    private changeSubject: Subject&lt;any&gt; = new Subject&lt;any&gt;();
  
    constructor( 
      private ngZone: NgZone,
      private changeDetector: ChangeDetectorRef
    ) {
      this.changeDetector.detach();
    }
  
    get value() { return this._value; }
  
    @Input() set value(v) {
      if (v !== this._value) {
        this._value = v;
        this.onChange(v);
      }
    }
  
    ngOnDestroy() {
  
    }
  
    ngAfterViewInit() {
      this.changeDetector.detach();
  
      this.config = this.config || {};
      this.codemirrorInit(this.config);
      this.changeSubject
        .debounceTime(500)
        .distinctUntilChanged()
        .subscribe(change =&gt; this.updateValue(change));
    }
  
    codemirrorInit(config) {
      this.ngZone.runOutsideAngular(() =&gt; {
        this.instance = CodeMirror.fromTextArea(this.host.nativeElement, config);
        this.instance.setValue(this._value);
        this.instance.on('change', () =&gt; {
          this.changeSubject.next(this.instance.getValue());
          // this.updateValue(this.instance.getValue());
        });
  
        this.instance.on('focus', (instance, event) =&gt; {
          this.focus.emit({instance, event});
        });
  
        this.instance.on('cursorActivity', (instance) =&gt; {
          this.cursorActivity.emit({instance});
        });
  
        this.instance.on('blur', (instance, event) =&gt; {
          this.blur.emit({instance, event});
        });
      })
  
    }
  
    updateValue(value) {
      this.value = value;
      this.onTouched();
      this.change.emit(value);
    }
  
    writeValue(value) {
      this._value = value || '';
      if (this.instance) {
        this.instance.setValue(this._value);
      }
    }
    onChange(_) {}
    onTouched() {}
    registerOnChange(fn) { this.onChange = fn; }
    registerOnTouched(fn) { this.onTouched = fn; }
  }
  </code></pre>
  
  <p>I've run out of ideas how to completly detach zone for 3rd party library, any help is appreciated.</p>
  
  <p>P.S. Don't mind doubled <code>changeDetector.detach()</code>.</p>