Obfuscate a Remix app

There is no @afterpack/remix package. Remix builds through Vite, so use @afterpack/vite, or run the CLI on the build output.

No Remix-specific package

AfterPack does not publish @afterpack/remix. Remix v2 and React Router v7 build through Vite, so the Vite plugin is the natural wiring, and the CLI works on the output regardless. Frameworks has the full matrix.

Install

Remix's own plugin runs inside your vite.config.ts, so @afterpack/vite goes in the same plugins array, after it:

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

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

Or skip the package and run the CLI on the build output instead.

Build

The plugin runs on generateBundle, obfuscating every JavaScript chunk in the bundle before Vite writes it. Remix builds the client and server legs as separate Vite builds, so the plugin runs once per leg, on that leg's bundle only. Pin one seed (seed: "git" is the simplest) if the two legs ship together and you want them built from the same seed. Builds & CI covers the trade.

Building with the CLI works the same way: build first, then point AfterPack at each output directory. A Remix Vite build typically writes build/client and build/server:

$ npx afterpack@latest build/client --seed=git

The path argument is required; there is no auto-detection. It takes a directory to walk, or a single .js/.mjs/.cjs file. Run it once per directory you want obfuscated, with the same --seed across both when they ship together. Both paths call the same shared pass, so everything else (the preset ladder, the fail-closed behavior, the artifacts) is identical.

Verify

Build mode turns the Protection Map off by default under NODE_ENV=production or CI=true. Build with source maps on for the build you want to inspect, then open the gitignored .afterpack/protectionMap.html. It contains your full source. Never commit it or serve it.

Options

Every configuration key works the same way through this plugin as on the Vite page, including directive capture; see Configuration for every key.

Directives

Directives are read from your source by the plugin. The CLI reads them when its input carries a source map. See Directives.

Edge cases

  • Fail-closed, with no override. An error/critical diagnostic, an empty result, or a file the engine could not obfuscate fails the build.
  • Server output is just JavaScript. AfterPack obfuscates whatever .js it finds in the directory you point it at.

Next