Aggressive minification tools.
THIS LIBRARY IS HIGHLY EXPERIMENTAL. USE AT YOUR OWN RISK.
$ npm install packelyze -D
packelyze
generatesmangle.properties.reserved
for terser by analyzing yourlib/index.d.ts
(or other entrypoint)- High compression ratio with
mangle.properties.reserved=/^.*/
andmangle.properties.builtins=true
- But you should declare your project's internal side effects like
fetch(...)
,postMessage(...)
- you can use with
zero-runtime
(WIP) to catch side-effects.
- you can use with
- Library developper to reduce bundle
- Performance-oriented frontend (for lighthouse today?)
- Developers who are required to reduce build size (third party script developper)
TBD
$ npx packelyze init # optional: generate for lib/index.d.ts
$ npx tsc -p tsconfig.packelyze.json # generate lib/index.d.ts from src/index.ts
$ npx packelyze analyze-dts # generate _packelyze-analyzed.json
You can use analyzed result by adding analyze
step before build
in package.json
.
"scripts": {
"analyze": "tsc -p tsconfig.packelyze.json && packelyze analyze-dts",
"build": "npm run analyze && <your build commnad>"
},
You can skip packelyze init
if you know packelyze analyze-dts
requirements blow.
requirements
packelyze.config.json
is options forpackelyze analyze-dts
- You can skip config file with cli options: example
packelyze analyze-dts -i lib/index.d.ts -o _analyzed.json -b es -b dom -e react/jsx-runtime
- You can skip config file with cli options: example
packelyze analyze-dts
analyzeslib/index.d.ts
to generate_packelyze-analyzed.json
- If you already genarete
lib/index.d.ts
, you can omittsconfig.packelyze.json
.
- If you already genarete
{
// analyzer entrypoint
"input": "lib/_eff.d.ts",
// analyzed output
"output": "_packelyze-analyzed.json",
// predefined builtin reserved for environment
"builtins": [
// ECMAScript default features
"es",
// DOM enviroment
"dom",
// Worker environment
"worker",
// terser's internal reserved dictionary. equivalent to es, dom, worker
"domprops",
// well known http headers to keep request headers
"httpHeaders",
// node standard modules
"node",
// react's JSX interfaces
"react",
// cloudflare-workers
"cloudflareWorkers"
],
// (Optional) emit _bundle.d.ts of entrypoint
"writeDts": "_bundled.d.ts"
}
import { minify } from "terser";
import analyzed from "./_packelyze-analyzed.json";
const out = await minify({
mangle: {
properties: {
// genarted reserved includes builtins
bultins: true,
// keep reserved properties
reserved: analyzed.reserved,
// minify everything except reserved!
regex: /.*/,
}
}
});
// use result
console.log(out.code.length);
You can notify reserved interfaces by export
from entrypoint.
// src/_eff.ts or src/index.ts
export type ___MyReservedDictionary = {
foo: any,
bar: any
}
It's a simple way to reserve foo
and bar
.
// src/types.ts
export type SendPayload = {keepMe: number};
// usage in src/*
const payload: SendPayload = {
keepMe: 1
};
fetch("/send", {
method: "POST",
body: JSON.stringify(payload)
});
// src/_eff.ts or src/index.d.ts to notify type interfaces to packelyze.
export * from "./types";
keepMe
will be reserved.
Native side-effects are fetch()
, postMessage()
and others.
Your code.
// MyGlobalVar is declared outside.
console.log(MyGlobalVar.xxxx);
You should declare types in src/*.d.ts
declare const MyGlobalVar: {
xxxx: number;
yyyy: number;
}
MyGlobalVar
, xxxx
, yyyy
will be resereved to touch.
import { foo } from "mylib"; // external on bundle
// You should keep xxx
foo(/* external */, { xxx: 1 })
- CI
- Benchmark
- cli: builtins deno
- cli: external
- cli: Keep
function.name
andclass.name
option - cli:
Eff<*>
aggregator - linter: check scope
- minifier: poc
MIT