1 | # browserify-shim [![build status](https://secure.travis-ci.org/thlorenz/browserify-shim.svg?branch=master)](http://travis-ci.org/thlorenz/browserify-shim)
|
2 |
|
3 | ### Make CommonJS-Incompatible Files Browserifyable
|
4 |
|
5 | #### package.json
|
6 |
|
7 | ```json
|
8 | {
|
9 | "main": "./js/entry.js",
|
10 | "browser": {
|
11 | "jquery": "./js/vendor/jquery.js"
|
12 | },
|
13 | "browserify-shim": {
|
14 | "jquery": "$",
|
15 | "three": "global:THREE"
|
16 | },
|
17 | "browserify": {
|
18 | "transform": [ "browserify-shim" ]
|
19 | },
|
20 | "dependencies": {
|
21 | "browserify-shim": "~3.2.0"
|
22 | }
|
23 | }
|
24 | ```
|
25 |
|
26 | browserify . -d -o bundle.js
|
27 |
|
28 |
|
29 |
|
30 | **Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)*
|
31 |
|
32 | - [Installation](#installation)
|
33 | - [Features](#features)
|
34 | - [API](#api)
|
35 | - [You Will Always](#you-will-always)
|
36 | - [1. Install browserify-shim dependency](#1-install-browserify-shim-dependency)
|
37 | - [2. Register browserify-shim as a transform with browserify](#2-register-browserify-shim-as-a-transform-with-browserify)
|
38 | - [3. Provide browserify-shim config](#3-provide-browserify-shim-config)
|
39 | - [Short Form vs. Long Form config](#short-form-vs-long-form-config)
|
40 | - [You will sometimes](#you-will-sometimes)
|
41 | - [a) Expose global variables via `global:*`](#a-expose-global-variables-via-global)
|
42 | - [1. add script tag for library you want to expose](#1-add-script-tag-for-library-you-want-to-expose)
|
43 | - [2. Add expose global config to `package.json`](#2-add-expose-global-config-to-packagejson)
|
44 | - [2.a. Add expose global config to external shim config](#2a-add-expose-global-config-to-external-shim-config)
|
45 | - [3. Require library by the name it was exposed as](#3-require-library-by-the-name-it-was-exposed-as)
|
46 | - [Why not just `var THREE = window.THREE`?](#why-not-just-var-three-=-windowthree)
|
47 | - [b) Use aliases](#b-use-aliases)
|
48 | - [c) Provide an external shim config](#c-provide-an-external-shim-config)
|
49 | - [d) Diagnose what browserify-shim is doing](#d-diagnose-what-browserify-shim-is-doing)
|
50 | - [Multi Shim Example including dependencies](#multi-shim-example-including-dependencies)
|
51 | - [a) Config inside `package.json` without aliases](#a-config-inside-packagejson-without-aliases)
|
52 | - [b) Config inside `package.json` with aliases](#b-config-inside-packagejson-with-aliases)
|
53 | - [c) Config inside `./config/shim.js` without aliases](#c-config-inside-configshimjs-without-aliases)
|
54 | - [`package.json`](#packagejson)
|
55 | - [`shim.js`](#shimjs)
|
56 | - [More Examples](#more-examples)
|
57 |
|
58 |
|
59 |
|
60 | ## Installation
|
61 |
|
62 | npm install browserify browserify-shim
|
63 |
|
64 | *For a version compatible with browserify@1.x run `npm install browserify-shim@1.x` instead.*
|
65 |
|
66 | *For a version compatible with the [v2 API](https://github.com/thlorenz/browserify-shim/tree/v2#api) `npm install browserify-shim@2.x` instead.*
|
67 |
|
68 | ## Features
|
69 |
|
70 | The core features of browserify-shim are:
|
71 |
|
72 | - Shims **non-CommonJS** modules in order for them to be **browserified** by specifying an alias, the path to the file,
|
73 | and the identifier under which the module attaches itself to the global `window` object.
|
74 | - Includes `depends` for shimming libraries that depend on other libraries being in the global namespace.
|
75 | - applies shims configured inside the dependencies of your package
|
76 |
|
77 | Additionally, it handles the following real-world edge cases:
|
78 |
|
79 | - Modules that just declare a `var foo = ...` on the script level and assume it gets attached to the `window` object.
|
80 | Since the only way they will ever be run is in the global context — "ahem, … NO?!"
|
81 | - Makes `define` and also `module` be `undefined`, in order to fix [improperly-authored
|
82 | libraries](https://github.com/mhemesath/r2d3/blob/918bd076e4f980722438b2594d1eba53a522ce75/r2d3.v2.js#L222) that need
|
83 | shimming but try anyway to use AMD or CommonJS. For more info read the comment inside [this
|
84 | fixture](https://github.com/thlorenz/browserify-shim/blob/master/test/shim/fixtures/shims/lib-with-exports-define-global-problem.js)
|
85 | - removes invalid requires, i.e. `require('jquery')` although `'jquery'` isn't installed due to the library being
|
86 | improperly published or *installed* incorrectly via a downloader like [bower](http://bower.io/)
|
87 |
|
88 | Since `browserify-shim` is a proper `browserify` transform you can publish packages with files that need to be shimmed,
|
89 | granted that you specify the shim config inside the `package.json`.
|
90 |
|
91 | When `browserify` resolves your package it will run the `browserify-shim` transform and thus shim what's necessary
|
92 | when generating the bundle.
|
93 |
|
94 | `browserify-shim` walks upwards from each source file and uses the first `"browserify-shim"` configuration it finds in a `package.json` file. You **can't** shim files outside your project from your project's package. You **can** add multiple `package.json` files as long as browserify-shim can always find a package above each source file with the right configuration.
|
95 |
|
96 | ## API
|
97 |
|
98 | ### You Will Always
|
99 |
|
100 | #### 1. Install browserify-shim dependency
|
101 |
|
102 | In most cases you want to install it as a [devDependency](https://npmjs.org/doc/json.html#devDependencies) via:
|
103 |
|
104 | npm install -D browserify-shim
|
105 |
|
106 | #### 2. Register browserify-shim as a transform with browserify
|
107 |
|
108 | Inside `package.json` add:
|
109 |
|
110 | ```json
|
111 | {
|
112 | "browserify": {
|
113 | "transform": [ "browserify-shim" ]
|
114 | }
|
115 | }
|
116 | ```
|
117 |
|
118 | Browserify transforms are run in order and may modify your source code along the way. You'll typically want to include browserify-shim last.
|
119 |
|
120 | #### 3. Provide browserify-shim config
|
121 |
|
122 | Inside `package.json` add:
|
123 |
|
124 | ```json
|
125 | {
|
126 | "browserify-shim": {
|
127 | "./js/vendor/jquery.js": "$",
|
128 | "three": "global:THREE"
|
129 | }
|
130 | }
|
131 | ```
|
132 |
|
133 | The above includes `./js/vendor/jquery.js` (relative to the `package.json`) in the bundle and exports `window.$`.
|
134 |
|
135 | Additionally it exposes `window.THREE` as `three`, so you can `var three = require('three')`. More info
|
136 | [below](#a-expose-global-variables-via-global).
|
137 |
|
138 | ##### Short Form vs. Long Form config
|
139 |
|
140 | Since `jquery` does not depend on other shimmed modules and thus has no `depends` field, we used the short form to
|
141 | specify its exports, however the example above is equivalent to:
|
142 |
|
143 | ```json
|
144 | {
|
145 | "browserify-shim": {
|
146 | "./js/vendor/jquery.js": { "exports": "$" }
|
147 | }
|
148 | }
|
149 | ```
|
150 |
|
151 | ### You will sometimes
|
152 |
|
153 | #### a) Expose global variables via `global:*`
|
154 |
|
155 | In some cases the libraries you are using are very large and you'd prefer to add them via a script tag instead to get
|
156 | the following benefits:
|
157 |
|
158 | - faster bundling times since the library is not included in the bundle
|
159 | - pull libraries from a [CDN](http://en.wikipedia.org/wiki/Content_delivery_network) which allows it to be pulled
|
160 | straight from the user's browser cache in case it was downloaded before
|
161 |
|
162 | We'll show how this works by taking the rather huge yet awesome `THREE.js` library as an example:
|
163 |
|
164 | ##### 1. add script tag for library you want to expose
|
165 |
|
166 | ```html
|
167 | <!-- index.html -->
|
168 | <head>
|
169 | <meta charset=utf-8 />
|
170 | <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/three.js/r61/three.min.js"></script>
|
171 | </head>
|
172 | ```
|
173 |
|
174 | ##### 2. Add expose global config to `package.json`
|
175 |
|
176 | ```json
|
177 | {
|
178 | "browserify-shim": {
|
179 | "three": "global:THREE"
|
180 | }
|
181 | }
|
182 | ```
|
183 |
|
184 | ##### 2.a. Add expose global config to external shim config
|
185 |
|
186 | In case you are using an external shim config, you may achieve the same by specifying the global via an `exports`.
|
187 |
|
188 | ```js
|
189 | module.exports = {
|
190 | 'three': { exports: 'global:THREE' }
|
191 | }
|
192 | ```
|
193 |
|
194 | [more about external configs here](#c-config-inside-configshimjs-without-aliases)
|
195 |
|
196 | **Note:** `THREE.js` attaches `window.THREE`.
|
197 |
|
198 | ##### 3. Require library by the name it was exposed as
|
199 |
|
200 | ```js
|
201 | var THREE = require('three');
|
202 | ```
|
203 |
|
204 | ##### Why not just `var THREE = window.THREE`?
|
205 |
|
206 | You want to avoid spreading the knowledge that `THREE` is a global and stay consistent in how you resolve dependencies.
|
207 | Additionally if `THREE` would ever be published to [npm](https://npmjs.org/) and you decide to install it from there,
|
208 | you don't have to change any of your code since it already is `require`ing it properly.
|
209 |
|
210 |
|
211 | #### b) Use aliases
|
212 |
|
213 | You may expose files under a different name via the [`browser` field](https://gist.github.com/defunctzombie/4339901#replace-specific-files---advanced) and refer to them under that alias in the shim config:
|
214 |
|
215 | ```json
|
216 | {
|
217 | "browser": {
|
218 | "jquery": "./js/vendor/jquery.js"
|
219 | },
|
220 | "browserify-shim": {
|
221 | "jquery": "$"
|
222 | }
|
223 | }
|
224 | ```
|
225 |
|
226 | This also allows you to require this module under the alias, i.e.: `var $ = require('jquery')`.
|
227 |
|
228 | #### c) Provide an external shim config
|
229 |
|
230 | ```json
|
231 | {
|
232 | "browserify-shim": "./config/shim.js"
|
233 | }
|
234 | ```
|
235 |
|
236 | The external shim format is very similar to the way in which the shim is specified inside the `package.json`. See
|
237 | [below](#c-config-inside-configshimjs-without-aliases) for more details.
|
238 |
|
239 | #### d) Diagnose what browserify-shim is doing
|
240 |
|
241 | You may encounter problems when your shim config isn't properly setup. In that case you can diagnose them via the
|
242 | `BROWSERIFYSHIM_DIAGNOSTICS` flag.
|
243 |
|
244 | Simply set the flag when building your bundle, i.e.:
|
245 |
|
246 | BROWSERIFYSHIM_DIAGNOSTICS=1 browserify -d . -o js/bundle.js
|
247 |
|
248 | or in a `build.js` script add: `process.env.BROWSERIFYSHIM_DIAGNOSTICS=1` to the top.
|
249 |
|
250 | ## Multi Shim Example including dependencies
|
251 |
|
252 | Some libraries depend on other libraries to have attached their exports to the window for historical reasons :(.
|
253 | (Hopefully soon we can truly say that this bad design is history.)
|
254 |
|
255 | In this contrived example we are shimming four libraries since none of them are commonJS compatible:
|
256 |
|
257 | - **x** exports **window.$**
|
258 | - **x-ui** exports nothing since it just **attaches itself to x**. Therefore x-ui depends on x.
|
259 | - **y** exports **window.Y** and also **depends on x** expecting to find it on the window as $.
|
260 | - **z** exports **window.zorro** and **depends on x and y**. It expects to find x on the window as $, but y on the window as YNOT,
|
261 | which is actually different than the name under which y exports itself.
|
262 |
|
263 | We will be using the `depends` field in order to ensure that a dependency is included and initialized before a library
|
264 | that depends on it is initialized.
|
265 |
|
266 | Below are three examples, each showing a way to properly shim the above mentioned modules.
|
267 |
|
268 | ### a) Config inside `package.json` without aliases
|
269 |
|
270 | ```json
|
271 | {
|
272 | "browserify": {
|
273 | "transform": [ "browserify-shim" ]
|
274 | },
|
275 | "browserify-shim": {
|
276 | "./vendor/x.js" : "$",
|
277 | "./vendor/x-ui.js" : { "depends": [ "./vendor/x.js" ] },
|
278 | "./vendor/y.js" : { "exports": "Y", "depends": [ "./vendor/x.js:$" ] },
|
279 | "./vendor/z.js" : { "exports": "zorro", "depends": [ "./vendor/x.js:$", "./vendor/y.js:YNOT" ] }
|
280 | }
|
281 | }
|
282 | ```
|
283 |
|
284 | **Note:** the `depends` array consists of entries of the format `path-to-file:export`
|
285 |
|
286 | ### b) Config inside `package.json` with aliases
|
287 |
|
288 | ```json
|
289 | {
|
290 | "browserify": {
|
291 | "transform": [ "browserify-shim" ]
|
292 | },
|
293 | "browser": {
|
294 | "x" : "./vendor/x.js",
|
295 | "x-ui" : "./vendor/x-ui.js",
|
296 | "y" : "./vendor/y.js",
|
297 | "z" : "./vendor/z.js"
|
298 | },
|
299 | "browserify-shim": {
|
300 | "x" : "$",
|
301 | "x-ui" : { "depends": [ "x" ] },
|
302 | "y" : { "exports": "Y", "depends": [ "x:$" ] },
|
303 | "z" : { "exports": "zorro", "depends": [ "x:$", "y:YNOT" ] }
|
304 | }
|
305 | }
|
306 | ```
|
307 |
|
308 | **Note:** the `depends` entries make use of the aliases as well `alias:export`
|
309 |
|
310 | ### c) Config inside `./config/shim.js` without aliases
|
311 |
|
312 | #### `package.json`
|
313 |
|
314 | ```json
|
315 | {
|
316 | "browserify": {
|
317 | "transform": [ "browserify-shim" ]
|
318 | },
|
319 | "browserify-shim": "./config/shim.js"
|
320 | }
|
321 | ```
|
322 |
|
323 | #### `shim.js`
|
324 |
|
325 | ```js
|
326 | module.exports = {
|
327 | '../vendor/x.js' : { 'exports': '$' },
|
328 | '../vendor/x-ui.js' : { 'depends': { '../vendor/x.js': null } },
|
329 | '../vendor/y.js' : { 'exports': 'Y', 'depends': { '../vendor/x.js': '$' } },
|
330 | '../vendor/z.js' : { 'exports': 'zorro', 'depends': { '../vendor/x.js': '$', '../vendor/y.js': 'YNOT' } }
|
331 | }
|
332 | ```
|
333 |
|
334 | **Note:** all paths are relative to `./config/shim.js` instead of the `package.json`.
|
335 |
|
336 | The main difference to `a)` is the `depends` field specification. Instead it being an array of strings it expresses its dependencies as a hashmap:
|
337 |
|
338 | - **key:** `path-to-file`
|
339 | - **value:** the name under which it is expected to be attached on the window
|
340 |
|
341 | ## More Examples
|
342 |
|
343 | - [shim-jquery](https://github.com/thlorenz/browserify-shim/tree/master/examples/shim-jquery)
|
344 | - [expose-jquery](https://github.com/thlorenz/browserify-shim/tree/master/examples/expose-jquery)
|
345 | - [shim-jquery-external](https://github.com/thlorenz/browserify-shim/tree/master/examples/shim-jquery-external)
|
346 | - the [tests](https://github.com/thlorenz/browserify-shim/tree/master/test) are a great resource to investigate the
|
347 | different ways to configure shims and to understand how shims are applied to packages found inside the `node_modules`
|
348 | of your package
|