Продуктивність AfterPack: виміряні швидкість і розмір

Скільки AfterPack коштує збірці й сторінці: виміряний час обфускації на бандлі 185 KB, час і розмір завантаження wasm-збірки, розмір результату, час запуску сторінки й ціна виконання кожного пресета, скільки захищений код платить за читання глобального об'єкта хоста і як новий сід впливає на кешування.

Кожне число на цій сторінці виміряне, а не оцінене. Якщо в таблиці не сказано інше, машиною був Apple M2 Max, 32 GB RAM, macOS 26.6.2. Нічого тут не є порівнянням з іншим інструментом.

Більшість вимірювань зроблено на фікстурі next16_framework_runtime: 185 KB рантайму фреймворку, який постачає реальна збірка Next.js 16. Це один уже мініфікований продакшн-бандл, тобто саме та форма, на якій AfterPack насправді працює.

Час збірки

Виміряно 2026-09-29 на машині, зазначеній вище, з AfterPack 0.2.0 на пресеті за замовчуванням light.

Що запускалосяВхідЧасПропускна здатність
npm-пакет на бандлі 185 KB185 KB229 ms0.79 MB/s
Сам рушій, той самий бандл185 KB243 ms0.74 MB/s
npm-пакет на багатофайловій збірці 766 KB766 KB1 362 ms0.55 MB/s

Орієнтуйтеся на рядок npm. Це опублікований пакет, який виконує роботу так, як її виконує плагін або npx afterpack@latest, тож він включає витрати на передачу вашого коду в рушій і назад. Рядок рушія є тим самим бандлом на тому самому пресеті без цих витрат, і його час виміряно окремим інструментом. Обидва результати відрізняються не більше ніж на 15 ms, тож пакування не додає вимірюваних витрат.

Пікове використання пам'яті в рядку рушія становило 20.8 MB понад базовий рівень для одного файлу 185 KB. Багатофайловий запуск на 766 KB у піку займав 76 MB.

Обфускація є кроком після збірки, тож цей час додається до вашої збірки, а не до завантаження сторінок вашими користувачами. Збірка 766 KB приблизно за 1.4 секунди дає уявлення про масштаб витрат на пресеті за замовчуванням; вищий пресет коштує більше.

Wasm-збірка

@afterpack/wasm є тим самим рушієм, скомпільованим у WebAssembly, для Cloudflare Worker, для Node і для пісочниці на цьому сайті.

Час, за пресетомNode 24
Бандл 110 KB, light147 ms
Бандл 185 KB, light237 ms
Бандл 185 KB, medium1 011 ms
Бандл 185 KB, extreme2 603 ms

Кожен час є медіаною дев'яти запусків з увімкненою Protection Map, виміряною 2026-10-17 з @afterpack/wasm 0.2.6 на машині, зазначеній вище. Бандл 110 KB є чанком polyfills із тієї самої збірки Next.js 16.

Завантаження займає 4.36 MiB без стиснення та 1.25 MiB після gzip. Воно відбувається один раз на ізолят Worker або на вкладку браузера, а не один раз на збірку.

Швидкість примусово перевіряється: перевірка в CI вимірює час роботи рушія на фікстурі 185 KB на пресеті extreme з увімкненою Protection Map, поруч із закріпленим еталонним рушієм у тому самому запуску, і завершує збірку помилкою, якщо найшвидший запуск рушія триває понад 13.5 раза довше, ніж у еталонного.

Wasm працює повільніше за нативну збірку, і його швидкість є свідомим компромісом: попередня збірка, оптимізована за розміром, виходила на 39% меншою після gzip і в 2.1x повільнішою, через що реальна збірка з 66 файлів перевищувала дедлайн хмарного рушія. Перемогла швидкість.

Це час на ноутбуці, а не в Cloudflare. Ізолят Worker у мережі Cloudflare має менше CPU, холодніший кеш і обмеження CPU на запит, тож той самий вхід обробляється там довше, ніж показує ця таблиця. Перш ніж розраховувати бюджет на основі цих чисел, виміряйте на платформі, на якій працюватимете.

Розмір результату

Обфускація додає байти. Виміряно 2026-10-16 з AfterPack 0.2.6 на п'яти фікстурах (рантайм 185 KB, описаний вище, ще два чанки Next.js 16, бандл Vite React і чанк PostHog), для кожного пресету, на результаті після gzip порівняно з тим самим файлом, мініфікованим:

ПресетМножник результату після gzip
minifyвід 1.09x до 1.17x
lightвід 1.29x до 1.60x
mediumвід 6.04x до 8.33x
hardвід 6.62x до 9.23x
extremeвід 8.25x до 11.19x

Кожен діапазон є розкидом між фікстурами, а не довірчим інтервалом, і він монотонно зростає разом із пресетом.

Цільова складність визначає розмір результату; ці діапазони є вимірами того, що видав кожен пресет. Задайте явний inflation.max, коли хочете, щоб збірка завершувалася помилкою, а не перевищувала обраний вами розмір; див. Пресети.

Малі файли виходять пропорційно більшими за будь-яке з цих значень, бо кожен результат містить фіксовані накладні витрати рантайму рушія. Дивіться на співвідношення на реальному бандлі.

Завантаження сторінки

Важчий пресет сповільнює запуск сторінки, бо браузер розбирає й виконує більше коду, перш ніж сторінка почне реагувати. Виміряно 2026-10-24 з AfterPack 1.0.0 на машині, зазначеній вище, у headless Chromium: п'ять малих застосунків з end-to-end тестів плагінів AfterPack, кожен зібраний один раз без AfterPack і по одному разу для кожного пресету з усім бандлом на цьому пресеті, і віддані з localhost, тож мережевий час не враховано. Кожна цифра є часом від навігації до першого кліку по лічильнику застосунку, який його змінює, медіаною п'яти холодних завантажень, кожне в новому контексті браузера.

ЗастосунокБез AfterPacklightmediumhardextreme
Vite і React35 ms52 ms253 ms295 ms596 ms
Vue на Vite31 ms36 ms176 ms117 ms199 ms
Острови Astro44 ms48 ms205 ms249 ms622 ms
SvelteKit27 ms32 ms84 ms89 ms162 ms
Next.js, webpack42 ms74 ms462 ms573 ms1 010 ms
Next.js, webpack, CPU сповільнено в 4 рази145 ms234 ms1 652 ms2 215 ms3 844 ms

Останній рядок учетверо сповільнює CPU Chromium, що грубо імітує телефон середнього класу.

Без захисту сторінки завантажують від 168 KB до 453 KB JavaScript. Розмір зростає приблизно в стільки ж разів на кожному застосунку (співвідношення наведено на сторінці Пресети); час запуску зростає залежно від того, скільки цього коду виконується до першого кліку. Час виконання скриптів у головному потоці на medium становив 4.5x від незахищеної збірки на Vue і 14.7x на Next.js. Власний рантайм фреймворку є частиною кожного бандла, і кожен пресет захищає також його.

На light перший робочий клік відбувався на 4–32 ms пізніше. Починаючи з medium, виміряйте власні сторінки, перш ніж випускати пресет на весь бандл; на сторінці Пресети описано, до якої частини коду кожен тариф дозволяє застосувати пресет.

Ціна виконання

Захищений код працює повільніше за оригінал, і ціна зростає з пресетом. Виміряно з AfterPack 0.2.4 на власному x86_64 CI-раннері, Node 22: чотири програми з щільними циклами, кожна цифра — час виконання захищеної програми, поділений на час оригіналу, медіана по чотирьох.

ПресетЧас виконання щодо оригіналу
minify1.0x
light2.1x
medium32.5x
hard35.0x
extreme37.3x

Це найгірші випадки: цикли не роблять нічого, крім захищеної арифметики, а звичайний код застосунку проводить у таких циклах значно менше часу. Перевірка в CI зупиняє рушій, якщо медіана пресета перевищує його цифру тут у 2.5 раза.

Гаряче числове ядро, як-от фільтр зображень, крок фізики чи внутрішній цикл парсера, платить майже повну цифру. З ключем Pro тримайте його на light за допомогою пресета ділянки, а решту бандла лишайте на глобальному пресеті. Збірка Free ігнорує нижчий пресет ділянки, тож на Free тримайте глобальний пресет на light, коли гаряче ядро важливе.

Читання глобальних змінних хоста

Захищений код читає глобальну змінну хоста, як-от URL, через перевірку, яка кидає той самий ReferenceError, що й ваш оригінальний код, коли цієї глобальної змінної немає. Вартість перевірки залежить від того, де виконується код.

Виміряно 2026-10-13 з AfterPack 0.2.4, у Node 24 на arm64 Mac, на циклі, що читає URL один раз за ітерацію. Кожне значення є часом виконання захищеної збірки, поділеним на час виконання тієї самої захищеної збірки, що читає глобальну змінну без перевірки. Діапазон охоплює два сіди, для кожного взято найшвидший із 5–7 чергованих раундів.

ПресетЗвичайний контекстУсередині node:vm
light1.00x2.7x
mediumвід 1.06x до 1.13xвід 2.0x до 2.1x
hardвід 1.04x до 1.05xвід 1.9x до 2.1x
extremeвід 1.10x до 1.18xвід 2.0x до 2.1x

Звичайний контекст означає сторінку в браузері, worker або головний контекст Node; цю колонку виміряно в потоці Node worker. Там перевірка не коштує нічого вимірюваного на light. Починаючи з medium, додатковий захист пресету обгортає перевірку, і за це доводиться платити на кожному читанні.

Контекст node:vm проводить кожен пошук у своєму глобальному об'єкті через callback, тому там той самий цикл виконується від 1.9x до 2.7x довше, ніж без перевірки. Тест чи бенчмарк, що запускає захищений код усередині node:vm, бачить цю вартість на її верхній межі, тож вимірюйте код, який читає глобальні змінні хоста в гарячому циклі, там, де його запускають ваші користувачі.

Кешування між релізами

Новий сід змінює байти кожного захищеного чанка, зокрема й тих, чий вихідний код не змінився. Плагіни бандлерів додають сід до імені файлу кожного чанка, тож після релізу відвідувачі, які повертаються, знову завантажують увесь захищений JavaScript. Фіксований сід зберігає незмінений чанк побайтово ідентичним і в кеші, але тоді цей чанк зберігає й свою форму між релізами. На виводі Next.js, Angular, Vite чи webpack CLI перейменовує файли з хешем вмісту так само, як плагіни; на іншому виводі імена лишаються, тож зафіксуйте seed або задайте такому результату короткий час кешування. Докладніше в розділі Імена файлів і кешування.

Далі

  • Пресети: бюджет розміру, який задає кожен пресет, і скільки коштує його підвищення.
  • Збірки та CI: де цьому кроку місце в пайплайні.
  • Cloudflare Workers: запуск wasm-збірки в ізоляті.
  • Пісочниця: wasm-збірка, що працює у вашому браузері й сама себе вимірює.