Dev48
ЯЗЫК
  • О нас
  • Услуги
  • Индустрии
  • Технологии
  • Статьи
  • Контакты
Забронировать звонок
    Главная/Статьи/Kak turbopack razbivaet vash javascript na chanki
Dev48
info@dev48.org+375 29 320-40-96WhatsApp@isky_by

© 2026 · Все права защищены.

Как Turbopack разбивает ваш JavaScript на чанки

Источник: Next.js•27 сентября 2026 г. в 07:35

Как Turbopack разбивает ваш JavaScript на чанки

Разбиение на чанки в Turbopack ускоряет загрузку страниц и позволяет использовать общий код на разных страницах. Мы выпустили новые экспериментальные функции для улучшения разбиения в Next.js 16.3.

Откройте вкладку сети (network) на этой странице, и вы увидите список файлов JavaScript с казалось бы случайными именами:

Сеть

Нажмите на один из них, отмените минификацию, и вы увидите примерно следующее:

Это чанк. Turbopack генерирует их десятками для вашего приложения Next.js. В них хранится ваш собственный код, пакеты, от которых вы зависите, и среда выполнения, которая связывает всё это воедино.

«Чанкинг» (разбиение на чанки) — это процесс определения того, какой код попадает в какой чанк. Существует множество способов разбиения, каждый из которых имеет свои плюсы и минусы.

Начнем с самого простого подхода: один чанк, содержащий весь JavaScript, который использует ваше приложение.

Все 355 модулей в одном чанке, загружаемые на каждой странице.

app.js

Теперь этот чанк загружается для каждой страницы. И поскольку каждая страница использует один и тот же чанк, каждый последующий запуск после первого приводит к попаданию в кэш. Отлично. Навигация будет быстрой.

Однако вы, вероятно, уже заметили обратную сторону медали. Загрузка страницы с минимальным количеством JavaScript или вообще без него все равно означает загрузку JavaScript для каждой другой страницы. Тьфу. По мере роста вашего сайта каждая загрузка страницы становится все тяжелее и тяжелее. В долгосрочной перспективе это нереализуемо.

Мы могли бы перейти к схеме «один чанк на страницу». Это позволило бы сохранить чанки компактными, и мы бы никогда не отправляли лишний код. Идеально!

Один чанк на страницу. Те же 355 модулей разбиты на 8 чанков, причем всё, что используется совместно на разных страницах, дублируется в каждом чанке, которому это необходимо.

/docs

/learn

/blog

/showcase

/team

/governance

/telemetry

Но тогда мы потеряем кэширование. Если каждая страница использует <Footer />, его код в итоге попадает в чанк каждой страницы. Посетитель, открывающий четыре страницы, четыре раза скачивает один и тот же код футера.

Поэтому нам нужно что-то более гранулированное. Что, если бы каждый модуль получил свой собственный чанк? Ничего лишнего никогда бы не отправлялось, а модуль, используемый совместно на разных страницах, скачивался бы только один раз.

Один чанк на модуль: 355 отдельных чанков, каждый из которых отправляется один раз и представляет собой отдельный сетевой запрос.

Отлично, есть одна небольшая проблема: это сотни сетевых запросов крошечных файлов JavaScript. Каждый из них влечет за собой накладные расходы, и сотни таких запросов замедлят работу сайта. HTTP/2 удешевил запросы, но каждый запрос по-прежнему несет накладные расходы. Алгоритмы сжатия (например, gzip) также работают хуже с большим количеством мелких файлов, поскольку они могут находить повторяющиеся паттерны только в пределах одного файла. Словари сжатия помогают, но не решают эту проблему.

Меньше запросов или меньше кода

Итак, перед нами стоит следующая задача: мы хотим добиться минимально возможного размера загрузки и минимального количества запросов. К сожалению, эти две цели противоречат друг другу. Меньшее количество более крупных чанков означает меньшее количество запросов, но чем больше они становятся, тем менее пригодны они для повторного использования на разных страницах.

Решение Turbopack заключается в объединении меньших чанков в более крупные. Самое сложное — решить, какие именно объединять и когда такое объединение действительно приносит пользу.

Для этого нам потребуется ввести новый термин — группа чанков (chunk group). Группа чанков — это набор чанков, которые загружаются вместе. Например, все чанки, используемые для /home, принадлежат к одной группе чанков, а для /blog — к другой:

Две группы чанков, по одной на каждый маршрут. Группа для `/home` загружает три чанка; группа для `/blog` загружает два. Один чанк принадлежит обеим группам, поэтому его объединение с соседом остается безопасным только в рамках одной группы.

Группы чанков решают проблему избыточной отправки кода. Turbopack объединяет только чанки из одной группы, а чанки в группе в любом случае всегда загружаются вместе, поэтому их объединение не может добавить ничего такого, что страница и так не скачивала бы.

Но как оптимизировать попадания в кэш, не перегружая браузер запросами?

Чтобы разобраться в этом, представьте два сценария визитов: когда вы заходите на страницу и уходите, и когда вы заходите на страницу, а затем переходите на другую. Этот анализ естественным образом применим и к сессиям с тремя и более посещениями страниц.

Для таких случаев давайте рассмотрим затраты или выгоду от объединения чанков для <Footer /> и <VideoPlayer />. Назовем чанк <Footer /> чанком A, а чанк <VideoPlayer /> — чанком B.

A используется на каждой странице, а B — только на главной странице. Оба находятся в группе чанков главной страницы, поэтому они являются кандидатами на объединение.

Если посетитель загружает главную страницу и уходит, объединение всегда в выигрыше. Это один запрос вместо двух, и оба чанка все равно были нужны.

Если они загружают вторую страницу, это зависит от того, нужны ли этой странице оба чанка или только один. Допустим, они переходят с главной страницы на страницу с правовой информацией (legal). Странице с правовой информацией нужен A, но не B. Поскольку A и B были объединены в один файл, объединенный файл там бесполезен, поэтому браузер снова скачивает A отдельно. Теперь посетитель скачал A дважды.

Объединение окупается при переходе только тогда, когда обеим страницам нужны оба чанка. В этом случае объединенный файл используется повторно, и вы экономите один запрос.

Вот другие возможные сценарии навигации. Каждая строка ниже представляет собой двухстраничную сессию, записанную как то, что нужно первой странице, а затем то, что нужно второй. Цифры показывают, как объединение A и B изменяет общее количество запросов и объем загруженного кода за эту сессию по сравнению с их раздельном хранением.

При рассмотрении вопроса об объединении чанков A и B мы вычисляем количество групп чанков, которые используют только A, только используют B и используют A + B. Мы взвешиваем затраты или выгоду от объединения с учетом вероятности каждого сценария.

Наконец, мы оцениваем случаи посещения одной страницы и посещения двух страниц с учетом их вероятностей. По нашим оценкам, 2/3 сессий состоят из одной страницы, а 1/3 включают две или более.

Три стратегии чанкинга

Вот сравнение рассмотренных нами версий чанкинга.

Чтобы получить цифры для каждой из них, я посетил nextjs.org с тремя различными конфигурациями чанкинга Turbopack: никогда не объединять, настройки по умолчанию и объединять всё в каждой группе чанков.

Для каждой версии я выполнил одинаковую серию переходов, измеряя количество запросов и объем загруженного клиентского JavaScript.

Как видите, чанкинг — это вопрос баланса. На сайте nextjs.org настройки по умолчанию сократили количество запросов более чем в два раза по сравнению с отсутствием объединения при отправке чуть меньшего объема кода; максимальное объединение сократило количество запросов еще сильнее, но в целом отправило на 10% больше кода. Однако, если бы мы реже переходили по страницам, максимальное объединение оказалось бы более оптимальным. Объединение каждого чанка в группе в один большой чанк давало преимущества при первоначальной загрузке страницы, но дорого обходилось в долгосрочной перспективе.

Новые возможности чанкинга в Next.js 16.3

Эффективность чанкинга ограничивается двумя факторами. Объединение определяется на этапе сборки, до того, как кто-либо посетит сайт, поэтому оно не может реагировать на то, что уже закэшировано в браузере. Кроме того, алгоритм должен угадывать, как люди перемещаются по вашему сайту, именно поэтому посещения одной страницы оцениваются с коэффициентом 2/3. Этим летом в рамках моей стажировки в команде Turbopack я работал над обеими проблемами, а также над сокращением того, что изначально попадает в чанки.

Более умная загрузка чанков

В таблице выше показана стоимость объединения. Когда посетитель загружает страницу с A, а затем страницу с A + B, объединение заставляет его скачивать A дважды. Сборщик не может этого избежать, потому что на этапе сборки он не знает, что уже есть у браузера. Среда выполнения знает.

Начиная с версии Next.js 16.3 или выше, включение параметра experimental.turbopackChunking.generateComponentChunks в вашем next.config.js заставляет Turbopack генерировать неразделенные версии чанков наряду с объединенными. Мы отслеживаем, из каких элементов состоит каждый объединенный чанк и какие из них уже были загружены, поэтому во время запроса мы можем выбрать то, что выгоднее: объединенный чанк или только недостающие части.

Это работает и в обратную сторону. Если посетитель уже загрузил объединенные A + B, мы можем пропустить повторную загрузку только A.

Таким образом, мягкие навигационные переходы загружают меньше ненужного кода, и мы получаем преимущества объединения без дополнительных затрат на навигацию.

Взгляните на это демонстрационное приложение, чтобы увидеть разницу:

generateComponentChunks: false

generateComponentChunks: true

Мы также экспериментируем с директивой only-if-cached, которая позволяет нам проверять, что у посетителя закэшировано при его прибытии. Это распространит те же улучшения на пользователей, которые покидают сайт и возвращаются позже.

Чанкование на основе аналитики

Возможно, вы заметили, что в нашем алгоритме чанкования мы делаем много допущений о веб-сайтах. Например, весовой коэффициент 2/3 — это предположение. Это разумное значение по умолчанию для многих сайтов, но не обязательно правильное для какого-то конкретного сайта. Если вы знаете, как пользователи действительно перемещаются по вашему сайту, вы можете сообщить нам об этом.

Теперь вы можете настроить эти параметры в файле next.config.js в разделе experimental.turbopackChunking:

  • firstPageLoadPriority: смещает вес между сценариями для одной и двух страниц. Более высокое значение (между 0 и 1) расставляет приоритеты в пользу быстрой начальной загрузки, потенциально в ущерб навигации. Показатель отказов (Bounce rate) — разумное начальное значение. По умолчанию мы используем 0.67.
  • priorityRoutes: список страниц, скорость загрузки которых имеет наибольшее значение. Мы будем более активно объединять чанки на этих маршрутах.
  • clusters: группы часто посещаемых вместе маршрутов, каждая из которых определяется массивом регулярных выражений. Мы будем более охотно объединять пересекающиеся чанки внутри кластера. Но если кластер объединяет страницы, использующие только A или только B, со страницами, использующими обещанные чанки, мы будем объединять их в меньшей степени.

Меньше чанков и меньшего размера

Все вышесказанное касается того, как группировать код. Последний набор функций направлен на то, чтобы изначально отправлять его в меньшем объеме. Я работал над следующими функциями для поддержки этого:

  • Tree-shaking для CJS-модулей: ранее мы поддерживали это только для ESM, поэтому неиспользуемые импорты и экспорты в CJS-модулях отправлялись клиенту. Включите эту функцию с помощью experimental.turbopackCjsTreeShaking. В будущих версиях Next.js она будет включена по умолчанию. Я также расширил набор ESM-модулей, которые мы можем анализировать и обрабатывать с помощью tree-shaking. Сюда вошло улучшение поддержки индексных файлов (barrel files) в динамических импортах.
  • Я также расширил набор ESM-модулей, которые мы можем анализировать и обрабатывать с помощью tree-shaking. Сюда вошло улучшение поддержки индексных файлов (barrel files) в динамических импортах.
  • Общая среда выполнения Turbopack: теперь один чанк среды выполнения заменяет чанки для каждой страницы. Включите его с помощью experimental.turbopackSharedRuntime. Это позволяет избежать блокирующего запроса и сэкономить около 10 КБ JavaScript на стороне клиента при каждом переходе после первого. Позже эта функция также будет включена по умолчанию.
  • Более легкая среда выполнения по умолчанию: среда выполнения больше не включает код WebAssembly и Web Worker по умолчанию. Мы определяем, когда вы используете эти модули, и добавляем код загрузки в этот момент.

Попробуйте в деле

Попробуйте эти новые функции в Next.js версии 16.3 или выше. А если вы хотите узнать больше о чанковании (включая чанкование CSS), ознакомьтесь с недавним докладом Тобиаса о компромиссах и ограничениях чанкования.

← Все статьи

О чём эта статья