у них, видимо, code-splitting "из коробки", но ты и сам можешь настроить, если с вебпаком "в ладах"
При серверном рендеринге(поправьте, если ошибаюсь) сначала создаётся экземпляр store, затем он вскармливается корневому элементу приложения, чтобы данные заполнили компоненты(словно вода заполняет иссохшее русло реки), затем всё это "добро" рендерится в старый-добрый html и возвращается на клиент.
Затем на клиенте react проверяет совпадают ли значения аттрибутов data-react-checksum
клиетского приложения и серверного. Если совпадают, это означает, что если мы "поднимем" клиентское приложение(дорогая операция), то что мы получим будет совпадать с тем, что отправил сервер. Выходит, что этого можно избежать. Именно это и делает реакт, просто копирует полученный на сервер DOM в клиентское приложение.
Next.js делает всё это за тебя. С одной стороны это хорошо, не надо возиться с настройкой серверного рендеринга, с другой стороны - плохо, потому что всё-таки стоит знать как всё происходит в деталях на сервере.