npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

common-bundle

v0.5.1

Published

A browserify plugin for packing modules into common shared bundles.

Downloads

30

Readme

common-bundle

version status coverage dependencies devDependencies node

A browserify plugin for packing modules into common shared bundles.

Features:

  • Powerful control on creating bundles
  • b.bundle() generates a stream flowing vinyl file objects.

Example

var browserify = require('browserify')
var glob = require('glob')
 
var basedir = '/path/to/src'
var entries = glob.sync('page/**/index.js', { cwd: basedir })
var b = browserify(entries, { basedir: basedir })
 
b.plugin('common-bundle', {
  // Pack each index.js and their dependencies into a new bundle
  // e.g. '/path/to/src/page/hi/index.js' => 'page/hi/index.js'
  groups: 'page/**/index.js',
  // create an additional bundle to hold common moudles shared by all other bundles
  common: 'common.js',
})
 
var vfs = require('vinyl-fs')
// Write all bundles to the build directory
// e.g. 'page/hi/index.js' => '/path/to/build/page/hi/index.js'
b.bundle().pipe(vfs.dest('/path/to/build'))

Or

var browserify = require('browserify')
var glob = require('glob')
 
var basedir = '/path/to/src'
var entries = glob.sync('page/**/index.js', { cwd: basedir })
var b = browserify(entries, { basedir: basedir })
 
b.plugin('common-bundle', function (entries) { 
  entries.forEach(function (file) { 
    // create a new bundle
    this.add(
      file,   // path of the new bundle
      file    // modules (and their dependencies) to hold
    )
  }, this)

  // create a new bundle for sharing modules
  this.addCommon( 
    'common.js',  // name of the common bundle
    'page/**/index.js'  // bundles to share the common bundle
  )
})
 
var vfs = require('vinyl-fs')
// Write all bundles to the build directory
// e.g. 'page/hi/index.js' => '/path/to/build/page/hi/index.js'
b.bundle().pipe(vfs.dest('/path/to/build'))

options

options can be specified in three ways:

  • String. Pack all modules into a single bundle.
  • Object. Creating bundles according to the groups and common field. Default
  • Function. Creating bundles manually.

groups and common

options.groups is used to create bundles for holding specified modules.

{ 
  // two bundles will be created
  // one is 'a.js', to hold the module 'a.js'
  // the other is 'b.js', to hold the module 'b.js'
  groups: ['a.js', 'b.js'],
}

To specify paths (rather than the default) for the created bundles:

{ 
  // two bundles will be created
  // one is 'bundle-a.js', to hold the module 'a.js'
  // the other is 'bundle-b.js', to hold the module 'b.js'
  groups: { 
    'bundle-a.js': 'a.js',
    'bundle-b.js': 'b.js',
  },
}

If options.groups is omitted, it defaults to the entries input to the bundler.

var browserify = require('browserify')
var entries = ['a.js', 'b.js']
var b = browserify(entries, { basedir: '/path/to/src' })

b.plugin('common-bundle')
// the same with
// b.plugin('common-bundle', { groups: entries })

Patterns are also accepted:

{
  groups: 'page/**/index.js'
}

It is the same with:

{
  groups: modulesMatched
}

modulesMatched is the result of matching the given pattern against all modules. Refer to multimatch for more information about the pattern.

options.common allow you to create a bundle for holding common modules shared by all other bundles.

{
  // one bundle for each entry
  // an additional bundle for holding modules shared by all entry bundles
  common: 'common.js'
}

manual control on the process of creating bundles

If options is specified as a function, it will be called as a method of the BundleFactory.

// receives the original entries
function (entries) {
  entries.forEach(function (file) { 
    // create a new bundle
    this.add(
      file,   // path of the new bundle
      file    // modules (and their dependencies) to hold
    )
  }, this)

  // create a new bundle for sharing modules
  this.addCommon( 
    'common.js',  // name of the common bundle
    this.getBundles()  // bundles to share the common bundle
  )
}

BundleFactory

A BundleFactory instance provides some methods to create bundles.

add

Signature: add(bundlePath, modulesToHold)

Create a new bundle with the path of bundlePath. All modules specified by modulesToHold and their dependencies will go to this bundle.

If bundlePath already exists, modules are just added to it.

modulesToHold should be paths to modules. You can use the getModules or select method to pick some specific modules in some cases.

getModules

Signature: getModules(patterns)

Pick some modules from the whole module set.

patterns should be accptable by multimatch

getBundles

Signature: getBundles(patterns)

Pick some bundles from the whole bundle set.

patterns should be accptable by multimatch

select

Signature: select(bundles, threshold, hasMagic)

Select modules from some bundles according to threshold.

If you are specifying patterns for the bundles, the third argument should be true.

threshold could be Number, which means modules are picked only when they are shared by more than the specific amount of bundles. By default, the picked modules are those shared by all bundles.

If threshold is specified as a function, it should respect the following signature:

isPicked = threshold(row, groups)

row is the module representation object. You can access the module path by row.file.

groups is an array of bundles holding row.

// get all bundles
var targetBundles = this.getBundles()
this.select(
  targetBundles,
  function (row, groups) {
    // pick row when more than half bundles holding it
    return groups.length * 2 > targetBundles
  }
)

addCommon

Signature: addCommon(commonBundlePath, bundlesToShare, threshold)

Pick some modules by calling this.select(bundlesToShare, threshold), and create a bundle with the path of commonBundlePath to hold them.

Moreover, the picked modules will be removed from each bundle in bundlesToShare.

Events

b.on('common.map', (o) => {})

Suppose there are two entries a.js and b.js, and they both require('./c').

We use the default options to create two bundles holding a.js and b.js respectively.

Then o will look like:

{
  "bundles": {
    // bundle path => { modules: [module id], deps: [bundle path] }
    "a.js": {
      "modules": [ 3, 1 ],
      "deps": []
    },
    "b.js": {
      "modules": [ 3, 2 ],
      "deps": []
    }
  },
  "modules": {
    // module id => { file: module path, bundles: [ [bundles] ] }
    "1": {
      "file": "a.js",
      "bundles": [
        [ "a.js" ]
      ]
    },
    "2": {
      "file": "b.js",
      "bundles": [
        [ "b.js" ]
      ]
    },
    "3": {
      "file": "c.js",
      "bundles": [
        // load this group of bundles to make c.js available
        [ "a.js" ],
        // or load this group
        [ "b.js" ]
      ]
    }
  },
  "entries": [ 1, 2 ],
  "basedir": "/path/to/src"
}

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

Every time a bundle created, a common.pipeline event is emitted with its id and the packing pipeline.

A pipeline is a labeled-stream-splicer:

You can call pipeline.get with a label name to get a handle on a stream pipeline that you can push(), unshift(), or splice() to insert your own transform streams.

Event handlers must be attached before calling b.plugin.

Work with gulp

var gulp = require('gulp')
var browserify = require('browserify')
var del = require('del')
var glob = require('globby')
var path = require('path')

gulp.task('build', function () {
  del.sync('build')
  return createBundler().bundle().pipe(gulp.dest('build'))
})

gulp.task('watch', function (cb) {
  var b = createBundler()
    .plugin('watchify2', { entryGlob: 'page/**/index.js' })
    .on('close', cb)
    .on('update', bundle)
  function bundle() {
    del.sync('build')
    b.bundle().pipe(gulp.dest('build'))
  }
  bundle()
})

function createBundler() {
  var basedir = path.resolve(__dirname, 'src')
  var entries = glob.sync('page/**/index.js', { cwd: basedir })
  var b = browserify(entries, { basedir: basedir })
  b.plugin('common-bundle', {
    groups: 'page/**/index.js',
    common: 'common.js',
  })
  b.on('common.map', function (o) {
    console.log(
      'bundles:', Object.keys(o.bundles).length,
      'modules:', Object.keys(o.modules).length,
      'entries:', Object.keys(o.entries).length
    )
  })
  return b
}