Как работать с очень длинными списками в JavaScript (angular, react, vuejs)?
(angular не использует vdom, для него история другая) перерисует целиком свой виртуальный dom 
Давайте немного проясним: виртуальный DOM - это грубо говоря js объект содержащий другие объекты.
При добавлении нового сообщения туда добавится новый объект и весь DOM сравнится со старой версией с помощью diff-алгоритма специфичного для конкретного фреймворка.И только результат этого сравнения добавится в реальный DOM.
Работа с объектом значительно быстрее работы с самим DOM-ом, поэтому чтобы оно начало работать заметно медленее у вас должен быть дикий уровень вложенности или очень большой DOM.
100 сообщений и 50 контактов - это небольшие цифры, с таким любой из упомянутых фреймворков справится без просадок.
Вот пример бенчмарков с большим количеством объектов(1000+) для многих фреймворков на примере незамысловатой таблицы:
www.stefankrause.net/js-frameworks-benchmark6/webd...
(там же есть ссылка на репо чтобы увидеть как она выглядит)
Как видите, там в таблицу уже содержащую 10 000 добавляется еще 1000(!) объектов, и многие фреймворки впонле с этим справляются.
В реальности же, вам вряд-ли придется добавлять такие цифры, потому что подгружают изначально обычно меньшее количество: такое, которое пользователь сможет увидеть в одном экране, все остальное догружается постепенно по мере надобности. То же самое касается вашей истории чата, ее стоит подгружать только за тот период, за который она необходима пользвателю.
В ангуляре для того, чтобы не перерисовывать весь список используется  ngForTrackBy https://angular.io/api/common/NgForOf в реакте для этого используется проперти key, при чем он тебе не отрендерит шаблон, если ты его не укажешь