Ofusca un build de Vite

@afterpack/vite ofusca tu build en generateBundle, antes de que Vite lo escriba. Es la integración de referencia que envuelven todos los demás paquetes de la familia Vite.

@afterpack/vite es la integración de referencia. Astro, Svelte, SvelteKit, Vue y Nuxt la envuelven, así que lo que describe esta página también se aplica a esos paquetes.

Lee las directivas @afterpack de tu código fuente y después ejecuta el motor en generateBundle, con el bundle terminado en memoria y antes de que Vite escriba nada.

Instalación

$ npm install -D @afterpack/vite
// vite.config.ts
import { defineConfig } from "vite";
import { afterpackVite } from "@afterpack/vite";

export default defineConfig({
  plugins: [afterpackVite()],
});

Build

Esa es toda la configuración. npm run build ahora emite salida ofuscada; vite dev no se toca, porque el plugin solo actúa en el generateBundle de un build. Vite escribe los chunks ofuscados y nunca los originales, y una ofuscación fallida deja outDir como estaba.

Lo que ofusca es lo que Vite compiló: cada chunk del bundle de salida. Los archivos que Vite copia tal cual desde publicDir al directorio de salida no se compilan, no están en el bundle y no se tocan. Haz pasar por el bundler todo lo que necesite protección.

El plugin escribe:

  • protectionMap.html: un único mapa combinado para el build, que siempre se escribe en .afterpack/, ignorado por git, en la raíz de tu proyecto. Incrusta tu código fuente original. Nunca dejes que acabe en un directorio servido.
  • foo.js.map: el source map, cuando los mapas están activados. Cuando están desactivados, que es el valor por defecto en producción, la entrada de mapa del propio Vite se descarta en lugar de escribirse junto al chunk ofuscado.

Aquí no hay foo.backup.<hash>.js. Los bytes ofuscados vuelven al bundle, así que no existe ningún archivo emitido junto al que colocar una copia de seguridad, y build.backup: true emite un aviso en lugar de escribirla.

.afterpack/ lleva su propio .gitignore, así que el plugin nunca edita el tuyo. Avisa si un artefacto acaba bajo una ruta servida.

Verificación

El Protection Map se escribe por defecto cuando Vite emite un source map y el build no se ejecuta en CI (CI=true o CI=1); un build de producción no lo desactiva. Vite no emite ningún source map a menos que se configure build.sourcemap, así que en un build normal el mapa está desactivado por defecto. Pídelo explícitamente cuando quieras inspeccionar uno:

afterpackVite({ protectionMap: { enabled: true } });

Con build.sourcemap sin establecer, esto también activa los source maps del propio Vite, para que el mapa pueda mostrar tu código fuente original. Sin un mapa localizable, el plugin no tiene de dónde mostrar el código fuente original y lo indica.

El informe se escribe en .afterpack/protectionMap.html. Contiene todo tu código fuente. Nunca lo confirmes en git ni lo sirvas, y revísalo solo en local.

entitlements.jslight · complexity 5Open full size
entitlements.js, 54 lines, built at the light preset with a directive around the signature check. Click any token to see what was applied to it.
Nunca publiques source maps en producción

Un archivo .map lleva hasta tu código fuente original. Nunca despliegues uno.

Opciones

Cualquier clave de configuración puede pasarse aquí en el objeto de opciones, por ejemplo afterpackVite({ preset: "hard", complexity: 40 }). Todas son opcionales. La exportación con nombre es afterpackVite.

preset y complexity establecen cosas distintas. Un preset es un conjunto: establece a la vez el objetivo de complejidad, el multiplicador total de salida y el presupuesto de inflación. complexity es un solo número dentro de ese conjunto:

afterpackVite({ preset: "hard", complexity: 40 }); // hard's size limits, target 40

Directivas

El plugin lee las directivas de tu código fuente, antes de que cualquier minificador elimine los comentarios. La gramática admite solo comentarios de bloque:

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

Los comentarios de línea // @afterpack … no se analizan y se notifican como diagnósticos.

Todas las claves que puede establecer una directiva están en la página de Directivas.

La captura omite node_modules y los archivos que no son JS/TS. Una directiva dentro de un componente de archivo único .vue o .svelte no se captura. Ponla en un módulo .ts/.js normal que importe el componente. Establece directives.enabled: false para omitir el análisis por completo.

Casos límite

Modo librería

La salida de build.lib es un contrato público. AfterPack se ejecuta sobre el bundle terminado, así que los nombres exportados se conservan; los internos se siguen renombrando y reestructurando.

Varias salidas

Cada build de Vite ofusca su propio bundle y nada más, así que builds separados son pasadas separadas aunque escriban en un mismo directorio. Fija la misma seed en todos ellos si comparten un contrato en tiempo de ejecución.

Siguiente