# browser-pack-flat

> bundle browserify modules into a single scope, a la rollup

Latest version **3.5.0** (published 2022-07-01) · MIT license · 0 weekly downloads

## Install

```sh
npm install browser-pack-flat
pnpm add browser-pack-flat
yarn add browser-pack-flat
bun add browser-pack-flat
```

Provides the command `browser-pack-flat`.

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 3.5.0 |
| Published | 2022-07-01 |
| First published | 2017-06-18 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 15 |
| Unpacked size | 146.2 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 55 |
| Author | Renée Kooi |
| Maintainers | goto-bus-stop |

## Links

- npm: https://www.npmjs.com/package/browser-pack-flat
- Repository: https://github.com/goto-bus-stop/browser-pack-flat
- Homepage: https://github.com/goto-bus-stop/browser-pack-flat#readme
- Issues: https://github.com/goto-bus-stop/browser-pack-flat/issues
- npm.io page: https://npm.io/package/browser-pack-flat

## Dependencies (15)

- [umd](https://npm.io/package/umd.md) ^3.0.3
- [dedent](https://npm.io/package/dedent.md) ^0.7.0
- [esutils](https://npm.io/package/esutils.md) ^2.0.2
- [through2](https://npm.io/package/through2.md) ^3.0.1
- [JSONStream](https://npm.io/package/JSONStream.md) ^1.3.2
- [path-parse](https://npm.io/package/path-parse.md) ^1.0.5
- [count-lines](https://npm.io/package/count-lines.md) ^0.1.2
- [wrap-comment](https://npm.io/package/wrap-comment.md) ^1.0.0
- [transform-ast](https://npm.io/package/transform-ast.md) ^2.4.2
- [scope-analyzer](https://npm.io/package/scope-analyzer.md) ^2.0.0
- [stream-combiner](https://npm.io/package/stream-combiner.md) ^0.2.2
- [estree-is-require](https://npm.io/package/estree-is-require.md) ^1.0.0
- [combine-source-map](https://npm.io/package/combine-source-map.md) ^0.8.0
- [convert-source-map](https://npm.io/package/convert-source-map.md) ^1.5.1
- [estree-is-member-expression](https://npm.io/package/estree-is-member-expression.md) ^1.0.0

## Recent versions

- 3.5.0 (latest) — 2022-07-01
- 3.4.2 — 2019-06-04
- 3.4.1 — 2019-05-24
- 3.4.0 — 2019-05-05
- 3.3.0 — 2019-01-24
- 3.2.0 — 2018-09-08
- 3.1.0 — 2018-05-23
- 3.0.9 — 2018-04-28
- 3.0.8 — 2018-02-06
- 3.0.7 — 2018-01-26
- 3.0.6 — 2018-01-02
- 3.0.5 — 2017-11-18
- 3.0.4 — 2017-11-17
- 3.0.3 — 2017-10-27
- 3.0.2 — 2017-10-24
- … 13 more at https://npm.io/package/browser-pack-flat/versions

## README

# browser-pack-flat

Bundle browserify modules into a single scope, a la rollup.

Caveats:

 - Modules are executed fully, one after another, instead of inline.
   This is a potential difference from Node.js and the default browserify behaviour.
   Usually this does not matter, but rarely the order that some things are executed in may change.
 - This rewrites `require()` calls to simple variable assignments.
   If a module wraps `require()` somehow it probably will not work.
   In practice this is quite rare.
 - Using `factor-bundle` to split output code into separate files will not work with this plugin.

## Install

```bash
npm install --save-dev browser-pack-flat
```

## Usage

```bash
browserify /path/to/app.js | browser-unpack | browser-pack-flat
```

Or as a plugin:

```bash
browserify /path/to/app.js -p browser-pack-flat
```

The plugin replaces the `browser-pack` module used by default by browserify.

With the Node API:

```js
var browserify = require('browserify')
var packFlat = require('browser-pack-flat')

browserify({ entries: './src/app.js' })
  .plugin(packFlat, { /* options */ })
  .bundle()
  .pipe(fs.createWriteStream('bundle.js'))
```

## What exactly?

browserify uses [browser-pack](https://github.com/browserify/browser-pack) to output a bundle.
browser-pack uses a small `require`-like runtime and wraps modules in functions to get a module loading behaviour that's almost identical to Node.js.
However this resolution can take a few milliseconds across an entire bundle.

Input:

```js
var unique = require('uniq');

var data = [1, 2, 2, 3, 4, 5, 5, 5, 6];

console.log(unique(data));
```

With browser-pack, this bundle would output:

```js
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var unique = require('uniq');

var data = [1, 2, 2, 3, 4, 5, 5, 5, 6];

console.log(unique(data));
},{"uniq":2}],2:[function(require,module,exports){
"use strict"

/* -- snip -- */

function unique(list, compare, sorted) {
  if(list.length === 0) {
    return list
  }
  if(compare) {
    if(!sorted) {
      list.sort(compare)
    }
    return unique_pred(list, compare)
  }
  if(!sorted) {
    list.sort()
  }
  return unique_eq(list)
}

module.exports = unique

},{}]},{},[1]);
```

browser-pack-flat instead rewrites `require()` calls and `module.exports` assignments to simple variables, and sorts the modules so that the module that would be executed first, is at the top of the bundle.
It doesn't need a runtime in most cases, and no function calls to execute modules.

```js
(function(){
"use strict"

/* -- snip -- */

function unique(list, compare, sorted) {
  if(list.length === 0) {
    return list
  }
  if(compare) {
    if(!sorted) {
      list.sort(compare)
    }
    return unique_pred(list, compare)
  }
  if(!sorted) {
    list.sort()
  }
  return unique_eq(list)
}

var _$unique_2 = unique

var _$main_1 = {};
/* removed: var _$unique_2 = require('uniq'); */;

var data = [1, 2, 2, 3, 4, 5, 5, 5, 6];

console.log(_$unique_2(data));
}());
```

Instead of `require('uniq')`, the main module simply refers to `_$unique_2`, which is the exports value of the `uniq` module.
The only function wrapper is the outermost one, which prevents variables from leaking into the `window` (global scope).

Sometimes it's not possible to sort modules in their execution order, because in the Node.js module system, a module can require another module that requires the first module: a circular dependency.
browser-pack-flat addresses this with a small runtime, to lazily execute modules that are part of a circular dependency chain.
This works similarly to how the Node.js module system works, and to how the standard browser-pack works too.
Instead of rewriting `require()`s to variables and `module.exports` to a variable assignment, in "circular modules" browser-pack-flat adds a function wrapper.
When a circular module is `require()`d, browser-pack-flat will call the function wrapper, which executes the module and caches the exports.

Below, `a.js` depends on `b.js`, and `b.js` depends on `a.js`:

```js
// app.js
console.log(
  require('./a')()
)
// a.js
var b = require('./b')
module.exports = function () {
  return b()
}
// b.js
module.exports = function () {
  return require('./a').toString()
}
```

With browser-pack-flat, this becomes:

```js
(function(){
var createModuleFactory = function createModuleFactory(factory) {
  var module; return function () { if (!module) { module = { exports: {} }; factory(module, module.exports) } return module.exports }
};
var _$a_1 = createModuleFactory(function (module, exports) {
var b = _$b_3()
module.exports = function () {
  return b()
}

});
var _$b_3 = createModuleFactory(function (module, exports) {
module.exports = function () {
  return _$a_1().toString()
}

});
var _$app_2 = {};
console.log(
  _$a_1()()
)

}());
```

The `createModuleFactory` helper returns the exports of the module it wraps, evaluating the module on the first call.
Instead of replacing `require('./a')` with `_$a_1` like browser-pack-flat normally would, it replaced it with `_$a_1()`.

browser-pack-flat does some more things like rewriting top-level variables in modules in case there is another variable with the same name in another module, but that's most of the magic!

## Related

 * [common-shakeify](https://github.com/goto-bus-stop/common-shakeify) - Tree-shaking plugin for browserify based on [@indutny](https://github.com/indutny)'s [common-shake](https://github.com/indutny/common-shake) library
 * [tinyify](https://github.com/browserify/tinyify) - Optimization plugin for browserify, includes browser-pack-flat

## License

[MIT](./LICENSE)

---
_Source: https://npm.io/package/browser-pack-flat · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
