@keak/shrink
v0.1.0
Published
Domain-specific JS minifier for A/B testing pixels. Combines Keak-aware AST transforms with best-in-class general minification.
Maintainers
Readme
@keak/shrink
Domain-specific JavaScript minifier for Keak A/B testing pixels. Combines Keak-aware AST transforms with Terser for the smallest possible output.
Install
npm install @keak/shrinkQuick Start
CLI
# Shrink a pixel script
keak-shrink pixel.js -o pixel.min.js
# Pipe from stdin
cat pixel.js | keak-shrink > pixel.min.js
# Analyze optimization opportunities without modifying
keak-shrink pixel.js --analyze
# Benchmark against Terser
keak-shrink pixel.js --benchmarkProgrammatic
import { shrink, analyze } from "@keak/shrink";
// Shrink with all optimizations (default)
const result = await shrink(source);
console.log(result.stats);
// { original: 98000, minified: 31000, gzipped: 11200, brotli: 9800,
// savingsPercent: 68.4, savingsPercentGzip: 42.1 }
// Analyze without modifying
const report = analyze(source);
console.log(report.estimatedSavingsPercent); // 68.4How It Works
keak-shrink runs a two-layer pipeline:
- Layer 1 — Keak-specific AST transforms that remove dead code, deduplicate modules, and compress embedded data unique to Keak pixel scripts
- Layer 2 — Terser minification with aggressive settings (3 passes, dead code elimination, variable collapsing)
This two-layer approach achieves significantly better compression than Terser alone because it eliminates Keak-specific dead weight before general minification.
Transform Pipeline
Transforms run in order. Each targets a specific optimization:
| Transform | What it does | Typical savings |
|---|---|---|
| Legacy Strip | Removes the entire legacy script bundle (shouldRunLegacyScript() always returns false in embedded mode) | 15–20 KB |
| Debug Strip | Removes console.*, debugLog, debugWarn, isDebugMode() blocks, window.KeakDebug | 0.5–1 KB |
| Conditional DCE | Domain-aware dead code elimination — removes unused features (Shopify, split tests, video, desktop sync, WebMCP) | 0–5 KB |
| Syntax Repair | Fixes orphaned else blocks, empty if statements, and artifacts from prior transforms | — |
| Module Dedup | Detects duplicated function bodies across modules via AST hashing and hoists them | 1–3 KB |
| Data Compression | Shortens KEAK_EMBEDDED_DATA keys, strips defaults, deduplicates signatures, injects runtime decoder | 50–70% of data payload |
| Analytics Precompute | Hoists repeated static analytics field collection into a single IIFE | ~1 KB |
CLI Reference
keak-shrink [input] [options]If no input file is provided, reads from stdin.
Output
| Flag | Description |
|---|---|
| -o, --output <file> | Write output to file (default: stdout) |
| --json | Output stats/analysis as JSON |
Transform Toggles
All transforms are enabled by default. Disable individually:
| Flag | Description |
|---|---|
| --keep-legacy | Keep the legacy script bundle |
| --no-debug-strip | Keep debug/console statements |
| --no-dedup | Skip module deduplication |
| --no-data-compress | Skip embedded data compression |
| --no-terser | Skip Terser (output transforms only) |
Advanced
| Flag | Description |
|---|---|
| --config <file> | Domain config JSON for conditional DCE |
| --sourcemap | Generate source map |
| --target <target> | ES target (default: es2020) |
Analysis & Benchmarking
| Flag | Description |
|---|---|
| --analyze | Report optimization opportunities without modifying code |
| --benchmark | Compare output against Terser variants |
Programmatic API
shrink(source, options?): Promise<ShrinkResult>
Applies all transforms then Terser minification.
import { shrink } from "@keak/shrink";
const result = await shrink(source, {
excludeLegacyBundle: true, // default: true
stripDebug: true, // default: true
deduplicateModules: true, // default: true
compressEmbeddedData: true,// default: true
conditionalDCE: { // optional, auto-detected from KEAK_EMBEDDED_DATA
isShopify: false,
hasSplitTests: true,
hasVideoTests: false,
isDesktopProject: false,
hasWebMCP: false,
},
terserOptions: {}, // pass-through to Terser, or false to skip
sourcemap: false, // default: false
target: "es2020", // default: "es2020"
});
result.code; // minified source
result.map; // source map (if enabled)
result.stats; // { original, minified, gzipped, brotli, savingsPercent, savingsPercentGzip }
result.transforms; // [{ name, bytesRemoved, nodesAffected, description }]analyze(source, options?): AnalysisReport
Estimates optimization opportunities without modifying code.
import { analyze, formatReport } from "@keak/shrink";
const report = analyze(source);
console.log(formatReport(report));
// Prints a table of per-category removable bytes and estimated savingsIndividual Transforms
For advanced usage, each transform is exported individually:
import {
stripLegacyBundle,
stripDebug,
deduplicateModules,
compressEmbeddedData,
conditionalDCE,
precomputeAnalytics,
} from "@keak/shrink";Utilities
import {
formatBytes, // (bytes) => "12.3 KB"
measureSize, // (code) => { raw, gzip, brotli }
runBenchmark, // (source, keakOutput?) => BenchmarkResult[]
formatBenchmark, // (results) => formatted table string
formatReport, // (report) => formatted analysis table
} from "@keak/shrink";Conditional DCE Config
When using --config or the conditionalDCE option, provide a JSON file or object specifying which features the domain uses. Features set to false (or omitted) will have their code removed:
{
"isShopify": false,
"hasSplitTests": true,
"hasVideoTests": false,
"isDesktopProject": false,
"hasWebMCP": false
}| Feature | Code removed when false |
|---|---|
| isShopify | Shopify detection, postMessage, theme script loading |
| hasSplitTests | Split test logic, anti-flicker overlay, rage click tracking |
| hasVideoTests | Video element handling and replaceWithVideo |
| isDesktopProject | Desktop project sync and projectUuid handling |
| hasWebMCP | WebMCP tool registration and runtime |
If no config is provided, keak-shrink auto-detects from KEAK_EMBEDDED_DATA in the source.
License
MIT
