Обфускація збірки esbuild

@afterpack/esbuild підключається до build.onEnd і обфускує виданий результат на місці.

@afterpack/esbuild є стандартним плагіном esbuild ({ name, setup(build) }). Він підключається до build.onEnd, який спрацьовує, щойно esbuild закінчив записувати результат на диск (write !== false, значення за замовчуванням).

Він підтримує обидві форми виводу: outdir (багато файлів) і outfile (один файл). Збірку, яка вже завершилася помилкою, він пропускає.

Встановлення

$ npm install -D @afterpack/esbuild
// build.mjs
import { build } from "esbuild";
import { afterpackEsbuild } from "@afterpack/esbuild";

await build({
  entryPoints: ["src/main.js"],
  bundle: true,
  format: "esm",
  outfile: "dist/app.js",
  plugins: [afterpackEsbuild()],
});

Іменований експорт: afterpackEsbuild.

Збірка

Плагін запускається на build.onEnd, після того як esbuild закінчив записувати результат на диск, однаково для outdir і outfile. Окремої dev-команди, яку він міг би пропускати, немає: кожен виклик build(), що записує файли, запускає плагін.

esbuild не надає хука всередині конвеєра, тож ваш необфускований бандл лежить на диску, доки прохід не завершиться, а для бандла на 185 KB на пресеті за замовчуванням це триває приблизно чверть секунди, і все, що може читати каталог виводу в цей проміжок, може його прочитати. Невдала обфускація залишає цей результат на місці: збірка завершується помилкою, тож у реліз нічого не потрапляє, але файли лишаються, доки наступна збірка їх не перезапише.

Перевірка

Protection Map за замовчуванням записується, коли esbuild видає source map і збірка не працює в CI (CI=true або CI=1); продакшн-режим її не вимикає. esbuild не видає source map, якщо ви не задали sourcemap, тож мапа за замовчуванням вимкнена. Запитайте її явно:

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

Вона записується в .afterpack/protectionMap.html, внесений у gitignore. Без sourcemap: true плагін попереджає, що не знайшов мапи бандлера, з якої можна відобразити оригінальний вихідний код. Звіт містить увесь ваш вихідний код. Ніколи не комітьте його і не роздавайте з сервера.

Параметри

Будь-який ключ конфігурації можна передати тут в об'єкті параметрів, наприклад afterpackEsbuild({ preset: "hard", complexity: 40 }).

Директиви

Директиви відновлюються із source map бандлера, тож якщо ви їх використовуєте, збирайте з sourcemap: true. Див. Директиви.

Особливі випадки

  • Зупинка з помилкою (fail closed). Невдалий файл або порожній результат відхиляє збірку.
  • write: false. На диску нічого немає, тож плагін нічого не робить. AfterPack потрібні записані файли.
  • TypeScript. На момент запуску AfterPack esbuild уже прибрав типи; мапи ведуть назад до рядків вашого .ts.

Далі