Skip to content

Commit

Permalink
Feature: inputMap and common of commons
Browse files Browse the repository at this point in the history
  • Loading branch information
zoubin committed Mar 7, 2016
1 parent 633a765 commit 8a799e3
Show file tree
Hide file tree
Showing 16 changed files with 973 additions and 401 deletions.
140 changes: 130 additions & 10 deletions README.md
Expand Up @@ -228,8 +228,6 @@ among those created through the [`groups`](#groups) option.

Type: `Array`

**NOTE**: if there is only one single original bundle, this option is ignored.

Examples:

```javascript
Expand Down Expand Up @@ -260,13 +258,13 @@ b.plugin('common-bundle', {

```

**output**:
**output**

Type: `String`

File path to the new bundle for sharing.

**filter**:
**filter**

Specify which bundles to share the new bundle.

Expand All @@ -280,6 +278,69 @@ Type: `String`, `Array`
Passed to [`multimatch`] to determine bundles to share the new bundle.


**NOTE**
If there is only one single original bundle,
this option is ignored.

**NOTE**
If this option is specified as an array,
each element is processed one by one in the index order.

So, the `filter` can use common bundles created before,
which means we can create a common bundle from existing common bundles.

```js
b.plugin('common-bundle', {
common: [
{
output: 'ab.js',
filter: ['page/A/index.js', 'page/B/index.js'],
},
{
output: 'bc.js',
filter: ['page/C/index.js', 'page/B/index.js'],
},
{
output: 'ac.js',
filter: ['page/A/index.js', 'page/C/index.js'],
},
{
// abc.js will contain modules shared by ab.js, bc.js and ac.js
output: 'abc.js',
filter: ['ab.js', 'bc.js', 'ac.js'],
},
],
})

```

If `output` is specified as an existing bundle,
bundles matched by `filter` will be made dependent upon it,
and modules are removed if present already in `output`.

```js
b.plugin('common-bundle', {
common: [
{
output: 'bundle.js',
filter: ['page/A/index.js', 'page/B/index.js'],
},
{
output: 'component.js',
filter: 'component/**/index.js',
},
{
// Now we can load component.js asynchronously in A, and B,
// with no component loaded twice.
output: 'bundle.js',
filter: 'component.js',
},
],
})

```


#### basedir
Specify how to name the bundles created.

Expand All @@ -289,14 +350,73 @@ Type: `String`

### Events

#### b.on('common.map', map => {})
**map**
#### b.on('common.map', (bundleMap, inputMap) => {})

Suppose there are two pages, `hi` and `hello`,
both depend upon `lodash` and `say`.

We can use the following options to create a `common.js`,
and check `bundleMap` and `inputMap`.

```js
b.plugin(require('../..'), {
groups: 'page/**/index.js',
common: 'common.js',
})
b.on('common.map', function (bundleMap, inputMap) {
console.log(JSON.stringify(bundleMap, null, 2))
console.log(JSON.stringify(inputMap, null, 2))
})

```

You can use `Object.keys(map)` to get paths (`file.relative`) to all bundles.
**bundleMap**

```js
{
// bundle => {}
"page/hi/index.js": {
"modules": [
// modules in this bundle
"page/hi/index.js"
],
"deps": [
// bundles should come before this bundle
"common.js"
]
},
"page/hello/index.js": {
"modules": [
"page/hello/index.js"
],
"deps": [
"common.js"
]
},
"common.js": {
"modules": [
"node_modules/lodash/index.js",
"web_modules/say/index.js"
]
}
}

In addition, `map[bundle]` is an object with the following fields:
* `modules`: `Array`. Paths to modules (relative to `basedir`) packed into `bundle`
* `deps`: `Array`. Paths to common bundles (`file.relative`) that `bundle` depends upon.
```

**inputMap**

```js
{
// input file => [bundles]
"page/hello/index.js": [
"page/hello/index.js"
],
"page/hi/index.js": [
"page/hi/index.js"
]
}

```

#### b.on('common.pipeline', (id, pipeline) => {})

Expand Down
28 changes: 28 additions & 0 deletions example/map/bundle.js
@@ -0,0 +1,28 @@
'use strict'

const browserify = require('browserify')
const vfs = require('vinyl-fs')
const del = require('del')
const glob = require('glob')
const path = require('path')

const basedir = path.resolve(__dirname, 'src')
const entries = glob.sync('page/**/index.js', { cwd: basedir })
const b = browserify(entries, {
basedir: basedir,
paths: [path.resolve(__dirname, 'src', 'web_modules')],
})
const build = path.resolve(__dirname, 'build')

b.plugin(require('../..'), {
groups: 'page/**/index.js',
common: 'common.js',
})

del.sync(build)
b.on('common.map', function (bundleMap, inputMap) {
console.log(JSON.stringify(bundleMap, null, 2))
console.log(JSON.stringify(inputMap, null, 2))
})
b.bundle().pipe(vfs.dest(build))

3 changes: 3 additions & 0 deletions example/map/src/node_modules/lodash/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions example/map/src/page/hello/index.js
@@ -0,0 +1 @@
module.exports = require('say')('Hello, world!')
1 change: 1 addition & 0 deletions example/map/src/page/hi/index.js
@@ -0,0 +1 @@
module.exports = require('say')('Hi, there!')
2 changes: 2 additions & 0 deletions example/map/src/web_modules/say/index.js
@@ -0,0 +1,2 @@
require('lodash')
module.exports = console.log.bind(console)
45 changes: 45 additions & 0 deletions example/map/watch.js
@@ -0,0 +1,45 @@
'use strict'

const browserify = require('browserify')
const vfs = require('vinyl-fs')
const del = require('del')
const glob = require('glob')
const path = require('path')

const basedir = path.resolve(__dirname, 'src')
const entries = glob.sync('page/**/index.js', { cwd: basedir })
const b = browserify(entries, {
basedir: basedir,
cache: {},
packageCache: {},
paths: [path.resolve(__dirname, 'src', 'web_modules')],
})

b.plugin(require('../..'), {
groups: 'page/**/index.js',
common: [
{
output: 'common-red-and-green.js',
filter: ['page/red/index.js', 'page/green/index.js'],
},
{
output: 'common-hello-and-hi.js',
filter: ['page/hi/index.js', 'page/hello/index.js'],
},
],
})

b.plugin('watchify2', { entryGlob: 'page/**/index.js' })

function bundle() {
let build = path.resolve(__dirname, 'build')
del.sync(build)
b.bundle().pipe(vfs.dest(build))
}

b.on('update', bundle)

b.on('log', console.log.bind(console))

bundle()

4 changes: 4 additions & 0 deletions example/multi/bundle.js
Expand Up @@ -29,5 +29,9 @@ b.plugin(require('../..'), {
})

del.sync(build)
b.on('common.map', function (bundleMap, inputMap) {
console.log(JSON.stringify(bundleMap, null, 2))
console.log(JSON.stringify(inputMap, null, 2))
})
b.bundle().pipe(vfs.dest(build))

42 changes: 23 additions & 19 deletions index.js
Expand Up @@ -27,6 +27,7 @@ module.exports = function (b, opts) {
function end(done) {
var noop = function () {}
var output = through.obj(noop, noop)

var vinylStream = vinylify({
basedir: basedir,
groupFilter: opts.groups || input,
Expand All @@ -45,27 +46,30 @@ module.exports = function (b, opts) {
},
})

var map = {}
vinylStream.on('output', function (id, file) {
map[id] = map[id] || {}
map[id].modules = map[id].modules || []
map[id].modules.push(path.relative(basedir, file))
})
vinylStream.once('common', function (bundle2common) {
bundle2common.forEach(function (commons, id) {
map[id] = map[id] || {}
map[id].deps = []
for (let i of commons) {
map[id].deps.push(i)
}
})
var inputFiles = input.map(file => path.relative(basedir, file))
vinylStream.once('map', function (bundleMap) {
var inputMap = inputFiles.reduce(function (o, file) {
o[file] = []
return o
}, Object.create(null))
for (let bundle in bundleMap) {
let modules = bundleMap[bundle].modules
modules = Object.keys(modules).map(id => path.relative(basedir, modules[id]))
bundleMap[bundle].modules = modules
let moduleMap = modules.reduce(function (o, file) {
o[file] = true
return o
}, Object.create(null))
inputFiles.forEach(function (file) {
if (moduleMap[file]) {
inputMap[file].push(bundle)
}
})
}
b.emit('common.map', bundleMap, inputMap)
})

vinylStream.on('data', file => output.push(file))
vinylStream.once('end', function () {
output.push(null)
b.emit('common.map', map)
})
vinylStream.once('end', () => output.push(null))

b.pipeline.get('pack').unshift(
through.obj(function (row, _, next) {
Expand Down

0 comments on commit 8a799e3

Please sign in to comment.