@afterpack/rollup mirrors @afterpack/vite: Rollup is what Vite builds on, so the same approach applies. It reads directives from your source, then runs the engine in generateBundle, with the finished bundle in memory and before Rollup writes any of it.
Install
$ npm install -D @afterpack/rollup// rollup.config.mjs
import { afterpackRollup } from "@afterpack/rollup";
export default {
input: "src/index.js",
output: { dir: "dist", format: "es", sourcemap: true },
plugins: [afterpackRollup()],
};The named export is afterpackRollup.
Build
The plugin runs in generateBundle, with order: "post", so it is the last hook to touch the bundle. It obfuscates every JavaScript chunk the bundle holds and hands them back, so Rollup writes the obfuscated chunks and never the originals. A failed obfuscation leaves the output directory as it was.
Verify
Ask for the Protection Map explicitly on a production build:
afterpackRollup({ protectionMap: { enabled: true } });It lands in the gitignored .afterpack/protectionMap.html. With output.sourcemap on it renders your original source; without one, there is nothing to render from and the pass says so. The report contains your full source. Never commit it or serve it.
entitlements.js, 54 lines, built at the medium preset with a directive around the signature check. Click any token to see what was applied to it.Options
Every configuration key can be passed here as the options object, for example afterpackRollup({ preset: "hard", complexity: 40 }).
Directives
Directives are read from your source by the plugin, before minification, so a directive survives bundling.
/* @afterpack preset=hard */
export function signRequest(payload) {
// ...
}
/* @afterpack end */Capture skips node_modules, virtual modules, and non-JS/TS files. The grammar is the same everywhere.
Edge cases
Multiple outputs
A config with two outputs runs generateBundle once per output, and each run only sees its own bundle. Nothing is obfuscated twice, whatever directories the outputs write to:
output: [
{ dir: "dist/esm", format: "es", entryFileNames: "lib.js" },
{ dir: "dist/cjs", format: "cjs", entryFileNames: "lib.cjs" },
],
plugins: [afterpackRollup({ seed: "git" })],Pin one seed across outputs that ship together.
Library builds
AfterPack runs on the bundle Rollup built, so every exported name your consumers import survives as written; only internals are renamed and restructured.
Next
- Frameworks: the full matrix.
- Vite: the same hooks, with Vite's config resolution.
- Builds & CI: seeds, dev-vs-prod, promoting the same bytes.
- Protection Map: reading the report.
- Directives: every marker key, and what it does.
- Configuration: the engine config surface.