# Обфускація застосунку Angular

Обфускація Angular v17+ — це прохід після збірки по dist/<app>/browser: через CLI або через допоміжний пакет @afterpack/angular.

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

Сучасний Angular (v17+) збирається через `@angular-devkit/build-angular:application`. Цей білдер побудований на esbuild, але не надає жодного хука для плагінів, тож, на відміну від плагінів для [Vite](https://www.afterpack.dev/uk/docs/frameworks/vite), [webpack](https://www.afterpack.dev/uk/docs/frameworks/webpack) і [esbuild](https://www.afterpack.dev/uk/docs/frameworks/esbuild), AfterPack не може під'єднатися до збірки.

Інтеграція — це прохід після збірки по згенерованому браузерному бандлу. `@afterpack/angular` — зручна обгортка над цим проходом. Це не плагін білдера.

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

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

```js
// scripts/obfuscate.mjs — run after `ng build`
import { afterpackAngular } from "@afterpack/angular";

await afterpackAngular({ seed: "git" });
```

Або запустіть [CLI](https://www.afterpack.dev/uk/docs/cli) напряму, нічого не встановлюючи.

## Збірка

Білдер застосунку записує клієнтський бандл у `dist/<app>/browser`.

З допоміжним пакетом браузерний результат знаходить `findAngularBrowserDir(distRoot)`. У монорепозиторії передайте `browserDir`. `findAngularBrowserDir` також експортується окремо, якщо вам потрібен лише пошук каталогу.

З CLI вкажіть йому браузерний результат напряму:

```jsonc
// package.json
{
  "scripts": {
    "build": "ng build && afterpack dist/my-app/browser --seed=git"
  }
}
```

[Вкажіть на нього CLI](https://www.afterpack.dev/uk/docs/cli#usage), і кожен згенерований чанк `.js` буде обфусковано на місці. [Резервна копія](https://www.afterpack.dev/uk/docs/config#build-backup) CLI потрапляє в `.afterpack/backups/` у корені проєкту, поза `dist/`, тож вона не потрапляє в розгортання; `npx afterpack@latest restore` скасовує запуск. Увагу варто звернути на допоміжний пакет `@afterpack/angular`: `build: { backup: true }` у ньому записує поруч файл `.backup.<hash>` у `dist/`, а це ваш оригінальний вихідний код усередині дерева, яке ви розгортаєте.

Допоміжний пакет також перейменовує кожен файл з хешем вмісту, щоб його ім'я [слідувало за обфускованими байтами](https://www.afterpack.dev/uk/docs/builds#file-names-and-caching), і заново обчислює хеші, які Angular записав для необфускованих файлів: атрибути `integrity` від опції `subresourceIntegrity` і таблицю хешів `ngsw.json` сервіс-воркера. [CLI](https://www.afterpack.dev/uk/docs/cli#content-hashed-file-names) робить і те, і інше, коли ви спрямовуєте його на `dist/<app>/browser/`. SSR-збірка, чий `angular-app-manifest.mjs` містить хеші ассетів, завершує прохід помилкою, і CLI її теж відхиляє.

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

[Зупинка з помилкою (fail closed)](https://www.afterpack.dev/uk/docs/diagnostics#fail-closed-no-exceptions): `afterpackAngular` кидає виняток, якщо в браузерному каталозі немає жодного `.js`/`.mjs`/`.cjs` або якщо рушій повідомляє про [діагностику](https://www.afterpack.dev/uk/docs/diagnostics) з помилкою.

## Перевірка

Увімкніть власний параметр збірки Angular `sourceMap` в `angular.json` для збірки, яку хочете дослідити, щоб [Protection Map](https://www.afterpack.dev/uk/docs/protection-map) могла показати ваш оригінальний вихідний код. Вона записується у `.afterpack/protectionMap.html`, внесений у gitignore. Вона містить увесь ваш вихідний код. Ніколи не комітьте її і не роздавайте з сервера.

І CLI, і допоміжний пакет за замовчуванням записують Protection Map лише тоді, коли source map існують і збірка не працює в CI (`CI=true` або `CI=1`); [продакшн-режим](https://www.afterpack.dev/uk/docs/config#build-mode) її не вимикає. `ng build` у своїй продакшн-конфігурації не видає source map, тож там мапа за замовчуванням вимкнена. `protectionMap: { enabled: true }` примусово її вмикає.

> **Ніколи не викладайте source map на CDN**
>
> Продакшн-source map веде до вашого оригінального вихідного коду. Генеруйте його для збірки, а потім не допускайте в розгорнутий `dist/`.

## Параметри

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

| Параметр | Тип | За замовчуванням |
|---|---|---|
| `cwd` | `string` | `process.cwd()`; корінь проєкту, звідки починаються пошук `afterpack.json` і `distRoot` |
| `distRoot` | `string` | `<cwd>/dist`; де шукати підкаталог `browser` |
| `browserDir` | `string` | не задано. Повністю вимикає автоматичний пошук |

Параметра `build.autorun` тут немає.

## Директиви

`directives.enabled` **тут відхиляється на кожному рівні** — в об'єкті параметрів, в `AFTERPACK_directives_enabled` і в
`afterpack.json` однаково. Білдер застосунку Angular закритий, тож цей прохід завжди бачить лише
вже мініфікований результат і не має хука, щоб зібрати коментарі `/* @afterpack ... */`. Якщо задати
цей параметр, збірка завершиться помилкою, а не проігнорує його мовчки. Написані вручну
[`regions`](https://www.afterpack.dev/uk/docs/config#regions) усе одно працюють, бо вони задають діапазони байтів, а не коментарі.

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

**Старий Angular (webpack).** Проєкти, які досі використовують старіший білдер на основі webpack, можуть обфускувати під час збірки за допомогою [`@afterpack/webpack`](https://www.afterpack.dev/uk/docs/frameworks/webpack) через кастомний білдер. Описаний вище шлях після збірки працює однаково з обома білдерами, і саме його ми рекомендуємо.

## Далі

- [Фреймворки](https://www.afterpack.dev/uk/docs/frameworks): повна матриця.
- [Довідник CLI](https://www.afterpack.dev/uk/docs/cli): прапорці, використані вище.
- [Збірки та CI](https://www.afterpack.dev/uk/docs/builds): сіди, dev проти prod, просування тих самих байтів.
- [Protection Map](https://www.afterpack.dev/uk/docs/protection-map): як читати звіт.
- [Конфігурація](https://www.afterpack.dev/uk/docs/config): поверхня конфігурації рушія.
- [Діагностика](https://www.afterpack.dev/uk/docs/diagnostics#exit-codes): що повертає невдалий прохід.
