# Ofusca una app de Angular

En Angular v17+ la ofuscación es una pasada posterior al build sobre dist/<app>/browser: con la CLI o con el helper @afterpack/angular.

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

Angular moderno (v17+) compila con `@angular-devkit/build-angular:application`. Ese builder se basa en esbuild pero no expone ningún hook para plugins, así que, a diferencia de los plugins de [Vite](https://www.afterpack.dev/es/docs/frameworks/vite), [webpack](https://www.afterpack.dev/es/docs/frameworks/webpack) y [esbuild](https://www.afterpack.dev/es/docs/frameworks/esbuild), aquí AfterPack no puede engancharse al build.

La integración es una pasada posterior al build sobre el bundle de navegador emitido. `@afterpack/angular` es un envoltorio de conveniencia sobre esa pasada. No es un plugin del builder.

## Instalación

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

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

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

O ejecuta directamente [la CLI](https://www.afterpack.dev/es/docs/cli), sin instalar nada.

## Build

El builder de aplicación escribe el bundle de cliente en `dist/<app>/browser`.

Con el helper, `findAngularBrowserDir(distRoot)` encuentra la salida de navegador. En un monorepo, pasa `browserDir`. `findAngularBrowserDir` también se exporta por separado si solo quieres el localizador.

Con la CLI, apúntala directamente a la salida de navegador:

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

[Apunta la CLI a ella](https://www.afterpack.dev/es/docs/cli#usage) y cada chunk `.js` emitido se ofusca en el sitio. La [copia de seguridad](https://www.afterpack.dev/es/docs/config#build-backup) de la CLI va a `.afterpack/backups/` en la raíz del proyecto, fuera de `dist/`, así que no se publica con el despliegue; `npx afterpack@latest restore` deshace la ejecución. El caso al que hay que prestar atención es el helper `@afterpack/angular`: ahí, `build: { backup: true }` escribe un archivo hermano `.backup.<hash>` dentro de `dist/`, es decir, tu código fuente original dentro del árbol que despliegas.

El helper también renombra cada archivo con hash de contenido para que su nombre [siga a sus bytes ofuscados](https://www.afterpack.dev/es/docs/builds#file-names-and-caching), y recalcula los hashes que Angular escribió para los archivos sin ofuscar: los atributos `integrity` de la opción `subresourceIntegrity` y la tabla de hashes `ngsw.json` del service worker. La [CLI](https://www.afterpack.dev/es/docs/cli#content-hashed-file-names) hace ambas cosas cuando la apuntas a `dist/<app>/browser/`. Un build SSR cuyo `angular-app-manifest.mjs` incluye hashes de assets hace fallar la pasada, y la CLI también lo rechaza.

El builder escribe el bundle antes de que pueda ejecutarse la pasada, así que tu bundle sin ofuscar está en disco hasta que la pasada termina, y cualquier cosa que pueda leer `dist/` en ese intervalo puede leerlo. Una pasada fallida deja esa salida en su sitio: el build falla, así que no se publica nada, pero los archivos permanecen hasta que el siguiente build los sobrescribe.

[Falla de forma segura (fail closed)](https://www.afterpack.dev/es/docs/diagnostics#fail-closed-no-exceptions): `afterpackAngular` lanza un error si el directorio de navegador no contiene ningún `.js`/`.mjs`/`.cjs`, o si el motor informa de un [diagnóstico](https://www.afterpack.dev/es/docs/diagnostics) de fallo.

## Verificación

Activa en `angular.json` la opción de build `sourceMap` del propio Angular para el build que quieras inspeccionar, de modo que el [Protection Map](https://www.afterpack.dev/es/docs/protection-map) pueda mostrar tu código fuente original. Se escribe en `.afterpack/protectionMap.html`, ignorado por git. Contiene todo tu código fuente. Nunca lo subas al repositorio ni lo sirvas.

Tanto la CLI como el helper escriben el Protection Map por defecto solo cuando existen source maps y el build no se ejecuta en CI (`CI=true` o `CI=1`); el modo de [producción](https://www.afterpack.dev/es/docs/config#build-mode) no lo desactiva. `ng build` no emite source maps en su configuración de producción, así que ahí el mapa está desactivado por defecto. `protectionMap: { enabled: true }` fuerza su activación.

> **Nunca publiques source maps en tu CDN**
>
> Un source map de producción da acceso a tu código fuente original. Genéralo para el build y después déjalo fuera del `dist/` que despliegas.

## Opciones

Cualquier [clave de configuración](https://www.afterpack.dev/es/docs/config) se puede pasar aquí en el objeto de opciones, por ejemplo `afterpackAngular({ preset: "hard", complexity: 40 })`. Estas opciones solo existen en este paquete, para localizar la salida del build:

| Opción | Tipo | Por defecto |
|---|---|---|
| `cwd` | `string` | `process.cwd()`; la raíz del proyecto, desde donde empiezan la búsqueda de `afterpack.json` y `distRoot` |
| `distRoot` | `string` | `<cwd>/dist`; dónde buscar el subdirectorio `browser` |
| `browserDir` | `string` | sin establecer. Omite por completo la localización automática |

Aquí no existe la opción `build.autorun`.

## Directivas

`directives.enabled` se **rechaza aquí, en todas las capas**: el objeto de opciones, `AFTERPACK_directives_enabled` y
`afterpack.json` por igual. El builder de aplicación de Angular está sellado, así que esta pasada solo
ve salida ya minificada y no tiene ningún hook desde el que capturar los comentarios `/* @afterpack ... */`.
Establecerla hace fallar el build en lugar de ignorarse en silencio. Las
[`regions`](https://www.afterpack.dev/es/docs/config#regions) escritas a mano siguen funcionando, porque nombran rangos de bytes en lugar de comentarios.

## Casos límite

**Angular antiguo (webpack).** Los proyectos que siguen con el antiguo builder basado en webpack pueden ofuscar dentro del build con [`@afterpack/webpack`](https://www.afterpack.dev/es/docs/frameworks/webpack) mediante un builder personalizado. La vía posterior al build descrita arriba funciona igual con ambos builders y es la recomendada.

## Siguiente

- [Frameworks](https://www.afterpack.dev/es/docs/frameworks): la matriz completa.
- [Referencia de la CLI](https://www.afterpack.dev/es/docs/cli): los flags usados arriba.
- [Build y CI](https://www.afterpack.dev/es/docs/builds): semillas, desarrollo frente a producción, promocionar los mismos bytes.
- [Protection Map](https://www.afterpack.dev/es/docs/protection-map): cómo leer el informe.
- [Configuración](https://www.afterpack.dev/es/docs/config): la superficie de configuración del motor.
- [Diagnósticos](https://www.afterpack.dev/es/docs/diagnostics#exit-codes): qué devuelve una pasada fallida.
