Skip to content

Commit 34eca47

Browse files
committed
docs: translate bundler comparison from Polish to English
Translate comprehensive tsdown vs pkgroll comparison to English: - Main heading and executive summary - Automatic shebang handling section - Technology and performance comparison table - CLI configuration approaches - Library compatibility matrix - Bundle size and tree-shaking analysis - Standalone binaries preparation - Developer experience and debugging - Critical edge cases - Known issues and gotchas - Use case recommendations All technical content now in English for wider accessibility while maintaining the same depth and technical accuracy.
1 parent 482d53d commit 34eca47

File tree

1 file changed

+91
-91
lines changed

1 file changed

+91
-91
lines changed

README.md

Lines changed: 91 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -183,48 +183,48 @@ git commit -m "docs: update API documentation"
183183

184184
## 🎨 Bundler Configuration
185185

186-
# tsdown vs pkgroll: Który bundler wybrać do CLI w TypeScript?
186+
# tsdown vs pkgroll: Which bundler to choose for TypeScript CLI?
187187

188-
**pkgroll wygrywa dla narzędzi CLI** dzięki automatycznej obsłudze shebang i konfiguracji zero-config, podczas gdy tsdown oferuje szybsze buildy, ale wymaga ręcznych workaroundów dla plików wykonywalnych. Dla złożonego CLI z subkomendami i wieloma kanałami dystrybucji (npm, npx, bin, deno compile), pkgroll zapewnia mniej problemów out-of-the-box, ale tsdown może być lepszy przy intensywnym development workflow dzięki 2x szybszemu buildowi.
188+
**pkgroll wins for CLI tools** thanks to automatic shebang handling and zero-config setup, while tsdown offers faster builds but requires manual workarounds for executable files. For complex CLIs with subcommands and multiple distribution channels (npm, npx, bin, deno compile), pkgroll provides fewer out-of-the-box issues, but tsdown may be better for intensive development workflows thanks to 2x faster builds.
189189

190190
---
191191

192-
## Automatyczna obsługa shebang decyduje o wyborze
192+
## Automatic shebang handling makes the difference
193193

194-
Najważniejsza różnica między bundlerami dla CLI to sposób obsługi **hashbang** (`#!/usr/bin/env node`). pkgroll automatycznie dodaje shebang do wszystkich plików zdefiniowanych w `bin` field package.json, co eliminuje całą klasę problemów z wykonywalnością. tsdown, zaprojektowany jako "The Elegant Library Bundler", nie posiada natywnej obsługi shebang i wymaga workaroundu:
194+
The most important difference between bundlers for CLI is how they handle **hashbang** (`#!/usr/bin/env node`). pkgroll automatically adds shebang to all files defined in the `bin` field of package.json, which eliminates an entire class of executability problems. tsdown, designed as "The Elegant Library Bundler", doesn't have native shebang support and requires a workaround:
195195

196196
```typescript
197-
// tsdown.config.ts - wymagany workaround
197+
// tsdown.config.ts - required workaround
198198
export default defineConfig({
199199
entry: { cli: 'src/cli.ts' },
200200
outputOptions: {
201-
banner: '#!/usr/bin/env node\n', // Ręczna injekcja
201+
banner: '#!/usr/bin/env node\n', // Manual injection
202202
},
203203
})
204204
```
205205

206-
pkgroll miał historycznie kilka bugów z shebang (hashbang w złym miejscu przy ESM, brak na Windows, znikający przy obecności `main` key), ale **wszystkie zostały naprawione** do wersji 2.14.2 (lipiec 2025). Teraz system działa niezawodnie - wystarczy zdefiniować `bin` w package.json.
206+
pkgroll historically had several shebang bugs (hashbang in wrong place with ESM, missing on Windows, disappearing with `main` key present), but **all were fixed** by version 2.14.2 (July 2025). The system now works reliably - just define `bin` in package.json.
207207

208208
---
209209

210-
## Porównanie technologii i wydajności
210+
## Technology and performance comparison
211211

212-
| Aspekt | tsdown | pkgroll |
212+
| Aspect | tsdown | pkgroll |
213213
|--------|--------|---------|
214-
| **Silnik bundlera** | Rolldown (Rust) | Rollup (JavaScript) |
215-
| **Transformacje TS** | Oxc (Rust) | esbuild |
216-
| **Generacja .d.ts** | rolldown-plugin-dts | rollup-plugin-dts |
217-
| **Szybkość buildu** | ~2x szybszy niż tsup | Wolniejszy (JS-based) |
218-
| **Tree-shaking** | Rolldown-based | Rollup (najlepszy w klasie) |
219-
| **Minifikacja** | Oxc (alpha - może mieć bugi) | esbuild (stabilny) |
214+
| **Bundler engine** | Rolldown (Rust) | Rollup (JavaScript) |
215+
| **TS transformations** | Oxc (Rust) | esbuild |
216+
| **.d.ts generation** | rolldown-plugin-dts | rollup-plugin-dts |
217+
| **Build speed** | ~2x faster than tsup | Slower (JS-based) |
218+
| **Tree-shaking** | Rolldown-based | Rollup (best in class) |
219+
| **Minification** | Oxc (alpha - may have bugs) | esbuild (stable) |
220220

221-
tsdown jest **do 8x szybszy** przy generowaniu TypeScript declarations dzięki Rust-owemu backendowi. Przy częstym rebuildowaniu podczas developmentu ta różnica jest odczuwalna. Jednak pkgroll oferuje **najlepszy tree-shaking** w ekosystemie dzięki Rollup, co przekłada się na mniejsze bundle size dla finalnych buildów.
221+
tsdown is **up to 8x faster** at generating TypeScript declarations thanks to its Rust backend. When frequently rebuilding during development, this difference is noticeable. However, pkgroll offers **best-in-class tree-shaking** in the ecosystem thanks to Rollup, which translates to smaller bundle sizes for final builds.
222222

223223
---
224224

225-
## Konfiguracja dla złożonego CLI z subkomendami
225+
## Configuration for complex CLI with subcommands
226226

227-
### Podejście pkgroll (zero-config)
227+
### pkgroll approach (zero-config)
228228

229229
```json
230230
{
@@ -246,9 +246,9 @@ tsdown jest **do 8x szybszy** przy generowaniu TypeScript declarations dzięki R
246246
}
247247
```
248248

249-
pkgroll automatycznie wykrywa entry pointy z `bin` i `exports`, dodaje shebangi gdzie trzeba, i generuje odpowiednie formaty. **Nie ma pliku konfiguracyjnego** - package.json jest "single source of truth".
249+
pkgroll automatically detects entry points from `bin` and `exports`, adds shebangs where needed, and generates appropriate formats. **There's no config file** - package.json is the "single source of truth".
250250

251-
### Podejście tsdown (explicit config)
251+
### tsdown approach (explicit config)
252252

253253
```typescript
254254
// tsdown.config.ts
@@ -273,41 +273,41 @@ export default defineConfig({
273273
})
274274
```
275275

276-
tsdown oferuje większą kontrolę i migrację z tsup (`npx tsdown migrate`), ale wymaga więcej konfiguracji dla CLI.
276+
tsdown offers more control and migration from tsup (`npx tsdown migrate`), but requires more configuration for CLI.
277277

278278
---
279279

280-
## Kompatybilność z bibliotekami CLI
280+
## CLI library compatibility
281281

282-
Obie bundlery **externalizują dependencies** domyślnie (pakiety z `dependencies` vs `devDependencies`), co oznacza że większość bibliotek CLI nie jest bundlowana. Dla heavy dependencies jak inquirer, commander czy chalk to zalecane podejście:
282+
Both bundlers **externalize dependencies** by default (packages in `dependencies` vs `devDependencies`), meaning most CLI libraries aren't bundled. For heavy dependencies like inquirer, commander, or chalk, this is the recommended approach:
283283

284-
| Biblioteka | tsdown | pkgroll | Uwagi |
284+
| Library | tsdown | pkgroll | Notes |
285285
|------------|--------|---------|-------|
286-
| commander.js ||| Externalizuj |
287-
| yargs ||| Externalizuj |
288-
| cac ||| ESM-only, działa |
289-
| inquirer | ⚠️ | ⚠️ | Dynamic requires - externalizuj |
290-
| prompts ||| Externalizuj |
291-
| chalk v5+ ||| ESM-only, działa |
292-
| picocolors ||| Może bundlować (tiny) |
293-
| ora ||| ESM-only, externalizuj |
294-
| cosmiconfig | ⚠️ | ⚠️ | Dynamic requires - externalizuj |
295-
296-
**ESM-only packages** (chalk 5+, ora, cac) działają w obu bundlerach bez problemów. Pakiety używające **dynamic requires** (inquirer, cosmiconfig) lepiej trzymać jako external dependencies.
286+
| commander.js ||| Externalize |
287+
| yargs ||| Externalize |
288+
| cac ||| ESM-only, works |
289+
| inquirer | ⚠️ | ⚠️ | Dynamic requires - externalize |
290+
| prompts ||| Externalize |
291+
| chalk v5+ ||| ESM-only, works |
292+
| picocolors ||| Can bundle (tiny) |
293+
| ora ||| ESM-only, externalize |
294+
| cosmiconfig | ⚠️ | ⚠️ | Dynamic requires - externalize |
295+
296+
**ESM-only packages** (chalk 5+, ora, cac) work in both bundlers without issues. Packages using **dynamic requires** (inquirer, cosmiconfig) are better kept as external dependencies.
297297

298298
---
299299

300-
## Bundle size i tree-shaking dla CLI
300+
## Bundle size and tree-shaking for CLI
301301

302-
### Efektywność tree-shaking
302+
### Tree-shaking efficiency
303303

304-
pkgroll z Rollup oferuje **najlepszy tree-shaking** - szczególnie istotne dla CLI z wieloma subkomendami, gdzie użytkownik wywołuje tylko jedną na raz. Rollup lepiej eliminuje nieużywany kod między modułami.
304+
pkgroll with Rollup offers **best-in-class tree-shaking** - especially important for CLIs with many subcommands, where users invoke only one at a time. Rollup better eliminates unused code between modules.
305305

306-
tsdown z Rolldown ma tree-shaking **włączony domyślnie** (`--no-treeshake` wyłącza), ale może być mniej agresywny niż Rollup w edge cases.
306+
tsdown with Rolldown has tree-shaking **enabled by default** (`--no-treeshake` disables it), but may be less aggressive than Rollup in edge cases.
307307

308-
### Lazy loading subkomend
308+
### Lazy loading subcommands
309309

310-
Żaden bundler nie ma wbudowanego lazy loading, ale można go zaimplementować manualnie:
310+
Neither bundler has built-in lazy loading, but you can implement it manually:
311311

312312
```typescript
313313
// src/cli.ts
@@ -325,15 +325,15 @@ if (handler) {
325325
}
326326
```
327327

328-
Oba bundlery obsługują dynamic imports, więc ten pattern działa.
328+
Both bundlers support dynamic imports, so this pattern works.
329329

330330
---
331331

332-
## Przygotowanie do standalone binaries
332+
## Preparing for standalone binaries
333333

334334
### deno compile compatibility
335335

336-
Dla deno compile potrzebujesz bundla jako pojedynczy plik ESM:
336+
For deno compile you need a bundle as a single ESM file:
337337

338338
```bash
339339
# tsdown
@@ -343,54 +343,54 @@ tsdown src/cli.ts --format esm --minify
343343
pkgroll --minify
344344
```
345345

346-
Następnie:
346+
Then:
347347
```bash
348348
deno compile --output mycli --allow-read --allow-write ./dist/cli.js
349349
```
350350

351351
### bun build --compile
352352

353-
Bun ma własny system kompilacji standalone:
353+
Bun has its own standalone compilation system:
354354

355355
```bash
356356
bun build ./src/cli.ts --compile --outfile mycli
357357
```
358358

359-
Nie wymaga wcześniejszego bundlowania - Bun robi wszystko sam. Output zawiera runtime (~45-90MB).
359+
No prior bundling needed - Bun does everything itself. Output includes runtime (~45-90MB).
360360

361361
### pkg/nexe compatibility
362362

363-
Oba bundlery produkują standardowy Node.js JavaScript, więc output jest kompatybilny z pkg i nexe:
363+
Both bundlers produce standard Node.js JavaScript, so output is compatible with pkg and nexe:
364364

365365
```bash
366-
# Po zbundlowaniu
366+
# After bundling
367367
pkg ./dist/cli.js --targets node20-linux-x64,node20-win-x64,node20-macos-x64
368368
```
369369

370-
### vercel/ncc jako alternatywa
370+
### vercel/ncc as alternative
371371

372-
ncc to zero-config compiler od Vercel, który produkuje single-file output:
372+
ncc is a zero-config compiler from Vercel that produces single-file output:
373373

374374
```bash
375375
ncc build src/cli.ts -o dist
376376
```
377377

378-
Może być prostszy dla prostych CLI, ale ma problemy z dynamic requires.
378+
May be simpler for simple CLIs, but has issues with dynamic requires.
379379

380380
---
381381

382-
## Developer experience i debugging
382+
## Developer experience and debugging
383383

384384
### Watch mode
385385

386-
Oba bundlery mają watch mode:
386+
Both bundlers have watch mode:
387387

388388
```bash
389389
tsdown --watch
390390
pkgroll --watch
391391
```
392392

393-
tsdown jest **znacząco szybszy** przy rebuildach dzięki Rust backend.
393+
tsdown is **significantly faster** at rebuilds thanks to Rust backend.
394394

395395
### Source maps
396396

@@ -399,14 +399,14 @@ tsdown --sourcemap
399399
pkgroll --sourcemap
400400
```
401401

402-
Użycie przy runtime:
402+
Usage at runtime:
403403
```bash
404404
node --enable-source-maps ./dist/cli.js
405405
```
406406

407-
**Uwaga**: pkgroll ma udokumentowany bug (#84) z offsetem linii w sourcemaps, tsdown działa lepiej.
407+
**Note**: pkgroll has a documented bug (#84) with line offset in sourcemaps, tsdown works better.
408408

409-
### Debugging w VS Code
409+
### Debugging in VS Code
410410

411411
```json
412412
{
@@ -422,22 +422,22 @@ node --enable-source-maps ./dist/cli.js
422422

423423
---
424424

425-
## Edge cases krytyczne dla CLI
425+
## Critical edge cases for CLI
426426

427-
### __dirname i __filename w ESM
427+
### __dirname and __filename in ESM
428428

429-
tsdown z `shims: true` automatycznie dodaje:
429+
tsdown with `shims: true` automatically adds:
430430
```javascript
431431
import { fileURLToPath } from 'node:url'
432432
const __filename = fileURLToPath(import.meta.url)
433433
const __dirname = dirname(__filename)
434434
```
435435
436-
pkgroll automatycznie shimuje `import.meta.dirname` i `import.meta.filename` w CJS output.
436+
pkgroll automatically shims `import.meta.dirname` and `import.meta.filename` in CJS output.
437437
438438
### process.exit() handling
439439
440-
Oba bundlery mogą agresywnie tree-shake kod po `process.exit()`. Bezpieczny pattern:
440+
Both bundlers may aggressively tree-shake code after `process.exit()`. Safe pattern:
441441
442442
```typescript
443443
async function main() {
@@ -454,55 +454,55 @@ main()
454454
455455
### Native modules
456456
457-
pkgroll **automatycznie obsługuje** pliki `.node` - kopiuje do `dist/natives/` i przepisuje importy. tsdown nie ma udokumentowanej obsługi - lepiej externalizować pakiety z native modules.
457+
pkgroll **automatically handles** `.node` files - copies to `dist/natives/` and rewrites imports. tsdown has no documented support - better to externalize packages with native modules.
458458
459459
---
460460
461-
## Znane problemy i gotchas
461+
## Known issues and gotchas
462462
463463
### pkgroll (19 open issues)
464-
- CJS default exports nie są unwrapowane pod `default` property (#101)
464+
- CJS default exports aren't unwrapped under `default` property (#101)
465465
- Sourcemap offset bugs (#84)
466-
- Brak config file API - wszystko przez CLI (#98 - requested feature)
467-
- Brak programmatic API (#137)
466+
- No config file API - everything through CLI (#98 - requested feature)
467+
- No programmatic API (#137)
468468
469469
### tsdown (37 open issues)
470-
- CSS handling problematyczny (#627, #653)
470+
- CSS handling problematic (#627, #653)
471471
- Yarn PnP config loading fails (#639)
472-
- DTS issues z TypeScript path mappings w monorepo (#594, #523)
473-
- `__dirname` shim nie replikuje dokładnie `import.meta.dirname` (#572)
474-
- Minifikacja powoduje błędy z Express routes (#462)
472+
- DTS issues with TypeScript path mappings in monorepo (#594, #523)
473+
- `__dirname` shim doesn't exactly replicate `import.meta.dirname` (#572)
474+
- Minification causes errors with Express routes (#462)
475475
476476
---
477477
478-
## Rekomendacja dla Twojego use case
478+
## Recommendation for your use case
479479
480-
Dla **złożonego CLI z subkomendami, interactive prompts i wieloma distribution targets** (npm, npx, bin, deno compile):
480+
For **complex CLI with subcommands, interactive prompts, and multiple distribution targets** (npm, npx, bin, deno compile):
481481
482-
### Wybierz pkgroll jeśli:
483-
- Preferujesz zero-config i package.json jako źródło prawdy
484-
- Chcesz automatyczną obsługę shebang bez workaroundów
485-
- Potrzebujesz najlepszego tree-shaking dla mniejszych bundli
486-
- Używasz native modules
487-
- Cenisz stabilność (mature project, quick bug fixes)
482+
### Choose pkgroll if:
483+
- You prefer zero-config and package.json as source of truth
484+
- You want automatic shebang handling without workarounds
485+
- You need best-in-class tree-shaking for smaller bundles
486+
- You use native modules
487+
- You value stability (mature project, quick bug fixes)
488488
489-
### Wybierz tsdown jeśli:
490-
- Intensywnie rozwijasz CLI i potrzebujesz szybkich rebuildów
491-
- Migrujesz z tsup (wbudowane narzędzie migracji)
492-
- Potrzebujesz programmatic API
493-
- Planujesz używać frameworkowych pluginów (Vue, Solid, Svelte)
494-
- Chcesz explicit config file z defineConfig()
489+
### Choose tsdown if:
490+
- You're intensively developing CLI and need fast rebuilds
491+
- You're migrating from tsup (built-in migration tool)
492+
- You need programmatic API
493+
- You plan to use framework plugins (Vue, Solid, Svelte)
494+
- You want explicit config file with defineConfig()
495495
496-
### Moja rekomendacja
496+
### My recommendation
497497
498-
**Zacznij od pkgroll** - automatyczna obsługa shebang i zero-config znacząco redukują friction przy budowaniu CLI. Jeśli buildy staną się bottleneckiem (duży projekt, częste rebuildy), rozważ migrację do tsdown z przygotowanymi workaroundami dla shebang.
498+
**Start with pkgroll** - automatic shebang handling and zero-config significantly reduce friction when building CLIs. If builds become a bottleneck (large project, frequent rebuilds), consider migrating to tsdown with prepared shebang workarounds.
499499
500-
Struktura projektu powinna wyglądać tak:
500+
Project structure should look like this:
501501
502502
```
503503
my-cli/
504504
├── src/
505-
│ ├── cli.ts # Main entry (hashbang dodawany automatycznie)
505+
│ ├── cli.ts # Main entry (hashbang added automatically)
506506
│ ├── index.ts # Library exports (programmatic API)
507507
│ └── commands/
508508
│ ├── init.ts
@@ -527,7 +527,7 @@ Package.json:
527527
}
528528
```
529529
530-
Ta konfiguracja działa out-of-the-box dla npm, npx i globalnej instalacji, a output można łatwo przekazać do deno compile lub pkg dla standalone binaries.
530+
This configuration works out-of-the-box for npm, npx, and global installation, and the output can be easily passed to deno compile or pkg for standalone binaries.
531531
532532
## 📖 Documentation
533533

0 commit comments

Comments
 (0)