# Обфускація збірки webpack

@afterpack/webpack під'єднується до compilation.hooks.processAssets і обфускує ваші ассети, перш ніж webpack їх запише.

Source: https://www.afterpack.dev/uk/docs/frameworks/webpack

`@afterpack/webpack` — це плагін для webpack 5: клас з `apply(compiler)`. Він зчитує [директиви `@afterpack`](https://www.afterpack.dev/uk/docs/directives) з вашого вихідного коду до мініфікації, а потім запускає рушій на `compilation.hooks.processAssets` одразу після того, як webpack призначає імена з хешем вмісту, і до запису.

Байти кожного ассета зчитуються з компіляції, а обфускована заміна передається назад у неї, тож webpack ніколи не записує ваш необфускований бандл. Невдала обфускація залишає каталог виводу таким, яким він був.

## Встановлення

```bash
npm install -D @afterpack/webpack
```

```js
// webpack.config.js
import { AfterpackWebpackPlugin } from "@afterpack/webpack";

export default {
  mode: "production",
  output: { path: "dist" },
  plugins: [new AfterpackWebpackPlugin()],
};
```

Експорт — це клас `AfterpackWebpackPlugin`.

## Збірка

Плагін під'єднується до `compilation.hooks.processAssets` одразу після етапу, на якому webpack обчислює хеші вмісту. Ім'я кожного чанка [слідує за його обфускованими байтами](https://www.afterpack.dev/uk/docs/builds#file-names-and-caching). Переписуються лише ассети `.js`, `.mjs` і `.cjs`, які належать якомусь чанку компіляції; чанки `.hot-update.` пропускаються. Ассет, який компілятор містить, але не збирав, наприклад маніфест, згенерований іншим плагіном, або скопійований файл, лишається без змін.

Плагіни стиснення запускаються на пізнішому етапі, тож стискають уже обфусковані байти.

`processAssets` запускається на кожній компіляції, зокрема на перезбірках у watch-режимі, і кожна перезбірка платить ціну роботи рушія. Задайте [`build.autorun: false`](https://www.afterpack.dev/uk/docs/config#build-autorun) (або `AFTERPACK_build_autorun=false`) для циклу розробки і залиште його увімкненим для продакшн-збірок.

## Перевірка

[Protection Map](https://www.afterpack.dev/uk/docs/protection-map) за замовчуванням записується, коли `devtool` створює source map і збірка не працює в CI (`CI=true` або `CI=1`); [продакшн-режим збірки](https://www.afterpack.dev/uk/docs/config#build-mode) її не вимикає. Продакшн-збірка webpack за замовчуванням не має `devtool`, тож мапа вимкнена. Запросіть її явно:

```js
new AfterpackWebpackPlugin({ protectionMap: { enabled: true } });
```

[Значення мапи за замовчуванням](https://www.afterpack.dev/uk/docs/config#protectionMap-enabled) залежить від наявності source map бандлера, тож задайте `devtool: "source-map"`, якщо хочете, щоб вона показувала ваш оригінальний вихідний код. Без нього плагін попередить, що не знайшов source map бандлера. Якщо мапа записується, то у `.afterpack/protectionMap.html`, внесений у gitignore, і ніколи в `dist/`. Вона містить увесь ваш вихідний код. Ніколи не комітьте його і не роздавайте з сервера.

*(live Protection Map demo embed — see https://www.afterpack.dev/protection-map-demo)*

## Параметри

Будь-який [ключ конфігурації](https://www.afterpack.dev/uk/docs/config) можна передати тут в об'єкті параметрів, наприклад `new AfterpackWebpackPlugin({ preset: "hard", complexity: 40 })`. Назви точно повторюють [`@afterpack/vite`](https://www.afterpack.dev/uk/docs/frameworks/vite#options) і [`@afterpack/next`](https://www.afterpack.dev/uk/docs/frameworks/nextjs#options), тож конфігурацію можна переносити між пакетами.

## Директиви

Директиви — це можливість тарифу [Pro](https://www.afterpack.dev/uk/docs/pro). У [збірці Free](https://www.afterpack.dev/uk/docs/directives#free-builds) директива, яка посилює захист, зупиняє збірку з помилкою `DIAG_PRO_DIRECTIVE_REQUIRES_KEY`.

Директиви зчитуються плагіном із вашого вихідного коду.

```js
/* @afterpack preset=hard */
function verifyLicense(token) {
  // ...
}
/* @afterpack end */
```

Директиви бувають лише блоковими коментарями: рядковий коментар `// @afterpack …` не сканується і з'являється як [діагностика](https://www.afterpack.dev/uk/docs/diagnostics). Повна граматика — на сторінці [Директиви](https://www.afterpack.dev/uk/docs/directives#writing-one).

Збір директив пропускає `node_modules` і модулі, що не є JS/TS. Задайте [`directives.enabled: false`](https://www.afterpack.dev/uk/docs/config#directives-enabled), щоб повністю пропустити сканування; написані вручну [`regions`](https://www.afterpack.dev/uk/docs/config#regions) працюють у будь-якому разі.

## Особливі випадки

- **Сторонній код у бандлі.** webpack об'єднує `node_modules` з вашими чанками, тож немає шаблону імен вихідних файлів, який би їх розділяв. AfterPack працює зі згенерованими файлами цілком; [`paths.exclude`](https://www.afterpack.dev/uk/docs/config#paths-exclude) — це виключення на рівні файлів, коли воно вам потрібне.
- **`webpack-subresource-integrity` відхиляється.** Його атрибути `integrity` не збігалися б з обфускованими чанками. Приберіть його й обчисліть цілісність за згенерованими файлами після збірки.
- **Зупинка з помилкою (fail closed), без можливості перевизначення.** Невдалий файл або порожній результат завершують збірку помилкою, а не випускають необфускований код.

## Далі

- [Фреймворки](https://www.afterpack.dev/uk/docs/frameworks): повна матриця.
- [Vite](https://www.afterpack.dev/uk/docs/frameworks/vite): еталонна інтеграція і повна семантика параметрів.
- [Конфігурація](https://www.afterpack.dev/uk/docs/config): кожен параметр вище і де його можна задати.
- [Директиви](https://www.afterpack.dev/uk/docs/directives): повна граматика маркерів.
- [Пресети](https://www.afterpack.dev/uk/docs/presets): шкала, за якою визначається `preset`.
- [Збірки та CI](https://www.afterpack.dev/uk/docs/builds): сіди, dev проти prod, просування тих самих байтів.
- [Protection Map](https://www.afterpack.dev/uk/docs/protection-map): як читати звіт.
