<div align="center">
  <br/>
  <br/>
  <img src="./assets/logo.png" alt="whybundled" width="600" align="center">
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
</div>

<p align="center">
  <a href="https://npmjs.org/package/whybundled">
    <img src="https://img.shields.io/npm/v/whybundled.svg" alt="NPM Version">
  </a>

  <a href="http://opensource.org/licenses/MIT">
    <img src="https://img.shields.io/npm/l/whybundled.svg" alt="License">
  </a>

  <a href="https://github.com/d4rkr00t/whybundled/issues">
    <img src="https://img.shields.io/github/issues/d4rkr00t/whybundled.svg" alt="Github Issues">
  </a>

  <a href='https://coveralls.io/github/d4rkr00t/whybundled'>
    <img src='https://coveralls.io/repos/github/d4rkr00t/whybundled/badge.svg' alt='Coverage Status' />
  </a>

  <a href="http://commitizen.github.io/cz-cli/">
    <img src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg" alt="Commitizen Friendly">
  </a>
</p>
<br/>
<br/>

Ever wondered why any particular module ended up in a bundle? WhyBundled is here to answer exactly this question.

It's meant to be used alongside [stats report from webpack](https://webpack.js.org/api/stats/).

## Quick Start

```sh
npm i -g whybundled

whybundled stats.json ← stats file generated by wepback
```

![whybundled default report](/assets/screenshot.png)

## Usage

```sh
USAGE
  whybundled stats.json [pattern]

COMMANDS
  by     Shows all modules that were brought into the bundle by a particular module.

OPTIONS
  --limit              Limits output of reasons and files [number] [default: 20]
  --filesOnly          Only include files [boolean]
  --modulesOnly        Only include modules [boolean]
  --directoryOnly      Only include direct dependencies [boolean]
  --transitiveOnly     Only include transitive dependencies [boolean]
  --duplicatesOnly     Only include modules that have duplicates in a resulting bundle [boolean]
  --ignore             Comma separated list of glob patterns to exclude modules from final output [string]
  --sortBy             Sort modules, available fields: size, imported. E.g. size:asc or size:desc. [string]
  --help               Output usage information
  --version            Output the version number

EXAMPLES
  whybundled stats.json --ignore babel-runtime,tslib
  whybundled stats.json --modulesOnly
  whybundled by stats.json styled-components
```

## Features

### Stats Analyses

- Outputs list of all modules/files included in the bundle in from most imported to least imported order.
- Builds a chain of dependencies for transitive dependencies.
- Shows all files that were included for particular module.
- Shows all reasons why particular module was included.

```sh
MODULE  isobject
├─ imported: 1 time     ← number of times module imported
├─ type: [transitive]   ← type of a dependency can be either direct or transitive
│  └─ isobject -> is-plain-object -> styled-components    ← for transitive dependencies whybundled outputs a chain of dependencies up to the closest direct
│
├─ locations:  ← where module is located in a project
│  └─ ../node_modules/isobject/
│
├─ files:      ← list of files that were included for this module
│  └─ ../node_modules/isobject/index.js
│
└─ reasons:    ← list of reasons why module was included in a bundle
   └─ is-plain-object
      └─ ../node_modules/is-plain-object/index.js  10:15-34  [cjs require]
```

### Duplicates Badge

If module has been bundled several times from different locations `whybundled` adds `[multiple]` badge next to the locations field:

![whybundled duplicates](/assets/multiple.png)

### Brought by

Using `by` command `whybundled` shows all modules that were brought into the bundle by a particular module:

```sh
USAGE
  whybundled by stats.json [pattern]

OPTIONS
  --limit      Limits output of reasons and files [number=20]
  --only       Limits output to only include modules that were included by specified module exclusively [boolean]
  --ignore     Comma separated list of glob patterns to exclude modules from final output [string]

EXAMPLES
  whybundled by stats.json styled-components
  whybundled by stats.json styled-components --ignore babel-runtime,tslib
  whybundled by stats.json styled-components --only
```

![whybundled brought by](/assets/by.png)
