{"id":13432895,"url":"https://github.com/browserify/browserify-handbook","last_synced_at":"2025-12-17T07:54:04.926Z","repository":{"id":17135492,"uuid":"19901927","full_name":"browserify/browserify-handbook","owner":"browserify","description":"how to build modular applications with browserify","archived":false,"fork":false,"pushed_at":"2024-12-21T10:01:06.000Z","size":237,"stargazers_count":4602,"open_issues_count":19,"forks_count":292,"subscribers_count":104,"default_branch":"master","last_synced_at":"2025-10-14T03:32:48.939Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/browserify.png","metadata":{"files":{"readme":"readme.markdown","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-05-18T03:24:36.000Z","updated_at":"2025-09-18T07:59:28.000Z","dependencies_parsed_at":"2025-05-14T16:07:31.012Z","dependency_job_id":"7f7864e3-f199-437e-96f9-d6378f27a523","html_url":"https://github.com/browserify/browserify-handbook","commit_stats":null,"previous_names":["substack/browserify-handbook"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/browserify/browserify-handbook","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserify%2Fbrowserify-handbook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserify%2Fbrowserify-handbook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserify%2Fbrowserify-handbook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserify%2Fbrowserify-handbook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/browserify","download_url":"https://codeload.github.com/browserify/browserify-handbook/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserify%2Fbrowserify-handbook/sbom","scorecard":{"id":254776,"data":{"date":"2025-08-11","repo":{"name":"github.com/browserify/browserify-handbook","commit":"0d2893ca704c17e86c6e630ece97d0d1ae74bf16"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.3,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":3,"reason":"Found 9/26 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/browserify/.github/SECURITY.md:1","Info: Found linked content: github.com/browserify/.github/SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: github.com/browserify/.github/SECURITY.md:1","Info: Found text in security policy: github.com/browserify/.github/SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 15 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T09:22:46.938Z","repository_id":17135492,"created_at":"2025-08-17T09:22:46.938Z","updated_at":"2025-08-17T09:22:46.938Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27779778,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-17T02:00:08.291Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T02:01:18.168Z","updated_at":"2025-12-17T07:54:04.904Z","avatar_url":"https://github.com/browserify.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","others"],"sub_categories":[],"readme":"# introduction\n\nThis document covers how to use [browserify](http://browserify.org) to build\nmodular applications.\n\n[![cc-by-3.0](http://i.creativecommons.org/l/by/3.0/80x15.png)](http://creativecommons.org/licenses/by/3.0/)\n\nbrowserify is a tool for compiling\n[node-flavored](http://nodejs.org/docs/latest/api/modules.html) commonjs modules\nfor the browser.\n\nYou can use browserify to organize your code and use third-party libraries even\nif you don't use [node](http://nodejs.org) itself in any other capacity except\nfor bundling and installing packages with npm.\n\nThe module system that browserify uses is the same as node, so\npackages published to [npm](https://npmjs.org) that were originally intended for\nuse in node but not browsers will work just fine in the browser too.\n\nIncreasingly, people are publishing modules to npm which are intentionally\ndesigned to work in both node and in the browser using browserify and many\npackages on npm are intended for use in just the browser.\n[npm is for all javascript](http://maxogden.com/node-packaged-modules.html),\nfront or backend alike.\n\n# table of contents\n\n- [introduction](#introduction)\n- [table of contents](#table-of-contents)\n- [node packaged manuscript](#node-packaged-manuscript)\n- [node packaged modules](#node-packaged-modules)\n  - [require](#require)\n  - [exports](#exports)\n  - [bundling for the browser](#bundling-for-the-browser)\n  - [how browserify works](#how-browserify-works)\n  - [how node_modules works](#how-node_modules-works)\n  - [why concatenate](#why-concatenate)\n- [development](#development)\n  - [source maps](#source-maps)\n    - [exorcist](#exorcist)\n  - [auto-recompile](#auto-recompile)\n    - [watchify](#watchify)\n    - [beefy](#beefy)\n    - [wzrd](#wzrd)\n    - [browserify-middleware, enchilada](#browserify-middleware-enchilada)\n    - [livereactload](#livereactload)\n    - [browserify-hmr](#browserify-hmr)\n    - [budo](#budo)\n  - [using the api directly](#using-the-api-directly)\n  - [grunt](#grunt)\n  - [gulp](#gulp)\n- [builtins](#builtins)\n  - [Buffer](#Buffer)\n  - [process](#process)\n  - [global](#global)\n  - [__filename](#__filename)\n  - [__dirname](#__dirname)\n- [transforms](#transforms)\n  - [writing your own](#writing-your-own)\n- [package.json](#packagejson)\n  - [browser field](#browser-field)\n  - [browserify.transform field](#browserifytransform-field)\n- [finding good modules](#finding-good-modules)\n  - [module philosophy](#module-philosophy)\n- [organizing modules](#organizing-modules)\n  - [avoiding ../../../../../../..](#avoiding-)\n  - [non-javascript assets](#non-javascript-assets)\n  - [reusable components](#reusable-components)\n- [testing in node and the browser](#testing-in-node-and-the-browser)\n  - [testing libraries](#testing-libraries)\n  - [code coverage](#code-coverage)\n  - [testling-ci](#testling-ci)\n- [bundling](#bundling)\n  - [saving bytes](#saving-bytes)\n  - [tinyify](#tinyify)\n  - [standalone](#standalone)\n  - [external bundles](#external-bundles)\n  - [ignoring and excluding](#ignoring-and-excluding)\n  - [browserify cdn](#browserify-cdn)\n- [shimming](#shimming)\n  - [browserify-shim](#browserify-shim)\n- [partitioning](#partitioning)\n  - [factor-bundle](#factor-bundle)\n  - [partition-bundle](#partition-bundle)\n- [compiler pipeline](#compiler-pipeline)\n  - [build your own browserify](#build-your-own-browserify)\n  - [labeled phases](#labeled-phases)\n    - [deps](#deps)\n    - [json](#json)\n    - [unbom](#unbom)\n    - [syntax](#syntax)\n    - [sort](#sort)\n    - [dedupe](#dedupe)\n    - [label](#label)\n    - [emit-deps](#emit-deps)\n    - [debug](#debug)\n    - [pack](#pack)\n    - [wrap](#wrap)\n  - [browser-unpack](#browser-unpack)\n- [plugins](#plugins)\n  - [using plugins](#using-plugins)\n  - [authoring plugins](#authoring-plugins)\n\n# node packaged manuscript\n\nYou can install this handbook with npm, appropriately enough. Just do:\n\n```\nnpm install -g browserify-handbook\n```\n\nNow you will have a `browserify-handbook` command that will open this readme\nfile in your `$PAGER`. Otherwise, you may continue reading this document as you\nare presently doing.\n\n# node packaged modules\n\nBefore we can dive too deeply into how to use browserify and how it works, it is\nimportant to first understand how the\n[node-flavored version](http://nodejs.org/docs/latest/api/modules.html)\nof the commonjs module system works.\n\n## require\n\nIn node, there is a `require()` function for loading code from other files.\n\nIf you install a module with [npm](https://npmjs.org):\n\n```\nnpm install uniq\n```\n\nThen in a file `nums.js` we can `require('uniq')`:\n\n```\nvar uniq = require('uniq');\nvar nums = [ 5, 2, 1, 3, 2, 5, 4, 2, 0, 1 ];\nconsole.log(uniq(nums));\n```\n\nThe output of this program when run with node is:\n\n```\n$ node nums.js\n[ 0, 1, 2, 3, 4, 5 ]\n```\n\nYou can require relative files by requiring a string that starts with a `.`. For\nexample, to load a file `foo.js` from `main.js`, in `main.js` you can do:\n\n``` js\nvar foo = require('./foo.js');\nconsole.log(foo(4));\n```\n\nIf `foo.js` was in the parent directory, you could use `../foo.js` instead:\n\n``` js\nvar foo = require('../foo.js');\nconsole.log(foo(4));\n```\n\nor likewise for any other kind of relative path. Relative paths are always\nresolved with respect to the invoking file's location.\n\nNote that `require()` returned a function and we assigned that return value to a\nvariable called `uniq`. We could have picked any other name and it would have\nworked the same. `require()` returns the exports of the module name that you\nspecify.\n\nHow `require()` works is unlike many other module systems where imports are akin\nto statements that expose themselves as globals or file-local lexicals with\nnames declared in the module itself outside of your control. Under the node\nstyle of code import with `require()`, someone reading your program can easily\ntell where each piece of functionality came from. This approach scales much\nbetter as the number of modules in an application grows.\n\n## exports\n\nTo export a single thing from a file so that other files may import it, assign\nover the value at `module.exports`:\n\n``` js\nmodule.exports = function (n) {\n    return n * 111\n};\n```\n\nNow when some module `main.js` loads your `foo.js`, the return value of\n`require('./foo.js')` will be the exported function:\n\n``` js\nvar foo = require('./foo.js');\nconsole.log(foo(5));\n```\n\nThis program will print:\n\n```\n555\n```\n\nYou can export any kind of value with `module.exports`, not just functions.\n\nFor example, this is perfectly fine:\n\n``` js\nmodule.exports = 555\n```\n\nand so is this:\n\n``` js\nvar numbers = [];\nfor (var i = 0; i \u003c 100; i++) numbers.push(i);\n\nmodule.exports = numbers;\n```\n\nThere is another form of doing exports specifically for exporting items onto an\nobject. Here, `exports` is used instead of `module.exports`:\n\n``` js\nexports.beep = function (n) { return n * 1000 }\nexports.boop = 555\n```\n\nThis program is the same as:\n\n``` js\nmodule.exports.beep = function (n) { return n * 1000 }\nmodule.exports.boop = 555\n```\n\nbecause `module.exports` is the same as `exports` and is initially set to an\nempty object.\n\nNote however that you can't do:\n\n``` js\n// this doesn't work\nexports = function (n) { return n * 1000 }\n```\n\nbecause the export value lives on the `module` object, and so assigning a new\nvalue for `exports` instead of `module.exports` masks the original reference. \n\nInstead if you are going to export a single item, always do:\n\n``` js\n// instead\nmodule.exports = function (n) { return n * 1000 }\n```\n\nIf you're still confused, try to understand how modules work in\nthe background:\n\n``` js\nvar module = {\n  exports: {}\n};\n\n// If you require a module, it's basically wrapped in a function\n(function(module, exports) {\n  exports = function (n) { return n * 1000 };\n}(module, module.exports))\n\nconsole.log(module.exports); // it's still an empty object :(\n```\n\nMost of the time, you will want to export a single function or constructor with\n`module.exports` because it's usually best for a module to do one thing.\n\nThe `exports` feature was originally the primary way of exporting functionality\nand `module.exports` was an afterthought, but `module.exports` proved to be much\nmore useful in practice at being more direct, clear, and avoiding duplication.\n\nIn the early days, this style used to be much more common:\n\nfoo.js:\n\n``` js\nexports.foo = function (n) { return n * 111 }\n```\n\nmain.js:\n\n``` js\nvar foo = require('./foo.js');\nconsole.log(foo.foo(5));\n```\n\nbut note that the `foo.foo` is a bit superfluous. Using `module.exports` it\nbecomes more clear:\n\nfoo.js:\n\n``` js\nmodule.exports = function (n) { return n * 111 }\n```\n\nmain.js:\n\n``` js\nvar foo = require('./foo.js');\nconsole.log(foo(5));\n```\n\n## bundling for the browser\n\nTo run a module in node, you've got to start from somewhere.\n\nIn node you pass a file to the `node` command to run a file:\n\n```\n$ node robot.js\nbeep boop\n```\n\nIn browserify, you do this same thing, but instead of running the file, you\ngenerate a stream of concatenated javascript files on stdout that you can write\nto a file with the `\u003e` operator:\n\n```\n$ browserify robot.js \u003e bundle.js\n```\n\nNow `bundle.js` contains all the javascript that `robot.js` needs to work.\nJust plop it into a single script tag in some html:\n\n``` html\n\u003chtml\u003e\n  \u003cbody\u003e\n    \u003cscript src=\"bundle.js\"\u003e\u003c/script\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nBonus: if you put your script tag right before the `\u003c/body\u003e`, you can use all of\nthe dom elements on the page without waiting for a dom onready event.\n\nThere are many more things you can do with bundling. Check out the bundling\nsection elsewhere in this document.\n\n## how browserify works\n\nBrowserify starts at the entry point files that you give it and searches for any\n`require()` calls it finds using\n[static analysis](http://npmjs.org/package/detective)\nof the source code's\n[abstract syntax tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree).\n\nFor every `require()` call with a string in it, browserify resolves those module\nstrings to file paths and then searches those file paths for `require()` calls\nrecursively until the entire dependency graph is visited.\n\nEach file is concatenated into a single javascript file with a minimal\n`require()` definition that maps the statically-resolved names to internal IDs.\n\nThis means that the bundle you generate is completely self-contained and has\neverything your application needs to work with a pretty negligible overhead.\n\nNote: If your `require()` contains anything other than a string literal (i.e. a variable) then it cannot be read at time of bundling, so the module being required will not be concatenated into your bundle and likely cause a runtime error.\n\nFor more details about how browserify works, check out the compiler pipeline\nsection of this document.\n\n## how node_modules works\n\nnode has a clever algorithm for resolving modules that is unique among rival\nplatforms.\n\nInstead of resolving packages from an array of system search paths like how\n`$PATH` works on the command line, node's mechanism is local by default.\n\nIf you `require('./foo.js')` from `/beep/boop/bar.js`, node will\nlook for `foo.js` in `/beep/boop`. Paths that start with a `./` or\n`../` are always local to the file that calls `require()`.\n\nIf however you require a non-relative name such as `require('xyz')` from\n`/beep/boop/foo.js`, node searches these paths in order, stopping at the first\nmatch and raising an error if nothing is found:\n\n```\n/beep/boop/node_modules/xyz\n/beep/node_modules/xyz\n/node_modules/xyz\n```\n\nFor each `xyz` directory that exists, node will first look for an\n`xyz/package.json` to see if a `\"main\"` field exists. The `\"main\"` field defines\nwhich file should take charge if you `require()` the directory path.\n\nFor example, if `/beep/node_modules/xyz` is the first match and\n`/beep/node_modules/xyz/package.json` has:\n\n```\n{\n  \"name\": \"xyz\",\n  \"version\": \"1.2.3\",\n  \"main\": \"lib/abc.js\"\n}\n```\n\nthen the exports from `/beep/node_modules/xyz/lib/abc.js` will be returned by\n`require('xyz')`.\n\nIf there is no `package.json` or no `\"main\"` field, `index.js` is assumed:\n\n```\n/beep/node_modules/xyz/index.js\n```\n\nIf you need to, you can reach into a package to pick out a particular file. For\nexample, to load the `lib/clone.js` file from the `dat` package, just do:\n\n```\nvar clone = require('dat/lib/clone.js')\n```\n\nThe recursive node_modules resolution will find the first `dat` package up the\ndirectory hierarchy, then the `lib/clone.js` file will be resolved from there.\nThis `require('dat/lib/clone.js')` approach will work from any location where\nyou can `require('dat')`.\n\nnode also has a mechanism for searching an array of paths, but this mechanism is\ndeprecated and you should be using `node_modules/` unless you have a very good\nreason not to.\n\nThe great thing about node's algorithm and how npm installs packages is that you\ncan never have a version conflict, unlike almost every other platform. npm\ninstalls the dependencies of each package into `node_modules`.\n\nEach library gets its own local `node_modules/` directory where its dependencies\nare stored and each dependency's dependencies has its own `node_modules/`\ndirectory, recursively all the way down.\n\nThis means that packages can successfully use different versions of libraries in\nthe same application, which greatly decreases the coordination overhead\nnecessary to iterate on APIs. This feature is very important for an ecosystem\nlike npm where there is no central authority to manage how packages are\npublished and organized. Everyone may simply publish as they see fit and not\nworry about how their dependency version choices might impact other dependencies\nincluded in the same application.\n\nYou can leverage how `node_modules/` works to organize your own local\napplication modules too. See the `avoiding ../../../../../../..` section for\nmore.\n\n## why concatenate\n\nBrowserify is a build step that you can run before deploying your code. It\ngenerates a single bundle file that has everything in it.\n\nHere are some other ways of implementing module systems for the browser and what\ntheir strengths and weaknesses are:\n\n### window globals\n\nInstead of a module system, each file defines properties on the window global\nobject or develops an internal namespacing scheme.\n\nThis approach does not scale well without extreme diligence since each new file\nneeds an additional `\u003cscript\u003e` tag in all of the html pages where the\napplication will be rendered. Further, the files tend to be very order-sensitive\nbecause some files need to be included before other files that expect globals to\nalready be present in the environment.\n\nIt can be difficult to refactor or maintain applications built this way.\nOn the plus side, all browsers natively support this approach and no server-side\ntooling is required.\n\nThis approach tends to be very slow since each `\u003cscript\u003e` tag initiates a\nnew round-trip http request.\n\n### concatenate\n\nInstead of window globals, all the scripts are concatenated beforehand on the\nserver. The code is still order-sensitive and difficult to maintain, but loads\nmuch faster because only a single http request for a single `\u003cscript\u003e` tag needs\nto execute.\n\nWithout source maps, exceptions thrown will have offsets that can't be easily\nmapped back to their original files.\n\n### AMD\n\nInstead of using `\u003cscript\u003e` tags, every file is wrapped with a `define()`\nfunction and callback. [This is AMD](http://requirejs.org/docs/whyamd.html). \n\nThe first argument is an array of modules to load that maps to each argument\nsupplied to the callback. Once all the modules are loaded, the callback fires.\n\n``` js\ndefine(['jquery'] , function ($) {\n    return function () {};\n});\n```\n\nYou can give your module a name in the first argument so that other modules can\ninclude it.\n\nThere is a commonjs sugar syntax that stringifies each callback and scans it for\n`require()` calls\n[with a regexp](https://github.com/requirejs/requirejs/blob/57c48253e42133a61075da67809b91ea34f89811/require.js#L16).\n\nCode written this way is much less order-sensitive than concatenation or globals\nsince the order is resolved by explicit dependency information.\n\nFor performance reasons, most of the time AMD is bundled server-side into a\nsingle file and during development it is more common to actually use the\nasynchronous feature of AMD.\n\n### bundling commonjs server-side\n\nIf you're going to have a build step for performance and a sugar syntax for\nconvenience, why not scrap the whole AMD business altogether and bundle\ncommonjs? With tooling you can resolve modules to address order-sensitivity and\nyour development and production environments will be much more similar and less\nfragile. The CJS syntax is nicer and the ecosystem is exploding because of node\nand npm.\n\nYou can seamlessly share code between node and the browser. You just need a\nbuild step and some tooling for source maps and auto-rebuilding.\n\nPlus, we can use node's module lookup algorithms to save us from version\nmismatch problems so that we can have multiple conflicting versions of different\nrequired packages in the same application and everything will still work. To\nsave bytes down the wire you can dedupe, which is covered elsewhere in this\ndocument.\n\n# development\n\nConcatenation has some downsides, but these can be very adequately addressed\nwith development tooling.\n\n## source maps\n\nBrowserify supports a `--debug`/`-d` flag and `opts.debug` parameter to enable\nsource maps. Source maps tell the browser to convert line and column offsets for\nexceptions thrown in the bundle file back into the offsets and filenames of the\noriginal sources.\n\nThe source maps include all the original file contents inline so that you can\nsimply put the bundle file on a web server and not need to ensure that all the\noriginal source contents are accessible from the web server with paths set up\ncorrectly.\n\n### exorcist\n\nThe downside of inlining all the source files into the inline source map is that\nthe bundle is twice as large. This is fine for debugging locally but not\npractical for shipping source maps to production. However, you can use\n[exorcist](https://npmjs.org/package/exorcist) to pull the inline source map out\ninto a separate `bundle.map.js` file:\n\n``` sh\nbrowserify main.js --debug | exorcist bundle.map.js \u003e bundle.js\n```\n\n## auto-recompile\n\nRunning a command to recompile your bundle every time can be slow and tedious.\nLuckily there are many tools to solve this problem. Some of these tools support\nlive-reloading to various degrees and others have a more traditional manual\nrefresh cycle.\n\nThese are just a few of the tools you can use, but there are many more on npm!\nThere are many different tools here that encompass many different tradeoffs and\ndevelopment styles. It can be a little bit more work up-front to find the tools\nthat resonate most strongly with your own personal expectations and experience,\nbut I think this diversity helps programmers to be more effective and provides\nmore room for creativity and experimentation. I think diversity in tooling and a\nsmaller browserify core is healthier in the medium to long term than picking a\nfew \"winners\" by including them in browserify core (which creates all kinds of\nhavoc in meaningful versioning and bitrot in core).\n\nThat said, here are a few modules you might want to consider for setting up a\nbrowserify development workflow. But keep an eye out for other tools not (yet)\non this list!\n\n### [watchify](https://npmjs.org/package/watchify)\n\nYou can use `watchify` interchangeably with `browserify` but instead of writing\nto an output file once, watchify will write the bundle file and then watch all\nof the files in your dependency graph for changes. When you modify a file, the\nnew bundle file will be written much more quickly than the first time because of\naggressive caching.\n\nYou can use `-v` to print a message every time a new bundle is written:\n\n```\n$ watchify browser.js -d -o static/bundle.js -v\n610598 bytes written to static/bundle.js  0.23s\n610606 bytes written to static/bundle.js  0.10s\n610597 bytes written to static/bundle.js  0.14s\n610606 bytes written to static/bundle.js  0.08s\n610597 bytes written to static/bundle.js  0.08s\n610597 bytes written to static/bundle.js  0.19s\n```\n\nHere is a handy configuration for using watchify and browserify with the\npackage.json \"scripts\" field:\n\n``` json\n{\n  \"build\": \"browserify browser.js -o static/bundle.js\",\n  \"watch\": \"watchify browser.js -o static/bundle.js --debug --verbose\",\n}\n```\n\nTo build the bundle for production do `npm run build` and to watch files for\nduring development do `npm run watch`.\n\n[Learn more about `npm run`][substack.net/task_automation_with_npm_run].\n\n### [beefy](https://www.npmjs.org/package/beefy)\n\nIf you would rather spin up a web server that automatically recompiles your code\nwhen you modify it, check out [beefy](http://didact.us/beefy/).\n\nJust give beefy an entry file:\n\n```\nbeefy main.js\n```\n\nand it will set up shop on an http port.\n\n### [wzrd](https://github.com/maxogden/wzrd)\n\nIn a similar spirit to beefy but in a more minimal form is\n[wzrd](https://github.com/maxogden/wzrd).\n\nJust `npm install -g wzrd` then you can do:\n\n```\nwzrd app.js\n```\n\nand open up http://localhost:9966 in your browser.\n\n### browserify-middleware, enchilada\n\nIf you are using express, check out\n[browserify-middleware](https://www.npmjs.org/package/browserify-middleware)\nor [enchilada](https://www.npmjs.org/package/enchilada).\n\nThey both provide middleware you can drop into an express application for\nserving browserify bundles.\n\n### [livereactload](https://github.com/milankinen/livereactload)\n\nlivereactload is a tool for [react](https://github.com/facebook/react)\nthat automatically updates your web page state when you modify your code.\n\nlivereactload is just an ordinary browserify transform that you can load with\n`-t livereactload`, but you should consult the\n[project readme](https://github.com/milankinen/livereactload#livereactload)\nfor more information.\n\n### [browserify-hmr](https://github.com/AgentME/browserify-hmr)\n\nbrowserify-hmr is a plugin for doing hot module replacement (hmr).\n\nFiles can mark themselves as accepting updates. If you modify a file that\naccepts updates of itself, or if you modify a dependency of a file that accepts\nupdates, then the file is re-executed with the new code.\n\nFor example, if we have a file, `main.js`:\n\n``` js\ndocument.body.textContent = require('./msg.js')\n\nif (module.hot) module.hot.accept()\n```\n\nand a file `msg.js`:\n\n``` js\nmodule.exports = 'hey'\n```\n\nWe can watch `main.js` for changes and load the `browserify-hmr` plugin:\n\n```\n$ watchify main.js -p browserify-hmr -o public/bundle.js -dv\n```\n\nand serve up the static file contents in `public/` with a static file server:\n\n```\n$ ecstatic public -p 8000\n```\n\nNow if we load `http://localhost:8000`, we see the message `hey` on the page.\n\nIf we change `msg.js` to be:\n\n``` js\nmodule.exports = 'wow'\n```\n\nthen a second later, the page updates to show `wow` all by itself.\n\nBrowserify-HMR can be used with\n[react-hot-transform](https://github.com/AgentME/react-hot-transform) to\nautomatically allow all React components to be updated live in addition to code\nusing the `module.hot` API. Unlike\n[livereactload](https://github.com/milankinen/livereactload), only modified\nfiles are re-executed instead of the whole bundle on each modification.\n\n### [budo](https://github.com/mattdesl/budo)\n\nbudo is a browserify development server with a stronger focus on incremental bundling and LiveReload integration (including CSS injection). \n\nInstall it like so:\n\n```sh\nnpm install budo -g\n```\n\nAnd run it on your entry file:\n\n```\nbudo app.js\n```\n\nThis starts the server at [http://localhost:9966](http://localhost:9966) with a default `index.html`, incrementally bundling your source on filesave. The requests are delayed until the bundle has finished, so you won't be served stale or empty bundles if you refresh the page mid-update.\n\nTo enable LiveReload and have the browser refresh on JS/HTML/CSS changes, you can run it like so:\n\n```\nbudo app.js --live\n```\n\n## using the api directly\n\nYou can just use the API directly from an ordinary `http.createServer()` for\ndevelopment too:\n\n``` js\nvar browserify = require('browserify');\nvar http = require('http');\n\nhttp.createServer(function (req, res) {\n    if (req.url === '/bundle.js') {\n        res.setHeader('content-type', 'application/javascript');\n        var b = browserify(__dirname + '/main.js').bundle();\n        b.on('error', console.error);\n        b.pipe(res);\n    }\n    else res.writeHead(404, 'not found')\n});\n```\n\n## grunt\n\nIf you use grunt, you'll probably want to use the\n[grunt-browserify](https://www.npmjs.org/package/grunt-browserify) plugin.\n\n## gulp\n\nIf you use gulp, you should use the browserify API directly.\n\nHere is\n[a guide for getting started](https://www.viget.com/articles/gulp-browserify-starter-faq)\nwith gulp and browserify.\n\nHere is a guide on how to [make browserify builds fast with watchify using\ngulp](https://github.com/gulpjs/gulp/blob/master/docs/recipes/fast-browserify-builds-with-watchify.md)\nfrom the official gulp recipes.\n\n# builtins\n\nIn order to make more npm modules originally written for node work in the\nbrowser, browserify provides many browser-specific implementations of node core\nlibraries:\n\n* [assert](https://npmjs.org/package/assert)\n* [buffer](https://npmjs.org/package/buffer)\n* [console](https://npmjs.org/package/console-browserify)\n* [constants](https://npmjs.org/package/constants-browserify)\n* [crypto](https://npmjs.org/package/crypto-browserify)\n* [domain](https://npmjs.org/package/domain-browser)\n* [events](https://npmjs.org/package/events)\n* [http](https://npmjs.org/package/http-browserify)\n* [https](https://npmjs.org/package/https-browserify)\n* [os](https://npmjs.org/package/os-browserify)\n* [path](https://npmjs.org/package/path-browserify)\n* [punycode](https://npmjs.org/package/punycode)\n* [querystring](https://npmjs.org/package/querystring)\n* [stream](https://npmjs.org/package/stream-browserify)\n* [string_decoder](https://npmjs.org/package/string_decoder)\n* [timers](https://npmjs.org/package/timers-browserify)\n* [tty](https://npmjs.org/package/tty-browserify)\n* [url](https://npmjs.org/package/url)\n* [util](https://npmjs.org/package/util)\n* [vm](https://npmjs.org/package/vm-browserify)\n* [zlib](https://npmjs.org/package/browserify-zlib)\n\nevents, stream, url, path, and querystring are particularly useful in a browser\nenvironment.\n\nAdditionally, if browserify detects the use of `Buffer`, `process`, `global`,\n`__filename`, or `__dirname`, it will include a browser-appropriate definition.\n\nSo even if a module does a lot of buffer and stream operations, it will probably\njust work in the browser, so long as it doesn't do any server IO.\n\nIf you haven't done any node before, here are some examples of what each of\nthose globals can do. Note too that these globals are only actually defined when\nyou or some module you depend on uses them.\n\n## [Buffer](http://nodejs.org/docs/latest/api/buffer.html)\n\nIn node all the file and network APIs deal with Buffer chunks. In browserify the\nBuffer API is provided by [buffer](https://www.npmjs.org/package/buffer), which\nuses augmented typed arrays in a very performant way with fallbacks for old\nbrowsers.\n\nHere's an example of using `Buffer` to convert a base64 string to hex:\n\n```\nvar buf = Buffer('YmVlcCBib29w', 'base64');\nvar hex = buf.toString('hex');\nconsole.log(hex);\n```\n\nThis example will print:\n\n```\n6265657020626f6f70\n```\n\n## [process](http://nodejs.org/docs/latest/api/process.html#process_process)\n\nIn node, `process` is a special object that handles information and control for\nthe running process such as environment, signals, and standard IO streams.\n\nOf particular consequence is the `process.nextTick()` implementation that\ninterfaces with the event loop.\n\nIn browserify the process implementation is handled by the\n[process module](https://www.npmjs.org/package/process) which just provides\n`process.nextTick()` and little else.\n\nHere's what `process.nextTick()` does:\n\n```\nsetTimeout(function () {\n    console.log('third');\n}, 0);\n\nprocess.nextTick(function () {\n    console.log('second');\n});\n\nconsole.log('first');\n```\n\nThis script will output:\n\n```\nfirst\nsecond\nthird\n```\n\n`process.nextTick(fn)` is like `setTimeout(fn, 0)`, but faster because\n`setTimeout` is artificially slower in javascript engines for compatibility reasons.\n\n## [global](http://nodejs.org/docs/latest/api/all.html#all_global)\n\nIn node, `global` is the top-level scope where global variables are attached\nsimilar to how `window` works in the browser. In browserify, `global` is just an\nalias for the `window` object.\n\n## [__filename](http://nodejs.org/docs/latest/api/all.html#all_filename)\n\n`__filename` is the path to the current file, which is different for each file.\n\nTo prevent disclosing system path information, this path is rooted at the\n`opts.basedir` that you pass to `browserify()`, which defaults to the\n[current working directory](https://en.wikipedia.org/wiki/Current_working_directory).\n\nIf we have a `main.js`:\n\n``` js\nvar bar = require('./foo/bar.js');\n\nconsole.log('here in main.js, __filename is:', __filename);\nbar();\n```\n\nand a `foo/bar.js`:\n\n``` js\nmodule.exports = function () {\n    console.log('here in foo/bar.js, __filename is:', __filename);\n};\n```\n\nthen running browserify starting at `main.js` gives this output:\n\n```\n$ browserify main.js | node\nhere in main.js, __filename is: /main.js\nhere in foo/bar.js, __filename is: /foo/bar.js\n```\n\n## [__dirname](http://nodejs.org/docs/latest/api/all.html#all_dirname)\n\n`__dirname` is the directory of the current file. Like `__filename`, `__dirname`\nis rooted at the `opts.basedir`.\n\nHere's an example of how `__dirname` works:\n\nmain.js:\n\n``` js\nrequire('./x/y/z/abc.js');\nconsole.log('in main.js __dirname=' + __dirname);\n```\n\nx/y/z/abc.js:\n\n``` js\nconsole.log('in abc.js, __dirname=' + __dirname);\n```\n\noutput:\n\n```\n$ browserify main.js | node\nin abc.js, __dirname=/x/y/z\nin main.js __dirname=/\n```\n\n# transforms\n\nInstead of browserify baking in support for everything, it supports a flexible\ntransform system that are used to convert source files in-place.\n\nThis way you can `require()` files written in coffee script or templates and\neverything will be compiled down to javascript.\n\nTo use [coffeescript](http://coffeescript.org/) for example, you can use the\n[coffeeify](https://www.npmjs.org/package/coffeeify) transform.\nMake sure you've installed coffeeify first with `npm install coffeeify` then do:\n\n```\n$ browserify -t coffeeify main.coffee \u003e bundle.js\n```\n\nor with the API you can do:\n\n```\nvar b = browserify('main.coffee');\nb.transform('coffeeify');\n```\n\nThe best part is, if you have source maps enabled with `--debug` or\n`opts.debug`, the bundle.js will map exceptions back into the original coffee\nscript source files. This is very handy for debugging with firebug or chrome\ninspector.\n\n## writing your own\n\nTransforms implement a simple streaming interface. Here is a transform that\nreplaces `$CWD` with the `process.cwd()`:\n\n``` js\nvar through = require('through2');\n\nmodule.exports = function (file) {\n    return through(function (buf, enc, next) {\n        this.push(buf.toString('utf8').replace(/\\$CWD/g, process.cwd()));\n        next();\n    });\n};\n```\n\nThe transform function fires for every `file` in the current package and returns\na transform stream that performs the conversion. The stream is written to and by\nbrowserify with the original file contents and browserify reads from the stream\nto obtain the new contents.\n\nSimply save your transform to a file or make a package and then add it with\n`-t ./your_transform.js`.\n\nFor more information about how streams work, check out the\n[stream handbook](https://github.com/substack/stream-handbook).\n\n# package.json\n\n## browser field\n\nYou can define a `\"browser\"` field in the package.json of any package that will\ntell browserify to override lookups for the main field and for individual\nmodules.\n\nIf you have a module with a main entry point of `main.js` for node but have a\nbrowser-specific entry point at `browser.js`, you can do:\n\n``` json\n{\n  \"name\": \"mypkg\",\n  \"version\": \"1.2.3\",\n  \"main\": \"main.js\",\n  \"browser\": \"browser.js\"\n}\n```\n\nNow when somebody does `require('mypkg')` in node, they will get the exports\nfrom `main.js`, but when they do `require('mypkg')` in a browser, they will get\nthe exports from `browser.js`.\n\nSplitting up whether you are in the browser or not with a `\"browser\"` field in\nthis way is greatly preferable to checking whether you are in a browser at\nruntime because you may want to load different modules based on whether you are\nin node or the browser. If the `require()` calls for both node and the browser\nare in the same file, browserify's static analysis will include everything\nwhether you use those files or not.\n\nYou can do more with the \"browser\" field as an object instead of a string.\n\nFor example, if you only want to swap out a single file in `lib/` with a\nbrowser-specific version, you could do:\n\n``` json\n{\n  \"name\": \"mypkg\",\n  \"version\": \"1.2.3\",\n  \"main\": \"main.js\",\n  \"browser\": {\n    \"lib/foo.js\": \"lib/browser-foo.js\"\n  }\n}\n```\n\nor if you want to swap out a module used locally in the package, you can do:\n\n``` json\n{\n  \"name\": \"mypkg\",\n  \"version\": \"1.2.3\",\n  \"main\": \"main.js\",\n  \"browser\": {\n    \"fs\": \"level-fs-browser\"\n  }\n}\n```\n\nYou can ignore files (setting their contents to the empty object) by setting\ntheir values in the browser field to `false`:\n\n``` json\n{\n  \"name\": \"mypkg\",\n  \"version\": \"1.2.3\",\n  \"main\": \"main.js\",\n  \"browser\": {\n    \"winston\": false\n  }\n}\n```\n\nThe browser field *only* applies to the current package. Any mappings you put\nwill not propagate down to its dependencies or up to its dependents. This\nisolation is designed to protect modules from each other so that when you\nrequire a module you won't need to worry about any system-wide effects it might\nhave. Likewise, you shouldn't need to worry about how your local configuration\nmight adversely affect modules far away deep into your dependency graph.\n\n## browserify.transform field\n\nYou can configure transforms to be automatically applied when a module is loaded\nin a package's `browserify.transform` field. For example, we can automatically\napply the [brfs](https://npmjs.org/package/brfs) transform with this\npackage.json:\n\n``` json\n{\n  \"name\": \"mypkg\",\n  \"version\": \"1.2.3\",\n  \"main\": \"main.js\",\n  \"browserify\": {\n    \"transform\": [ \"brfs\" ]\n  }\n}\n```\n\nNow in our `main.js` we can do:\n\n``` js\nvar fs = require('fs');\nvar src = fs.readFileSync(__dirname + '/foo.txt', 'utf8');\n\nmodule.exports = function (x) { return src.replace(x, 'zzz') };\n```\n\nand the `fs.readFileSync()` call will be inlined by brfs without consumers of\nthe module having to know. You can apply as many transforms as you like in the\ntransform array and they will be applied in order.\n\nLike the `\"browser\"` field, transforms configured in package.json will only\napply to the local package for the same reasons.\n\n### configuring transforms\n\nSometimes a transform takes configuration options on the command line. To apply these\nfrom package.json you can do the following.\n\n**on the command line**\n```\nbrowserify -t coffeeify \\\n           -t [ browserify-ngannotate --ext .coffee --bar ] \\\n           index.coffee \u003e index.js\n```\n\n**in package.json**\n``` json\n\"browserify\": {\n  \"transform\": [\n    \"coffeeify\",\n    [\"browserify-ngannotate\", {\"ext\": \".coffee\", \"bar\": true}]\n  ]\n}\n```\n\n\n# finding good modules\n\nHere are [some useful heuristics][substack.net/finding_modules]\nfor finding good modules on npm that work in the browser:\n\n* I can install it with npm\n\n* code snippet on the readme using require() - from a quick glance I should see\nhow to integrate the library into what I'm presently working on\n\n* has a very clear, narrow idea about scope and purpose\n\n* knows when to delegate to other libraries - doesn't try to do too many things itself\n\n* written or maintained by authors whose opinions about software scope,\nmodularity, and interfaces I generally agree with (often a faster shortcut\nthan reading the code/docs very closely)\n\n* inspecting which modules depend on the library I'm evaluating - this is baked\ninto the package page for modules published to npm\n\nOther metrics like number of stars on github, project activity, or a slick\nlanding page, are not as reliable.\n\n## module philosophy\n\nPeople used to think that exporting a bunch of handy utility-style things would\nbe the main way that programmers would consume code because that is the primary\nway of exporting and importing code on most other platforms and indeed still\npersists even on npm.\n\nHowever, this\n[kitchen-sink mentality](https://github.com/substack/node-mkdirp/issues/17)\ntoward including a bunch of thematically-related but separable functionality\ninto a single package appears to be an artifact for the difficulty of\npublishing and discovery in a pre-github, pre-npm era.\n\nThere are two other big problems with modules that try to export a bunch of\nfunctionality all in one place under the auspices of convenience: demarcation\nturf wars and finding which modules do what.\n\nPackages that are grab-bags of features\n[waste a ton of time policing boundaries](https://github.com/jashkenas/underscore/search?q=%22special-case%22\u0026ref=cmdform\u0026type=Issues)\nabout which new features belong and don't belong.\nThere is no clear natural boundary of the problem domain in this kind of package\nabout what the scope is, it's all\n[somebody's smug opinion](http://david.heinemeierhansson.com/2012/rails-is-omakase.html).\n\nNode, npm, and browserify are not that. They are avowedly à la carte,\nparticipatory, and would rather celebrate disagreement and the dizzying\nproliferation of new ideas and approaches than try to clamp down in the name of\nconformity, standards, or \"best practices\".\n\nNobody who needs to do gaussian blur ever thinks \"hmm I guess I'll start checking\ngeneric mathematics, statistics, image processing, and utility libraries to see\nwhich one has gaussian blur in it. Was it stats2 or image-pack-utils or\nmaths-extra or maybe underscore has that one?\"\nNo. None of this. Stop it. They `npm search gaussian` and they immediately see\n[ndarray-gaussian-filter](https://npmjs.org/package/ndarray-gaussian-filter) and\nit does exactly what they want and then they continue on with their actual\nproblem instead of getting lost in the weeds of somebody's neglected grand\nutility fiefdom.\n\n# organizing modules\n\n## avoiding ../../../../../../..\n\nNot everything in an application properly belongs on the public npm and the\noverhead of setting up a private npm or git repo is still rather large in many\ncases. Here are some approaches for avoiding the `../../../../../../../`\nrelative paths problem.\n\n### symlink\n\nThe simplest thing you can do is to symlink your app root directory into your\nnode_modules/ directory.\n\nDid you know that [symlinks work on windows\ntoo](http://www.howtogeek.com/howto/windows-vista/using-symlinks-in-windows-vista/)?\n\nTo link a `lib/` directory in your project root into `node_modules`, do:\n\n```\nln -s ../lib node_modules/app\n```\n\nand now from anywhere in your project you'll be able to require files in `lib/`\nby doing `require('app/foo.js')` to get `lib/foo.js`. \n\nOne caveat though: transformations such as `reactify` defined on the command line or in the main\n`package.json` are not applied to code required like this. You need to define\nthe transformations also in `lib/package.json`.\n\n### node_modules\n\nPeople sometimes object to putting application-specific modules into\nnode_modules because it is not obvious how to check in your internal modules\nwithout also checking in third-party modules from npm.\n\nThe answer is quite simple! If you have a `.gitignore` file that ignores\n`node_modules`:\n\n```\nnode_modules\n```\n\nYou can just add an exception with `!` for each of your internal application\nmodules:\n\n```\nnode_modules/*\n!node_modules/foo\n!node_modules/bar\n```\n\nPlease note that you can't *unignore* a subdirectory,\nif the parent is already ignored. So instead of ignoring `node_modules`,\nyou have to ignore every directory *inside* `node_modules` with the \n`node_modules/*` trick, and then you can add your exceptions.\n\nNow anywhere in your application you will be able to `require('foo')` or\n`require('bar')` without having a very large and fragile relative path.\n\nIf you have a lot of modules and want to keep them more separate from the\nthird-party modules installed by npm, you can just put them all under a\ndirectory in `node_modules` such as `node_modules/app`:\n\n```\nnode_modules/app/foo\nnode_modules/app/bar\n```\n\nNow you will be able to `require('app/foo')` or `require('app/bar')` from\nanywhere in your application.\n\nIn your `.gitignore`, just add an exception for `node_modules/app`:\n\n```\nnode_modules/*\n!node_modules/app\n```\n\nIf your application had transforms configured in package.json, you'll need to\ncreate a separate package.json with its own transform field in your\n`node_modules/foo` or `node_modules/app/foo` component directory because\ntransforms don't apply across module boundaries. This will make your modules\nmore robust against configuration changes in your application and it will be\neasier to independently reuse the packages outside of your application.\n\n### custom paths\n\nYou might see some places talk about using the `$NODE_PATH` environment variable\nor `opts.paths` to add directories for node and browserify to look in to find\nmodules.\n\nUnlike most other platforms, using a shell-style array of path directories with\n`$NODE_PATH` is not as favorable in node compared to making effective use of the\n`node_modules` directory.\n\nThis is because your application is more tightly coupled to a runtime\nenvironment configuration so there are more moving parts and your application\nwill only work when your environment is setup correctly.\n\nnode and browserify both support but discourage the use of `$NODE_PATH`.\n\n## non-javascript assets\n\nThere are many\n[browserify transforms](https://github.com/browserify/browserify/wiki/list-of-transforms)\nyou can use to do many things. Commonly, transforms are used to include\nnon-javascript assets into bundle files.\n\n### [brfs](https://www.npmjs.com/package/brfs)\n\nOne way of including any kind of asset that works in both node and the browser\nis brfs.\n\nbrfs uses static analysis to compile the results of `fs.readFile()` and\n`fs.readFileSync()` calls down to source contents at compile time.\n\nFor example, this `main.js`:\n\n``` js\nvar fs = require('fs');\nvar html = fs.readFileSync(__dirname + '/robot.html', 'utf8');\nconsole.log(html);\n```\n\napplied through brfs would become something like:\n\n``` js\nvar fs = require('fs');\nvar html = \"\u003cb\u003ebeep boop\u003c/b\u003e\";\nconsole.log(html);\n```\n\nwhen run through brfs.\n\nThis is handy because you can reuse the exact same code in node and the browser,\nwhich makes sharing modules and testing much simpler.\n\n`fs.readFile()` and `fs.readFileSync()` accept the same arguments as in node,\nwhich makes including inline image assets as base64-encoded strings very easy:\n\n``` js\nvar fs = require('fs');\nvar imdata = fs.readFileSync(__dirname + '/image.png', 'base64');\nvar img = document.createElement('img');\nimg.setAttribute('src', 'data:image/png;base64,' + imdata);\ndocument.body.appendChild(img);\n```\n\nIf you have some css you want to inline into your bundle, you can do that too\nwith the assistance of a module such as\n[insert-css](https://npmjs.org/package/insert-css):\n\n``` js\nvar fs = require('fs');\nvar insertStyle = require('insert-css');\n\nvar css = fs.readFileSync(__dirname + '/style.css', 'utf8');\ninsertStyle(css);\n```\n\nInserting css this way works fine for small reusable modules that you distribute\nwith npm because they are fully-contained, but if you want a more holistic\napproach to asset management using browserify, check out \n[atomify](https://www.npmjs.org/package/atomify) and\n[parcelify](https://www.npmjs.org/package/parcelify).\n\n### [hbsify](https://www.npmjs.com/package/hbsify)\n\n### [jadeify](https://www.npmjs.com/package/jadeify)\n\n### [reactify](https://www.npmjs.com/package/reactify)\n\n## reusable components\n\nPutting these ideas about code organization together, we can build a reusable UI\ncomponent that we can reuse across our application or in other applications.\n\nHere is a bare-bones example of an empty widget module:\n\n``` js\nmodule.exports = Widget;\n\nfunction Widget (opts) {\n    if (!(this instanceof Widget)) return new Widget(opts);\n    this.element = document.createElement('div');\n}\n\nWidget.prototype.appendTo = function (target) {\n    if (typeof target === 'string') target = document.querySelector(target);\n    target.appendChild(this.element);\n};\n```\n\nHandy javascript constructor tip: you can include a `this instanceof Widget`\ncheck like above to let people consume your module with `new Widget` or\n`Widget()`. It's nice because it hides an implementation detail from your API\nand you still get the performance benefits and indentation wins of using\nprototypes.\n\nTo use this widget, just use `require()` to load the widget file, instantiate\nit, and then call `.appendTo()` with a css selector string or a dom element.\n\nLike this:\n\n``` js\nvar Widget = require('./widget.js');\nvar w = Widget();\nw.appendTo('#container');\n```\n\nand now your widget will be appended to the DOM.\n\nCreating HTML elements procedurally is fine for very simple content but gets\nvery verbose and unclear for anything bigger. Luckily there are many transforms\navailable to ease importing HTML into your javascript modules.\n\nLet's extend our widget example using [brfs](https://npmjs.org/package/brfs). We\ncan also use [domify](https://npmjs.org/package/domify) to turn the string that\n`fs.readFileSync()` returns into an html dom element:\n\n``` js\nvar fs = require('fs');\nvar domify = require('domify');\n\nvar html = fs.readFileSync(__dirname + '/widget.html', 'utf8');\n\nmodule.exports = Widget;\n\nfunction Widget (opts) {\n    if (!(this instanceof Widget)) return new Widget(opts);\n    this.element = domify(html);\n}\n\nWidget.prototype.appendTo = function (target) {\n    if (typeof target === 'string') target = document.querySelector(target);\n    target.appendChild(this.element);\n};\n```\n\nand now our widget will load a `widget.html`, so let's make one:\n\n``` html\n\u003cdiv class=\"widget\"\u003e\n  \u003ch1 class=\"name\"\u003e\u003c/h1\u003e\n  \u003cdiv class=\"msg\"\u003e\u003c/div\u003e\n\u003c/div\u003e\n```\n\nIt's often useful to emit events. Here's how we can emit events using the\nbuilt-in `events` module and the [inherits](https://npmjs.org/package/inherits)\nmodule:\n\n``` js\nvar fs = require('fs');\nvar domify = require('domify');\nvar inherits = require('inherits');\nvar EventEmitter = require('events').EventEmitter;\n\nvar html = fs.readFileSync(__dirname + '/widget.html', 'utf8');\n\ninherits(Widget, EventEmitter);\nmodule.exports = Widget;\n\nfunction Widget (opts) {\n    if (!(this instanceof Widget)) return new Widget(opts);\n    this.element = domify(html);\n}\n\nWidget.prototype.appendTo = function (target) {\n    if (typeof target === 'string') target = document.querySelector(target);\n    target.appendChild(this.element);\n    this.emit('append', target);\n};\n```\n\nNow we can listen for `'append'` events on our widget instance:\n\n``` js\nvar Widget = require('./widget.js');\nvar w = Widget();\nw.on('append', function (target) {\n    console.log('appended to: ' + target.outerHTML);\n});\nw.appendTo('#container');\n```\n\nWe can add more methods to our widget to set elements on the html:\n\n``` js\nvar fs = require('fs');\nvar domify = require('domify');\nvar inherits = require('inherits');\nvar EventEmitter = require('events').EventEmitter;\n\nvar html = fs.readFileSync(__dirname + '/widget.html', 'utf8');\n\ninherits(Widget, EventEmitter);\nmodule.exports = Widget;\n\nfunction Widget (opts) {\n    if (!(this instanceof Widget)) return new Widget(opts);\n    this.element = domify(html);\n}\n\nWidget.prototype.appendTo = function (target) {\n    if (typeof target === 'string') target = document.querySelector(target);\n    target.appendChild(this.element);\n};\n\nWidget.prototype.setName = function (name) {\n    this.element.querySelector('.name').textContent = name;\n}\n\nWidget.prototype.setMessage = function (msg) {\n    this.element.querySelector('.msg').textContent = msg;\n}\n```\n\nIf setting element attributes and content gets too verbose, check out\n[hyperglue](https://npmjs.org/package/hyperglue).\n\nNow finally, we can toss our `widget.js` and `widget.html` into\n`node_modules/app-widget`. Since our widget uses the\n[brfs](https://npmjs.org/package/brfs) transform, we can create a `package.json`\nwith:\n\n``` json\n{\n  \"name\": \"app-widget\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"main\": \"widget.js\",\n  \"browserify\": {\n    \"transform\": [ \"brfs\" ]\n  },\n  \"dependencies\": {\n    \"brfs\": \"^1.1.1\",\n    \"inherits\": \"^2.0.1\"\n  }\n}\n```\n\nAnd now whenever we `require('app-widget')` from anywhere in our application,\nbrfs will be applied to our `widget.js` automatically!\nOur widget can even maintain its own dependencies. This way we can update\ndependencies in one widget without worrying about breaking changes cascading\nover into other widgets.\n\nMake sure to add an exclusion in your `.gitignore` for\n`node_modules/app-widget`:\n\n```\nnode_modules/*\n!node_modules/app-widget\n```\n\nYou can read more about [shared rendering in node and the\nbrowser][substack.net/shared_rendering_in_node_and_the_browser] if you\nwant to learn about sharing rendering logic between node and the browser using\nbrowserify and some streaming html libraries.\n\n# testing in node and the browser\n\nTesting modular code is very easy! One of the biggest benefits of modularity is\nthat your interfaces become much easier to instantiate in isolation and so it's\neasy to make automated tests.\n\nUnfortunately, few testing libraries play nicely out of the box with modules and\ntend to roll their own idiosyncratic interfaces with implicit globals and obtuse\nflow control that get in the way of a clean design with good separation.\n\nPeople also make a huge fuss about \"mocking\" but it's usually not necessary if\nyou design your modules with testing in mind. Keeping IO separate from your\nalgorithms, carefully restricting the scope of your module, and accepting\ncallback parameters for different interfaces can all make your code much easier\nto test.\n\nFor example, if you have a library that does both IO and speaks a protocol,\n[consider separating the IO layer from the\nprotocol](https://www.youtube.com/watch?v=g5ewQEuXjsQ#t=12m30)\nusing an interface like [streams](https://github.com/substack/stream-handbook).\n\nYour code will be easier to test and reusable in different contexts that you\ndidn't initially envision. This is a recurring theme of testing: if your code is\nhard to test, it is probably not modular enough or contains the wrong balance of\nabstractions. Testing should not be an afterthought, it should inform your\nwhole design and it will help you to write better interfaces.\n\n## testing libraries\n\n### [tape](https://npmjs.org/package/tape)\n\nTape was specifically designed from the start to work well in both node and\nbrowserify. Suppose we have an `index.js` with an async interface:\n\n``` js\nmodule.exports = function (x, cb) {\n    setTimeout(function () {\n        cb(x * 100);\n    }, 1000);\n};\n```\n\nHere's how we can test this module using [tape](https://npmjs.org/package/tape). \nLet's put this file in `test/beep.js`:\n\n``` js\nvar test = require('tape');\nvar hundreder = require('../');\n\ntest('beep', function (t) {\n    t.plan(1);\n    \n    hundreder(5, function (n) {\n        t.equal(n, 500, '5*100 === 500');\n    });\n});\n```\n\nBecause the test file lives in `test/`, we can require the `index.js` in the\nparent directory by doing `require('../')`. `index.js` is the default place that\nnode and browserify look for a module if there is no package.json in that\ndirectory with a `main` field.\n\nWe can `require()` tape like any other library after it has been installed with\n`npm install tape`.\n\nThe string `'beep'` is an optional name for the test.\nThe 3rd argument to `t.equal()` is a completely optional description.\n\nThe `t.plan(1)` says that we expect 1 assertion. If there are not enough\nassertions or too many, the test will fail. An assertion is a comparison\nlike `t.equal()`. tape has assertion primitives for:\n\n* t.equal(a, b) - compare a and b strictly with `===`\n* t.deepEqual(a, b) - compare a and b recursively\n* t.ok(x) - fail if `x` is not truthy\n\nand more! You can always add an additional description argument.\n\nRunning our module is very simple! To run the module in node, just run\n`node test/beep.js`:\n\n```\n$ node test/beep.js\nTAP version 13\n# beep\nok 1 5*100 === 500\n\n1..1\n# tests 1\n# pass  1\n\n# ok\n```\n\nThe output is printed to stdout and the exit code is 0.\n\nTo run our code in the browser, just do:\n\n```\n$ browserify test/beep.js \u003e bundle.js\n```\n\nthen plop `bundle.js` into a `\u003cscript\u003e` tag:\n\n```\n\u003cscript src=\"bundle.js\"\u003e\u003c/script\u003e\n```\n\nand load that html in a browser. The output will be in the debug console which\nyou can open with F12, ctrl-shift-j, or ctrl-shift-k depending on the browser.\n\nThis is a bit cumbersome to run our tests in a browser, but you can install the\n`testling` command to help. First do:\n\n```\nnpm install -g testling\n```\n\nAnd now just do `browserify test/beep.js | testling`:\n\n```\n$ browserify test/beep.js | testling\n\nTAP version 13\n# beep\nok 1 5*100 === 500\n\n1..1\n# tests 1\n# pass  1\n\n# ok\n```\n\n`testling` will launch a real browser headlessly on your system to run the tests.\n\nNow suppose we want to add another file, `test/boop.js`:\n\n``` js\nvar test = require('tape');\nvar hundreder = require('../');\n\ntest('fraction', function (t) {\n    t.plan(1);\n\n    hundreder(1/20, function (n) {\n        t.equal(n, 5, '1/20th of 100');\n    });\n});\n\ntest('negative', function (t) {\n    t.plan(1);\n\n    hundreder(-3, function (n) {\n        t.equal(n, -300, 'negative number');\n    });\n});\n```\n\nHere our test has 2 `test()` blocks. The second test block won't start to\nexecute until the first is completely finished, even though it is asynchronous.\nYou can even nest test blocks by using `t.test()`.\n\nWe can run `test/boop.js` with node directly as with `test/beep.js`, but if we\nwant to run both tests, there is a minimal command-runner we can use that comes\nwith tape. To get the `tape` command do:\n\n```\nnpm install -g tape\n```\n\nand now you can run:\n\n```\n$ tape test/*.js\nTAP version 13\n# beep\nok 1 5*100 === 500\n# fraction\nok 2 1/20th of 100\n# negative\nok 3 negative number\n\n1..3\n# tests 3\n# pass  3\n\n# ok\n```\n\nand you can just pass `test/*.js` to browserify to run your tests in the\nbrowser:\n\n```\n$ browserify test/* | testling\n\nTAP version 13\n# beep\nok 1 5*100 === 500\n# fraction\nok 2 1/20th of 100\n# negative\nok 3 negative number\n\n1..3\n# tests 3\n# pass  3\n\n# ok\n```\n\nPutting together all these steps, we can configure `package.json` with a test\nscript:\n\n``` json\n{\n  \"name\": \"hundreder\",\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"devDependencies\": {\n    \"tape\": \"^2.13.1\",\n    \"testling\": \"^1.6.1\"\n  },\n  \"scripts\": {\n    \"test\": \"tape test/*.js\",\n    \"test-browser\": \"browserify test/*.js | testlingify\"\n  }\n}\n```\n\nNow you can do `npm test` to run the tests in node and `npm run test-browser` to\nrun the tests in the browser. You don't need to worry about installing commands\nwith `-g` when you use `npm run`: npm automatically sets up the `$PATH` for all\npackages installed locally to the project.\n\nIf you have some tests that only run in node and some tests that only run in the\nbrowser, you could have subdirectories in `test/` such as `test/server` and\n`test/browser` with the tests that run both places just in `test/`. Then you\ncould just add the relevant directory to the globs:\n\n``` json\n{\n  \"name\": \"hundreder\",\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"devDependencies\": {\n    \"tape\": \"^2.13.1\",\n    \"testling\": \"^1.6.1\"\n  },\n  \"scripts\": {\n    \"test\": \"tape test/*.js test/server/*.js\",\n    \"test-browser\": \"browserify test/*.js test/browser/*.js | testling\"\n  }\n}\n```\n\nand now server-specific and browser-specific tests will be run in addition to\nthe common tests.\n\nIf you want something even slicker, check out\n[prova](https://www.npmjs.org/package/prova) once you have gotten the basic\nconcepts.\n\n### assert\n\nThe core assert module is a fine way to write simple tests too, although it can\nsometimes be tricky to ensure that the correct number of callbacks have fired.\n\nYou can solve that problem with tools like\n[macgyver](https://www.npmjs.org/package/macgyver) but it is appropriately DIY.\n\n## code coverage\n\n### coverify\n\nA simple way to check code coverage in browserify is to use the\n[coverify](https://npmjs.org/package/coverify) transform.\n\n```\n$ browserify -t coverify test/*.js | node | coverify\n```\n\nor to run your tests in a real browser:\n\n```\n$ browserify -t coverify test/*.js | testling | coverify\n```\n\ncoverify works by transforming the source of each package so that each\nexpression is wrapped in a `__coverageWrap()` function.\n\nEach expression in the program gets a unique ID and the `__coverageWrap()`\nfunction will print `COVERED $FILE $ID` the first time the expression is\nexecuted.\n\nBefore the expressions run, coverify prints a `COVERAGE $FILE $NODES` message to\nlog the expression nodes across the entire file as character ranges.\n\nHere's what the output of a full run looks like:\n\n```\n$ browserify -t coverify test/whatever.js | node\nCOVERAGE \"/home/substack/projects/defined/test/whatever.js\" [[14,28],[14,28],[0,29],[41,56],[41,56],[30,57],[95,104],[95,105],[126,146],[126,146],[115,147],[160,194],[160,194],[152,195],[200,217],[200,218],[76,220],[59,221],[59,222]]\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 2\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 1\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 0\nCOVERAGE \"/home/substack/projects/defined/index.js\" [[48,49],[55,71],[51,71],[73,76],[92,104],[92,118],[127,139],[120,140],[172,195],[172,196],[0,204],[0,205]]\nCOVERED \"/home/substack/projects/defined/index.js\" 11\nCOVERED \"/home/substack/projects/defined/index.js\" 10\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 5\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 4\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 3\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 18\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 17\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 16\nTAP version 13\n# whatever\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 7\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 6\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 10\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 9\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 8\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 13\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 12\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 11\nCOVERED \"/home/substack/projects/defined/index.js\" 0\nCOVERED \"/home/substack/projects/defined/index.js\" 2\nCOVERED \"/home/substack/projects/defined/index.js\" 1\nCOVERED \"/home/substack/projects/defined/index.js\" 5\nCOVERED \"/home/substack/projects/defined/index.js\" 4\nCOVERED \"/home/substack/projects/defined/index.js\" 3\nCOVERED \"/home/substack/projects/defined/index.js\" 7\nCOVERED \"/home/substack/projects/defined/index.js\" 6\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 15\nCOVERED \"/home/substack/projects/defined/test/whatever.js\" 14\nok 1 should be equal\n\n1..1\n# tests 1\n# pass  1\n\n# ok\n```\n\nThese COVERED and COVERAGE statements are just printed on stdout and they can be\nfed into the `coverify` command to generate prettier output:\n\n```\n$ browserify -t coverify test/whatever.js | node | coverify\nTAP version 13\n# whatever\nok 1 should be equal\n\n1..1\n# tests 1\n# pass  1\n\n# ok\n\n# /home/substack/projects/defined/index.js: line 6, column 9-32\n\n          console.log('whatever');\n          ^^^^^^^^^^^^^^^^^^^^^^^^\n\n# coverage: 30/31 (96.77 %)\n```\n\nTo include code coverage into your project, you can add an entry into the\n`package.json` scripts field:\n\n``` json\n{\n  \"scripts\": {\n    \"test\": \"tape test/*.js\",\n    \"coverage\": \"browserify -t coverify test/*.js | node | coverify\"\n  }\n}\n```\n\nThere is also a [covert](https://npmjs.com/package/covert) package that\nsimplifies the browserify and coverify setup:\n\n``` json\n{\n  \"scripts\": {\n    \"test\": \"tape test/*.js\",\n    \"coverage\": \"covert test/*.js\"\n  }\n}\n```\n\nTo install coverify or covert as a devDependency, run\n`npm install -D coverify` or `npm install -D covert`.\n\n# bundling\n\nThis section covers bundling in more detail.\n\nBundling is the step where starting from the entry files, all the source files\nin the dependency graph are walked and packed into a single output file.\n\n## saving bytes\n\nOne of the first things you'll want to tweak is how the files that npm installs\nare placed on disk to avoid duplicates.\n\nWhen you do a clean install in a directory, npm will ordinarily factor out\nsimilar versions into the topmost directory where 2 modules share a dependency.\nHowever, as you install more packages, new packages will not be factored out\nautomatically. You can however use the `npm dedupe` command to factor out\npackages for an already-installed set of packages in `node_modules/`. You could\nalso remove `node_modules/` and install from scratch again if problems with\nduplicates persist.\n\nbrowserify will not include the same exact file twice, but compatible versions\nmay differ slightly. browserify is also not version-aware, it will include the\nversions of packages exactly as they are laid out in `node_modules/` according\nto the `require()` algorithm that node uses.\n\nYou can use the `browserify --list` and `browserify --deps` commands to further\ninspect which files are being included to scan for duplicates.\n\n## tinyify\n\nYou can use the [tinyify](https://github.com/browserify/tinyify) plugin to apply\na decent set of zero-config optimizations to your bundle. It will drastically\nreduce output size.\n\n```\n$ browserify foo.js --plugin tinyify \u003e bundle.js\n```\n\ntinyify includes [browser-pack-flat](https://github.com/goto-bus-stop/browser-pack-flat),\nwhich does not follow the Node module loading behaviour as closely as the\ndefault [browser-pack](https://github.com/browserify/browser-pack) does. If\nthere are timing issues in your tinyified bundle output, you can add the\n`--no-flat` flag to revert to the default behaviour:\n\n```\n$ browserify foo.js --plugin [ tinyify --no-flat ] \u003e bundle.js\n```\n\nAll kinds of other optimizations will still be applied so you should still see\nvery significant bundle size wins.\n\n## standalone\n\nYou can generate UMD bundles with `--standalone` that will work in node, the\nbrowser with globals, and AMD environments.\n\nJust add `--standalone NAME` to your bundle command:\n\n```\n$ browserify foo.js --standalone xyz \u003e bundle.js\n```\n\nThis command will export the contents of `foo.js` under the external module name\n`xyz`. If a module system is detected in the host environment, it will be used.\nOtherwise a window global named `xyz` will be exported.\n\nYou can use dot-syntax to specify a namespace hierarchy:\n\n```\n$ browserify foo.js --standalone foo.bar.baz \u003e bundle.js\n```\n\nIf there is already a `foo` or a `foo.bar` in the host environment in window\nglobal mode, browserify will attach its exports onto those objects. The AMD and\n`module.exports` modules will behave the same.\n\nNote however that standalone only works with a single entry or directly-required\nfile.\n\n## external bundles\n\n## ignoring and excluding\n\nIn browserify parlance, \"ignore\" means: replace the definition of a module with\nan empty object. \"exclude\" means: remove a module completely from a dependency graph.\n\nAnother way to achieve many of the same goals as ignore and exclude is the\n\"browser\" field in package.json, which is covered elsewhere in this document.\n\n### ignoring\n\nIgnoring is an optimistic strategy designed to stub in an empty definition for\nnode-specific modules that are only used in some code paths. For example, if a\nmodule requires a library that only works in node but for a specific chunk of\nthe code:\n\n``` js\nvar fs = require('fs');\nvar path = require('path');\nvar mkdirp = require('mkdirp');\n\nexports.convert = convert;\nfunction convert (src) {\n    return src.replace(/beep/g, 'boop');\n}\n\nexports.write = function (src, dst, cb) {\n    fs.readFile(src, function (err, src) {\n        if (err) return cb(err);\n        mkdirp(path.dirname(dst), function (err) {\n            if (err) return cb(err);\n            var out = convert(src);\n            fs.writeFile(dst, out, cb);\n        });\n    });\n};\n```\n\nbrowserify already \"ignores\" the `'fs'` module by returning an empty object, but\nthe `.write()` function here won't work in the browser without an extra step like\na static analysis transform or a runtime storage fs abstraction.\n\nHowever, if we really want the `convert()` function but don't want to see\n`mkdirp` in the final bundle, we can ignore mkdirp with `b.ignore('mkdirp')` or\n`browserify --ignore mkdirp`. The code will still work in the browser if we\ndon't call `write()` because `require('mkdirp')` won't throw an exception, just\nreturn an empty object.\n\nGenerally speaking it's not a good idea for modules that are primarily\nalgorithmic (parsers, formatters) to do IO themselves but these tricks can let\nyou use those modules in the browser anyway.\n\nTo ignore `foo` on the command-line do:\n\n```\nbrowserify --ignore foo\n```\n\nTo ignore `foo` from the api with some bundle instance `b` do:\n\n``` js\nb.ignore('foo')\n```\n\n### excluding\n\nAnother related thing we might want is to completely remove a module from the\noutput so that `require('modulename')` will fail at runtime. This is useful if\nwe want to split things up into multiple bundles that will defer in a cascade to\npreviously-defined `require()` definitions.\n\nFor example, if we have a vendored standalone bundle for jquery that we don't want to appear in\nthe primary bundle:\n\n```\n$ npm install jquery\n$ browserify -r jquery \u003e jquery-bundle.js\n```\n\nthen we want to just `require('jquery')` in a `main.js`:\n\n``` js\nvar $ = require('jquery');\n$(window).click(function () { document.body.bgColor = 'red' });\n```\n\ndefering to the jquery dist bundle so that we can write:\n\n``` html\n\u003cscript src=\"jquery-bundle.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"bundle.js\"\u003e\u003c/script\u003e\n```\n\nand not have the jquery definition show up in `bundle.js`, then while compiling\nthe `main.js`, you can `--exclude jquery`:\n\n```\nbrowserify main.js --exclude jquery \u003e bundle.js\n```\n\nTo exclude `foo` on the command-line do:\n\n```\nbrowserify --exclude foo\n```\n\nTo exclude `foo` from the api with some bundle instance `b` do:\n\n``` js\nb.exclude('foo')\n```\n\n## browserify cdn\n\n# shimming\n\nUnfortunately, some packages are not written with node-style commonjs exports.\nFor modules that export their functionality with globals or AMD, there are\npackages that can help automatically convert these troublesome packages into\nsomething that browserify can understand.\n\n## browserify-shim\n\nOne way to automatically convert non-commonjs packages is with\n[browserify-shim](https://npmjs.org/package/browserify-shim).\n\n[browserify-shim](https://npmjs.org/package/browserify-shim) is loaded as a\ntransform and also reads a `\"browserify-shim\"` field from `package.json`.\n\nSuppose we need to use a troublesome third-party library we've placed in\n`./vendor/foo.js` that exports its functionality as a window global called\n`FOO`. We can set up our `package.json` with:\n\n``` json\n{\n  \"browserify\": {\n    \"transform\": \"browserify-shim\"\n  },\n  \"browserify-shim\": {\n    \"./vendor/foo.js\": \"FOO\"\n  }\n}\n```\n\nand now when we `require('./vendor/foo.js')`, we get the `FOO` variable that\n`./vendor/foo.js` tried to put into the global scope, but that attempt was\nshimmed away into an isolated context to prevent global pollution.\n\nWe could even use the [browser field](#browser-field) to make `require('foo')`\nwork instead of always needing to use a relative path to load `./vendor/foo.js`:\n\n``` json\n{\n  \"browser\": {\n    \"foo\": \"./vendor/foo.js\"\n  },\n  \"browserify\": {\n    \"transform\": \"browserify-shim\"\n  },\n  \"browserify-shim\": {\n    \"foo\": \"FOO\"\n  }\n}\n```\n\nNow `require('foo')` will return the `FOO` export that `./vendor/foo.js` tried\nto place on the global scope.\n\n# partitioning\n\nMost of the time, the default method of bundling where one or more entry files\nmap to a single bundled output file is perfectly adequate, particularly\nconsidering that bundling minimizes latency down to a single http request to\nfetch all the javascript assets.\n\nHowever, sometimes this initial penalty is too high for parts of a website that\nare rarely or never used by most visitors such as an admin panel.\nThis partitioning can be accomplished with the technique covered in the\n[ignoring and excluding](#ignoring-and-excluding) section, but factoring out\nshared dependencies manually can be tedious for a large and fluid dependency\ngraph.\n\nLuckily, there are plugins that can automatically factor browserify output into\nseparate bundle payloads.\n\n## factor-bundle\n\n[factor-bundle](https://www.npmjs.org/package/factor-bundle) splits browserify\noutput into multiple bundle targets based on entry-point. For each entry-point,\nan entry-specific output file is built. Files that are needed by two or more of\nthe entry files get factored out into a common bundle.\n\nFor example, suppose we have 2 pages: /x and /y. Each page has an entry point,\n`x.js` for /x and `y.js` for /y.\n\nWe then generate page-specific bundles `bundle/x.js` and `bundle/y.js` with\n`bundle/common.js` containing the dependencies shared by both `x.js` and `y.js`:\n\n```\nbrowserify x.js y.js -p [ factor-bundle -o bundle/x.js -o bundle/y.js ] \\\n  -o bundle/common.js\n```\n\nNow we can simply put 2 script tags on each page. On /x we would put:\n\n``` html\n\u003cscript src=\"/bundle/common.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"/bundle/x.js\"\u003e\u003c/script\u003e\n```\n\nand on page /y we would put:\n\n``` html\n\u003cscript src=\"/bundle/common.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"/bundle/y.js\"\u003e\u003c/script\u003e\n```\n\nYou could also load the bundles asynchronously with ajax or by inserting a\nscript tag into the page dynamically but factor-bundle only concerns itself with\ngenerating the bundles, not with loading them.\n\n## partition-bundle\n\n[partition-bundle](https://www.npmjs.org/package/partition-bundle) handles\nsplitting output into multiple bundles like factor-bundle, but includes a\nbuilt-in loader using a special `loadjs()` function.\n\npartition-bundle takes a json file that maps source files to bundle files:\n\n```\n{\n  \"entry.js\": [\"./a\"],\n  \"common.js\": [\"./b\"],\n  \"common/extra.js\": [\"./e\", \"./d\"]\n}\n```\n\nThen partition-bundle is loaded as a plugin and the mapping file, output\ndirectory, and destination url path (required for dynamic loading) are passed\nin:\n\n```\nbrowserify -p [ partition-bundle --map mapping.json \\\n  --output output/directory --url directory ]\n```\n\nNow you can add:\n\n``` html\n\u003cscript src=\"entry.js\"\u003e\u003c/script\u003e\n```\n\nto your page to load the entry file. From inside the entry file, you can\ndynamically load other bundles with a `loadjs()` function:\n\n``` js\na.addEventListener('click', function() {\n  loadjs(['./e', './d'], function(e, d) {\n    console.log(e, d);\n  });\n});\n```\n\n# compiler pipeline\n\nSince version 5, browserify exposes its compiler pipeline as a\n[labeled-stream-splicer](https://www.npmjs.org/package/labeled-stream-splicer).\n\nThis means that transformations can be added or removed directly into the\ninternal pipeline. This pipeline provides a clean interface for advanced\ncustomizations such as watching files or factoring bundles from multiple entry\npoints. \n\nFor example, we could replace the built-in integer-based labeling mechanism with\nhashed IDs by first injecting a pass-through transform after the \"deps\" have\nbeen calculated to hash source files. Then we can use the hashes we captured to\ncreate our own custom labeler, replacing the built-in \"label\" transform:\n\n``` js\nvar browserify = require('browserify');\nvar through = require('through2');\nvar shasum = require('shasum');\n\nvar b = browserify('./main.js');\n\nvar hashes = {};\nvar hasher = through.obj(function (row, enc, next) {\n    hashes[row.id] = shasum(row.source);\n    this.push(row);\n    next();\n});\nb.pipeline.get('deps').push(hasher);\n\nvar labeler = through.obj(function (row, enc, next) {\n    row.id = hashes[row.id];\n    \n    Object.keys(row.deps).forEach(function (key) {\n        row.deps[key] = hashes[row.deps[key]];\n    });\n    \n    this.push(row);\n    next();\n});\nb.pipeline.get('label').splice(0, 1, labeler);\n\nb.bundle().pipe(process.stdout);\n```\n\nNow instead of getting integers for the IDs in the output format, we get file\nhashes:\n\n```\n$ node bundle.js\n(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"\u0026\u0026require;if(!u\u0026\u0026a)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\"\u0026\u0026require;for(var o=0;o\u003cr.length;o++)s(r[o]);return s})({\"5f0a0e3a143f2356582f58a70f385f4bde44f04b\":[function(require,module,exports){\nvar foo = require('./foo.js');\nvar bar = require('./bar.js');\n\nconsole.log(foo(3) + bar(4));\n\n},{\"./bar.js\":\"cba5983117ae1d6699d85fc4d54eb589d758f12b\",\"./foo.js\":\"736100869ec2e44f7cfcf0dc6554b055e117c53c\"}],\"cba5983117ae1d6699d85fc4d54eb589d758f12b\":[function(require,module,exports){\nmodule.exports = function (n) { return n * 100 };\n\n},{}],\"736100869ec2e44f7cfcf0dc6554b055e117c53c\":[function(require,module,exports){\nmodule.exports = function (n) { return n + 1 };\n\n},{}]},{},[\"5f0a0e3a143f2356582f58a70f385f4bde44f04b\"]);\n```\n\nNote that the built-in labeler does other things like checking for the external,\nexcluded configurations so replacing it will be difficult if you depend on those\nfeatures. This example just serves as an example for the kinds of things you can\ndo by hacking into the compiler pipeline.\n\n## build your own browserify\n\n## labeled phases\n\nEach phase in the browserify pipeline has a label that you can hook onto. Fetch\na label with `.get(name)` to return a\n[labeled-stream-splicer](https://npmjs.org/package/labeled-stream-splicer)\nhandle at the appropriate label. Once you have a handle, you can `.push()`,\n`.pop()`, `.shift()`, `.unshift()`, and `.splice()` your own transform streams\ninto the pipeline or remove existing transform streams.\n\n### record\n\nThe recorder is used to capture the inputs sent to the `deps` phase so that they\ncan be replayed on subsequent calls to `.bundle()`. Unlike in previous releases,\nv5 can generate bundle output multiple times. This is very handy for tools like\nwatchify that re-bundle when a file has changed.\n\n### deps\n\nThe `deps` phase expects entry and `require()` files or objects as input and\ncalls [module-deps](https://npmjs.org/package/module-deps) to generate a stream\nof json output for all of the files in the dependency graph.\n\nmodule-deps is invoked with some customizations here such as:\n\n* setting up the browserify transform key for package.json\n* filtering out external, excluded, and ignored files\n* setting the default extensions for `.js` and `.json` plus options configured\nin the `opts.extensions` parameter in the browserify constructor\n* configuring a global [insert-module-globals](https://github.com/browserify/insert-module-globals)\ntransform to detect and implement `process`, `Buffer`, `global`, `__dirname`,\nand `__filename`\n* setting up the list of node builtins which are shimmed by browserify\n\n### json\n\nThis transform adds `module.exports=` in front of files with a `.json`\nextension.\n\n### unbom\n\nThis transform removes byte order markers, which are sometimes used by windows\ntext editors to indicate the endianness of files. These markers are ignored by\nnode, so browserify ignores them for compatibility.\n\n### syntax\n\nThis transform checks for syntax errors using the\n[syntax-error](https://npmjs.org/package/syntax-error) package to give\ninformative syntax errors with line and column numbers.\n\n### sort\n\nThis phase uses [deps-sort](https://www.npmjs.org/package/deps-sort) to sort\nthe rows written to it in order to make the bundles deterministic.\n\n### dedupe\n\nThe transform at this phase uses dedupe information provided by\n[deps-sort](https://www.npmjs.org/package/deps-sort) in the `sort` phase to\nremove files that have duplicate contents. \n\n### label\n\nThis phase converts file-based IDs which might expose system path information\nand inflate the bundle size into integer-based IDs.\n\nThe `label` phase will also normalize path names based on the `opts.basedir` or\n`process.cwd()` to avoid exposing system path information.\n\n### emit-deps\n\nThis phase emits a `'dep'` event for each row after the `label` phase.\n\n### debug\n\nIf `opts.debug` was given to the `browserify()` constructor, this phase will\ntransform input to add `sourceRoot` and `sourceFile` properties which are used\nby [browser-pack](https://npmjs.org/package/browser-pack) in the `pack` phase.\n\n### pack\n\nThis phase converts rows with `'id'` and `'source'` parameters as input (among\nothers) and generates the concatenated javascript bundle as output\nusing [browser-pack](https://npmjs.org/package/browser-pack).\n\n### wrap\n\nThis is an empty phase at the end where you can easily tack on custom post\ntransformations without interfering with existing mechanics.\n\n## browser-unpack\n\n[browser-unpack](https://npmjs.org/package/browser-unpack) converts a compiled\nbundle file back into a format very similar to the output of\n[module-deps](https://npmjs.org/package/module-deps).\n\nThis is very handy if you need to inspect or transform a bundle that has already\nbeen compiled.\n\nFor example:\n\n``` js\n$ browserify src/main.js | browser-unpack\n[\n{\"id\":1,\"source\":\"module.exports = function (n) { return n * 100 };\",\"deps\":{}}\n,\n{\"id\":2,\"source\":\"module.exports = function (n) { return n + 1 };\",\"deps\":{}}\n,\n{\"id\":3,\"source\":\"var foo = require('./foo.js');\\nvar bar = require('./bar.js');\\n\\nconsole.log(foo(3) + bar(4));\",\"deps\":{\"./bar.js\":1,\"./foo.js\":2},\"entry\":true}\n]\n```\n\nThis decomposition is needed by tools such as\n[factor-bundle](https://www.npmjs.org/package/factor-bundle)\nand [bundle-collapser](https://www.npmjs.org/package/bundle-collapser).\n\n# plugins\n\nWhen loaded, plugins have access to the browserify instance itself.\n\n## using plugins\n\nPlugins should be used sparingly and only in cases where a transform or global\ntransform is not powerful enough to perform the desired functionality.\n\nYou can load a plugin with `-p` on the command-line:\n\n```\n$ browserify main.js -p foo \u003e bundle.js\n```\n\nwould load a plugin called `foo`. `foo` is resolved with `require()`, so to load\na local file as a plugin, preface the path with a `./` and to load a plugin from\n`node_modules/foo`, just do `-p foo`.\n\nYou can pass options to plugins with square brackets around the entire plugin\nexpression, including the plugin name as the first argument:\n\n```\n$ browserify one.js two.js \\\n  -p [ factor-bundle -o bundle/one.js -o bundle/two.js ] \\\n  \u003e common.js\n```\n\nThis command-line syntax is parsed by the\n[subarg](https://npmjs.org/package/subarg) package.\n\nTo see a list of browserify plugins, browse npm for packages with the keyword\n\"browserify-plugin\": http://npmjs.org/browse/keyword/browserify-plugin\n\n## authoring plugins\n\nTo author a plugin, write a package that exports a single function that will\nreceive a bundle instance and options object as arguments:\n\n``` js\n// example plugin\n\nmodule.exports = function (b, opts) {\n  // ...\n}\n```\n\nPlugins operate on the bundle instance `b` directly by listening for events or\nsplicing transforms into the pipeline. Plugins should not overwrite bundle\nmethods unless they have a very good reason.\n\n[substack.net/finding_modules]: https://web.archive.org/web/20180624204219/https://substack.net/finding_modules\n[substack.net/task_automation_with_npm_run]: https://web.archive.org/web/20180624203804/http://substack.net/task_automation_with_npm_run\n[substack.net/shared_rendering_in_node_and_the_browser]: https://web.archive.org/web/20180624204233/http://substack.net/shared_rendering_in_node_and_the_browser\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrowserify%2Fbrowserify-handbook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrowserify%2Fbrowserify-handbook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrowserify%2Fbrowserify-handbook/lists"}