# Ofusca un build de Next.js

@afterpack/next ofusca el JavaScript de cliente dentro de next build, con Turbopack o webpack, en SSR o en exportación estática.

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

`@afterpack/next` ofusca tu JavaScript de cliente desde dentro de `next build`. `withAfterpack` devuelve una configuración que lleva `compiler.runAfterProductionCompile`, el hook de build propio de Next, que Next llama una sola vez con cualquiera de los dos bundlers.

Envolver tu configuración es toda la integración. No hay script de ciclo de vida ni comando aparte.

## Instalación

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

```ts
// next.config.ts
import type { NextConfig } from "next";
import { withAfterpack } from "@afterpack/next";

const nextConfig: NextConfig = {
  // your existing config
};

export default withAfterpack(nextConfig);
```

La forma de función de una configuración de Next funciona igual. `withAfterpack(async (phase, ctx) => ({ … }))` devuelve una función envuelta.

## Build

`next build` emite ahora salida ofuscada, sea cual sea el bundler que produjo `.next/` (Turbopack o webpack). `next dev` no se toca. Cada invocación de `next build` ejecuta el hook, incluido un job de CI que lo llama directamente, y no hay ningún script de ciclo de vida que una instalación pueda omitir. Si el hook lanza una excepción, el build falla con código de salida 1.

El hook ofusca solo el JavaScript que se sirve al cliente: `.next/static/chunks`, más `out/` en una exportación estática. `.next/server` nunca llega a un navegador y no se ofusca. El hook renombra cada chunk 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 reescribe las referencias a él. El hook se ejecuta después de la compilación y antes del prerenderizado y de la exportación estática, así que una exportación estática copia chunks ofuscados en `out/`.

Next escribe los chunks antes de que se ejecute el hook, así que tus chunks sin ofuscar quedan en disco durante aproximadamente un segundo del build, y cualquier cosa que pueda leer `.next/` en ese intervalo puede leerlos. Los plugins integrados en el pipeline ([Vite](https://www.afterpack.dev/es/docs/frameworks/vite), [Rollup](https://www.afterpack.dev/es/docs/frameworks/rollup), [webpack](https://www.afterpack.dev/es/docs/frameworks/webpack), [Parcel](https://www.afterpack.dev/es/docs/frameworks/parcel)) devuelven en cambio el bundle ofuscado al bundler, de modo que nunca se escribe nada sin ofuscar.

Un hook `compiler.runAfterProductionCompile` que ya tengas configurado se compone en lugar de reemplazarse. El tuyo se ejecuta primero y el de AfterPack después, así que el tuyo ve los mismos bytes que vería sin AfterPack instalado.

El hook captura las opciones que pasas a `withAfterpack`. Tienen prioridad sobre las variables de entorno `AFTERPACK_*`, que a su vez tienen prioridad sobre `afterpack.json`. Usa [`paths.exclude`](https://www.afterpack.dev/es/docs/config#paths-exclude) para dejar un archivo sin tocar.

Cuando el mapa está activado, el [`protectionMap.html`](https://www.afterpack.dev/es/docs/protection-map) combinado se escribe en `.afterpack/`, ignorado por git, en la raíz de tu proyecto. Está desactivado por defecto; consulta [Verificación](#verify).

## Verificación

Cada build protegido escribe un recibo en `.afterpack/receipts/.next.json`, en la [raíz de tu proyecto](https://www.afterpack.dev/es/docs/cli#files), fuera de `.next/`: la versión del motor, la semilla, el bundler, el id del build y un sha256 por cada archivo ofuscado. Compruébalo en tu paso de despliegue:

```bash
npx afterpack@latest verify .
```

Sale con un código distinto de cero cuando falta el recibo, cuando pertenece a otro build o cuando algún archivo registrado ya no tiene el hash con el que se ofuscó.

El `out/` de una exportación estática es una copia de estos chunks, así que `npx afterpack@latest verify out` lo comprueba contra el mismo recibo y nombra cualquier archivo que haya cambiado.

El [Protection Map](https://www.afterpack.dev/es/docs/protection-map) se escribe por defecto solo cuando el bundler emitió un source map y el build no se ejecuta en CI (`CI=true` o `CI=1`). Next.js no emite source maps para el navegador a menos que `productionBrowserSourceMaps` esté activado, así que el mapa está desactivado por defecto. Actívalo de forma explícita para ver los artefactos completos en local:

```ts
export default withAfterpack(nextConfig, { protectionMap: { enabled: true } });
```

El informe se guarda en `.afterpack/protectionMap.html`, ignorado por git. Contiene todo tu código fuente. Nunca lo subas al repositorio ni lo sirvas.

> **Nunca publiques source maps en producción**
>
> Un archivo `.map` contiene tu código fuente original. Establece `productionBrowserSourceMaps: true` solo cuando quieras que el Protection Map muestre el código fuente original. El hook elimina los maps del árbol servido y mantiene desactivado el comentario `//# sourceMappingURL` en producción.

## Opciones

Cualquier [clave de configuración](https://www.afterpack.dev/es/docs/config) puede pasarse como segundo argumento de `withAfterpack`, por ejemplo `withAfterpack(nextConfig, { preset: "hard", complexity: 40 })`.

## Directivas

Las directivas son una función [Pro](https://www.afterpack.dev/es/docs/pro). En un [build Free](https://www.afterpack.dev/es/docs/directives#free-builds), una directiva que aumenta la protección detiene el build con `DIAG_PRO_DIRECTIVE_REQUIRES_KEY`.

El plugin lee las directivas de tu código fuente, y necesitan `productionBrowserSourceMaps: true` para localizarse en los chunks compilados. Consulta [Directivas](https://www.afterpack.dev/es/docs/directives).

## Casos límite

- **`experimental.sri` se rechaza.** Next calcula el hash de integridad de cada recurso mientras lo escribe, antes de que pueda ejecutarse ningún hook de build, así que el navegador bloquea un chunk reescrito después. Elimina `experimental.sri` o elimina `withAfterpack`.
- **Un `generateBuildId` fijo mantiene archivos modificados en una misma URL.** Con un id de build que no cambia entre releases, `static/<buildId>/_buildManifest.js` y `_ssgManifest.js` conservan su URL mientras sus bytes cambian, y el build avisa. Deja `generateBuildId` sin definir para que Next genere un id aleatorio en cada build, o devuelve un id nuevo en cada release.
- **Apunta a `.next/`, no a `dist/`.** Si usas [la CLI genérica](https://www.afterpack.dev/es/docs/cli#usage) en lugar de este paquete, `npx afterpack@latest .next/static/chunks` es el destino equivalente, pero no elimina por ti los maps servidos.
- **[Falla de forma segura (fail closed)](https://www.afterpack.dev/es/docs/diagnostics#fail-closed-no-exceptions) ante archivos sin ofuscar, sin posibilidad de anularlo.** Si el motor no puede ofuscar un archivo de forma segura, el build falla e indica de qué archivo se trata. Excluye el archivo del proceso por completo con [`paths.exclude`](https://www.afterpack.dev/es/docs/config#paths-exclude) si nunca debe ofuscarse.

## Siguiente

- [Frameworks](https://www.afterpack.dev/es/docs/frameworks): la matriz completa.
- [Inicio rápido](https://www.afterpack.dev/es/docs/quickstart): instalar, compilar y verificar.
- [Builds y CI](https://www.afterpack.dev/es/docs/builds): semillas, desarrollo frente a producción y promocionar los mismos bytes.
- [Protection Map](https://www.afterpack.dev/es/docs/protection-map): cómo leer el informe.
- [Directivas](https://www.afterpack.dev/es/docs/directives): cada clave de marcador y lo que hace.
- [Configuración](https://www.afterpack.dev/es/docs/config): la superficie de configuración del motor.
