UNPKG

12.8 kBMarkdownView Raw
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<!-- START doctoc generated TOC please keep comment here to allow auto update -->
29<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
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<!-- END doctoc generated TOC please keep comment here to allow auto update -->
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
70The 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
77Additionally, 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
88Since `browserify-shim` is a proper `browserify` transform you can publish packages with files that need to be shimmed,
89granted that you specify the shim config inside the `package.json`.
90
91When `browserify` resolves your package it will run the `browserify-shim` transform and thus shim what's necessary
92when 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
102In 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
108Inside `package.json` add:
109
110```json
111{
112 "browserify": {
113 "transform": [ "browserify-shim" ]
114 }
115}
116```
117
118Browserify 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
122Inside `package.json` add:
123
124```json
125{
126 "browserify-shim": {
127 "./js/vendor/jquery.js": "$",
128 "three": "global:THREE"
129 }
130}
131```
132
133The above includes `./js/vendor/jquery.js` (relative to the `package.json`) in the bundle and exports `window.$`.
134
135Additionally 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
140Since `jquery` does not depend on other shimmed modules and thus has no `depends` field, we used the short form to
141specify 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
155In some cases the libraries you are using are very large and you'd prefer to add them via a script tag instead to get
156the 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
162We'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
186In case you are using an external shim config, you may achieve the same by specifying the global via an `exports`.
187
188```js
189module.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
201var THREE = require('three');
202```
203
204##### Why not just `var THREE = window.THREE`?
205
206You want to avoid spreading the knowledge that `THREE` is a global and stay consistent in how you resolve dependencies.
207Additionally if `THREE` would ever be published to [npm](https://npmjs.org/) and you decide to install it from there,
208you don't have to change any of your code since it already is `require`ing it properly.
209
210
211#### b) Use aliases
212
213You 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
226This 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
236The 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
241You 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
244Simply set the flag when building your bundle, i.e.:
245
246 BROWSERIFYSHIM_DIAGNOSTICS=1 browserify -d . -o js/bundle.js
247
248or in a `build.js` script add: `process.env.BROWSERIFYSHIM_DIAGNOSTICS=1` to the top.
249
250## Multi Shim Example including dependencies
251
252Some 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
255In 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,
261which is actually different than the name under which y exports itself.
262
263We will be using the `depends` field in order to ensure that a dependency is included and initialized before a library
264that depends on it is initialized.
265
266Below 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
326module.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
336The 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