{
"main": "./js/entry.js",
"browser": {
"jquery": "./js/vendor/jquery.js"
},
"browserify-shim": {
"jquery": "$",
"three": "global:THREE"
},
"browserify": {
"transform": [ "browserify-shim" ]
},
"dependencies": {
"browserify-shim": "~3.2.0"
}
}
browserify . -d -o bundle.js
Table of Contents generated with DocToc
npm install browserify browserify-shim
For a version compatible with browserify@1.x run npm install browserify-shim@1.x
instead.
For a version compatible with the v2 API npm install browserify-shim@2.x
instead.
The core features of browserify-shim are:
window
object.depends
for shimming libraries that depend on other libraries being in the global namespace.Additionally, it handles the following real-world edge cases:
var foo = ...
on the script level and assume it gets attached to the window
object.
Since the only way they will ever be run is in the global context — "ahem, … NO?!"define
and also module
be undefined
, in order to fix improperly-authored
libraries that need
shimming but try anyway to use AMD or CommonJS. For more info read the comment inside this
fixturerequire('jquery')
although 'jquery'
isn't installed due to the library being
improperly published or installed incorrectly via a downloader like bowerSince browserify-shim
is a proper browserify
transform you can publish packages with files that need to be shimmed,
granted that you specify the shim config inside the package.json
.
When browserify
resolves your package it will run the browserify-shim
transform and thus shim what's necessary
when generating the bundle.
browserify-shim
walks upwards from each source file and uses the first "browserify-shim"
configuration it finds in a package.json
file. You can't shim files outside your project from your project's package. You can add multiple package.json
files as long as browserify-shim can always find a package above each source file with the right configuration.
In most cases you want to install it as a devDependency via:
npm install -D browserify-shim
Inside package.json
add:
{
"browserify": {
"transform": [ "browserify-shim" ]
}
}
Browserify transforms are run in order and may modify your source code along the way. You'll typically want to include browserify-shim last.
Inside package.json
add:
{
"browserify-shim": {
"./js/vendor/jquery.js": "$",
"three": "global:THREE"
}
}
The above includes ./js/vendor/jquery.js
(relative to the package.json
) in the bundle and exports window.$
.
Additionally it exposes window.THREE
as three
, so you can var three = require('three')
. More info
below.
Since jquery
does not depend on other shimmed modules and thus has no depends
field, we used the short form to
specify its exports, however the example above is equivalent to:
{
"browserify-shim": {
"./js/vendor/jquery.js": { "exports": "$" }
}
}
global:*
In some cases the libraries you are using are very large and you'd prefer to add them via a script tag instead to get the following benefits:
We'll show how this works by taking the rather huge yet awesome THREE.js
library as an example:
<!-- index.html -->
<head>
<meta charset=utf-8 />
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/three.js/r61/three.min.js"></script>
</head>
package.json
{
"browserify-shim": {
"three": "global:THREE"
}
}
In case you are using an external shim config, you may achieve the same by specifying the global via an exports
.
module.exports = {
'three': { exports: 'global:THREE' }
}
more about external configs here
Note: THREE.js
attaches window.THREE
.
var THREE = require('three');
var THREE = window.THREE
?You want to avoid spreading the knowledge that THREE
is a global and stay consistent in how you resolve dependencies.
Additionally if THREE
would ever be published to npm and you decide to install it from there,
you don't have to change any of your code since it already is require
ing it properly.
You may expose files under a different name via the browser
field and refer to them under that alias in the shim config:
{
"browser": {
"jquery": "./js/vendor/jquery.js"
},
"browserify-shim": {
"jquery": "$"
}
}
This also allows you to require this module under the alias, i.e.: var $ = require('jquery')
.
{
"browserify-shim": "./config/shim.js"
}
The external shim format is very similar to the way in which the shim is specified inside the package.json
. See
below for more details.
You may encounter problems when your shim config isn't properly setup. In that case you can diagnose them via the
BROWSERIFYSHIM_DIAGNOSTICS
flag.
Simply set the flag when building your bundle, i.e.:
BROWSERIFYSHIM_DIAGNOSTICS=1 browserify -d . -o js/bundle.js
or in a build.js
script add: process.env.BROWSERIFYSHIM_DIAGNOSTICS=1
to the top.
Some libraries depend on other libraries to have attached their exports to the window for historical reasons :(. (Hopefully soon we can truly say that this bad design is history.)
In this contrived example we are shimming four libraries since none of them are commonJS compatible:
We will be using the depends
field in order to ensure that a dependency is included and initialized before a library
that depends on it is initialized.
Below are three examples, each showing a way to properly shim the above mentioned modules.
package.json
without aliases{
"browserify": {
"transform": [ "browserify-shim" ]
},
"browserify-shim": {
"./vendor/x.js" : "$",
"./vendor/x-ui.js" : { "depends": [ "./vendor/x.js" ] },
"./vendor/y.js" : { "exports": "Y", "depends": [ "./vendor/x.js:$" ] },
"./vendor/z.js" : { "exports": "zorro", "depends": [ "./vendor/x.js:$", "./vendor/y.js:YNOT" ] }
}
}
Note: the depends
array consists of entries of the format path-to-file:export
package.json
with aliases{
"browserify": {
"transform": [ "browserify-shim" ]
},
"browser": {
"x" : "./vendor/x.js",
"x-ui" : "./vendor/x-ui.js",
"y" : "./vendor/y.js",
"z" : "./vendor/z.js"
},
"browserify-shim": {
"x" : "$",
"x-ui" : { "depends": [ "x" ] },
"y" : { "exports": "Y", "depends": [ "x:$" ] },
"z" : { "exports": "zorro", "depends": [ "x:$", "y:YNOT" ] }
}
}
Note: the depends
entries make use of the aliases as well alias:export
./config/shim.js
without aliasespackage.json
{
"browserify": {
"transform": [ "browserify-shim" ]
},
"browserify-shim": "./config/shim.js"
}
shim.js
module.exports = {
'../vendor/x.js' : { 'exports': '$' },
'../vendor/x-ui.js' : { 'depends': { '../vendor/x.js': null } },
'../vendor/y.js' : { 'exports': 'Y', 'depends': { '../vendor/x.js': '$' } },
'../vendor/z.js' : { 'exports': 'zorro', 'depends': { '../vendor/x.js': '$', '../vendor/y.js': 'YNOT' } }
}
Note: all paths are relative to ./config/shim.js
instead of the package.json
.
The main difference to a)
is the depends
field specification. Instead it being an array of strings it expresses its dependencies as a hashmap:
path-to-file
node_modules
of your package