Галоўная / Артыкулы

Настройка новых кантролів чанкавання у Turbopack у Next.js 16.3

Практычны ўзгляд на новую настройку turbopackChunking у Next.js 16.3, якая пояснюе, як maxChunkCountPerGroup і generateComponentChunks вплываюць на размер пакета і кэшаванне.

6 хв чытання1482 слоў

Было 4:40 паўтаркі, самэй той момант, калі вы закрываеце ноутбук на выходныя, калі звычная практыка разгортання дапаможнага прыстрою для панелі керування раптам перестала быць звычайной. Компіляцыя, якая зазвычай завершалася за 40 секунд, гэты раз зайняла трохі больш чым тры хвіліны, а пакет кліента для галоўнага маршруту збільшыўся на майже 300 кБ. Жадных маршрутаў не было зменяна, і жадных новых залежнасцей не было дадана, якія моглы б гэта поясніць. Џедыным зменам таго тыдня была незначная апгрэйдваная версія Next.js. Пасля чаго настала вечара, пры якой трэба было стаяць і разглядаць вікно «Сеть», спаглядая, як чатыры вельмі большыя файлы JavaScript завантажаюцца адні за іншым, там як раней для гэтай работы выкарыстоўвалася дзесятка маленькіх файлаў.

Прычыной не была памылка. Це была логіка чанкавання Turbopack, якая працавала абсалютна так, як і было запланавана, проста не так, як чакалі.

Чаму проблема чанкавання так і не была рашыта

Эта проблема існуе ў тых, хто займаецца пакетаваннем, прыблізна дзесяць гадоў. У Webpack-а клас SplitChunksPlugin апублікаваў настройкі такія як minSize, maxSize і cacheGroups, якія практычна ніхто не розумеў з самых аснов, іх большасць была скопіявана з якогось тэпа на Stack Overflow, які існуе з 2019 года. Основны компроміс застаецца незменным: адкладанне всіх элементаў у меншую колькасць большых частак зменшае колькасць HTTP-запытанняў, але пагаршуе кэшаванне, адтолькі як адна змянена частка CSS можа зробіць недзейнаўчым цэлы пакет размерам 500 кБ. Раздзеленне на большую колькасць меньшых частак павышае дзейнаўчасць кэшу, але збільшае колькасць запытанняў, што быстра стае помітным на повольных з’ўязках.

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

Што змянілася ў 16.3

У Next.js 16.3 поведанне злучэння больш не ўкладзенае ў адну незрозумелую гіпертэзу, а тепер выказваецца безпосередня через настройкі. Быў даданы новы блок turbopackChunking, а два найважлівейшыя настройкі — maxChunkCountPerGroup і maxMergeChunkSize.

// next.config.js
module.exports = {
  experimental: {
    turbopackChunking: {
      maxChunkCountPerGroup: 40, // default
      maxMergeChunkSize: 200_000, // bytes, default
    },
  },
};

Змена значэння maxChunkCountPerGroup на меньшыя цікавіцы спрыяе болей агрэсывнаму з’еднанню дадзеных: менша колькасць запытак праз завантажэнне сторункі, але слабейшая збережаннё кэша пад час навігацыі. Падвышэнне цікавіцы стварае меньшыя, але болей чакловыя фрагменты дадзеных, якія застаюцца недастрымленымі нават калі зменяюцца несувязаныя часткі прыемплу. maxMergeChunkSize абмежвае розмер з’еднанага фрагмента, паказваючы, насколькі вялікі ён можа стаць, перш чым Turbopack перастане дадаваць да яго дапаможны код, што ўжыткова, калі адна вялікая залежнасць вендара традыцыйна поглотвае ўсё навакола сябе.

Раней такіх налаштаванняў не існавало. Вы проста атрымлівалі тое, што давала стандартная схема, і прыменялі способы для ўсунуць яе наследкі.

Варыянт частковага разбівання компонентав

Іншыя значныя дадачкі — это generateComponentChunks, який распрастраńвае можлівасці частковага разбівання Turbopack на адзінкавыя компоненты, а не толькі на межах маршрутаў.

module.exports = {
  experimental: {
    turbopackChunking: {
      generateComponentChunks: true,
    },
  },
};

Актывацыя гэтага параметра прыводзіць да таго, што Turbopack выдае як з’едыненыя, так і нез’едыненыя версіі частак, што дазволяе системе запуску на момент завантажэння выбраць тую версію, якая трэба, на аднойчынку з тым, што вже знаходзіцца у кэшы браузера. Якщо якая-небудзь спільная складовая была збережана ў кэшы пасля поперадньаго візіту на стороннюю сторонку, система запуску можа запрашаць меншы нез’едынены частак заместо таго, каб завантажыць з’едынены пакет, які дублюе вялікі частка коду, які вже ў кэшы. Гэта принципова іншая падход, чым спроба заздалегідь вырачыць ідеальны розмер частака — гэта першы прыклад, калі інструмент для стварэння пакета перакладае гэта рашэнне на момент запиту, заместо таго, каб зафіксаваць яго ў момент стварэння пакета.

Што мы на самай працы бачылі

Команда, яка тэставала гэта ў даскладнай прыемлі, увёлі функцыю generateComponentChunks і стала спазірваць, што будзе вядуцца працоўваць у наступныя дні. Пачатковая загрузка сторанкі практычна не змянілася, скасціўшыся майже на 2%. Але паўтаральныя навігацыі, якія станавяць большую частку рэальнага выкарыстоўвання такой прыемлі, як даскладная панель, прывелі да таго, што сярэднія размеры JS-кода, які перадаўцца за адну навігацыю, зменіліся праўда на 35%. Гэта і є галоўная ценнасць гэтага рашэння: гэта не функцыя, якая мае на мету зменшыць час першай загрузкі, а тая, якая падтрымвае рэгламент працы з прыемлёю праўда дзесять хвілін падряд. Большасць тэстаў размеру пакета дадзеных, якія циркулююць у Інтэрнете, апранаваныя да зьмеравання абсалютна іншага сцэнарыю, які не відбівае рэальны спосаб выкарыстоўвання прыемлей з інтэнсіўным внутршнім навігацыяным режымам.

Тая ж сама каманда таксама пераглянула значэнне maxChunkCountPerGroup для сайту маркетынгу, які знаходзится ў там самым monorepo, зменшыўшы яго з 40 да 24. Што стосуецца гэтага сайту, то там пераважна відбываюцца сесіі з адной сторанай, таму дадатковыя запиты да сеті, якія ствараюцца за дапамою болей дробнай структуры чакунков, былі проста зайвым навантажэнням без жадных практычных наследкіў. Той самы інструмент, але працэс налаштавання — працоўны, і обе выборы былі правильныя для сваіх адпаведных контэкстаў. Гэта, мабыць, справжні урок: няма жадной ўніверсальна правильной стратэгіі чакункавання, Turbopack проста дапамагаў здзейсніць гэты выбор за вас без запытанняў.

Як гэта паўтараецца з старымі налаштаваннямі Webpack

Для тых, хто гадзіў гады над splitChunks.cacheGroups, аналагам у гэтай новай системе є maxMergeChunkSize; на вядмэн ад багацтва назв у Webpack, гэтае значэнне працуе абсалютна так, як і павінна. Канфігурацыя Webpack аб’ядналася дзесятками слаба задокументаваных настаўок, якія взаімадзейвалі між сабою способамі, якія ніхто не могаў цалком зрозумець, і багато команд застаўаліся з канфігурацыйным файлам, залишытым інжынерамі, якія вучора пайшлі, і ніхто не наважваўся яго зменіць. Падход Turbopack ўмышлена простейшы: у вас є два-тры настаўкі заместо дзесятка, што прагарыць частку гнучкасці для асабліва рэдкасных ситуацый, але таксама скрачвае час між тым, калі вы заўважылі, што „наш бандл не такі“, і моментам, калі вы знаеце, якое самэ значэнне трэба паслядзіць. Гэты компроміс є разумным для прыняцця, асабліва для тых, хто не хочаць...

Не будзе большэй ніколі такой канфігурацыі cacheGroups, яка працавала бы калькамі на гады.

Є ўсё жа адна разліка, якую варта выявіць окрема. Webpack у значныя меры змушваў вас разважаць пра падзеле на чакі ў момент складання, разглядаючы выход дакумента stats.json і намагаючыся спрогназаваць, што на самай працоўным браузере рэальнага відвідчыка будзе знаходзіцца ў кэшы. Падзел на чакі на рэвэлеце компанентаў у Turbopack пераносіць частку гэтых разваг у момент запыту, калі працоўны час можа пераканацца ў рэальным стане кэшы, а не толькі здагадвацца пра ўсё гэта заздалегідь. Це справжнія архітектурны перакід, а не проста змена назвы флага канфігурацыі.

Адзін недагодак

Эта функцыя яшчэ атрыбутавана як эксперыментальная, і дакументацыя чытра пра гэта паведамляе. Адна команда сталкнулася з ситуацыёй, калі дынамічна імпортаваная бібліятэка для стварэння графікав была раздзелена так, што падчас развяртання на працоўнай сістэме на час з’явілася памылка „Не удалося завантажыць чак“, тое сама проблема з застарэлымі рэферэнсамі чак, якая вплыла практычна на кожны інструмент для збірання коду, які падтрымлеў роздзелэнне коду. Жорсткая аднаўлення рашыла проблему для тых корыстнікаў, якія на ёю сталкнуліся, але гэта ўжо ўсё-такі корыстнае нагадванне пра тое, што болей дробнае роздзелэння коду расшыроўвае можлівасці выхаду такога конкрэтнага типу памылак, а не зменшвае іх.

Ешчэ ёсць прыбліжна проблема налаштавання гэтых параметраў без рэальных дадзеных пра трафік, што па суты ёсць адгадваннем. Варта стрымацца ад прагнення змяніць стандартныя настройкі у новым проекте, пакуль у вас не будзе рэальных статыстык навігацыі, якія пакажуць, чырыя вашы візітары зазвычай застаюцца на адной сторонцы, чырыя ж переходзяць між дзесяткамі або большай колькасцю сторонак у адной сесіі. Якщо такіх дадзеных ўжо няма, гэта як і будзь-яя іншая прычына, каб пачаць ўсё-такі іх збіраць пры перадзеяванні будь-какіх налаштаванняў. Налаштаванне слепа несе рэальную пахібку — можна досягнуць горшага коефіцыента запам’ятавання дадзеных, чым даў бы стандартны варіант, і такая регрэсія праходзіць непазначальна. Ніхто не падае адзыв пра баг пад загаловкам «навігацыя здавалася трохі медленнейшая», яны проста перестаюць вяртацца.

Тады, чы рэальна паўная актывацыя?

Для сцэнарыю дашборда адказ быў «так», і настройка застала увыклена. Для маркетынговага сайту была скорэчана адна цифра, і на гэтым усё завершылася. Нічыга з гэтага не відновляе фундаментальна зламаныя прыкладненне, і якщо ваш пакет занадта вялік чераз залежнасць, якая вам на самай працэ не патрэбна, ніякая стратегія частковага выканання не дапаможае паспясці з гэтай памылкай. Гэтае функцыянальнасць праставляе сабою спрямаваныя рашэння для вузкага калекства, што ўсёлякім чынам вядомае адліненне ад багацтва функцыяй інструментаў для стварэння, якія выходзяць гэтага года; такое мненне мае важнасць, бо яго высказваюць тыя, хто витрачаў больш вечароў, ніж хацелі, на борьбу самэ з такімі багамі.