1 | #almond
|
2 |
|
3 | A replacement [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) loader for
|
4 | [RequireJS](http://requirejs.org). It provides a minimal AMD API footprint that includes [loader plugin](http://requirejs.org/docs/plugins.html) support. Only useful for built/bundled AMD modules, does not do dynamic loading.
|
5 |
|
6 | ## Why
|
7 |
|
8 | Some developers like to use the AMD API to code modular JavaScript, but after doing an optimized build,
|
9 | they do not want to include a full AMD loader like RequireJS, since they do not need all that functionality.
|
10 | Some use cases, like mobile, are very sensitive to file sizes.
|
11 |
|
12 | By including almond in the built file, there is no need for RequireJS.
|
13 | almond is around **1 kilobyte** when minified with Closure Compiler and gzipped.
|
14 |
|
15 | Since it can support certain types of loader plugin-optimized resources, it is a great
|
16 | fit for a library that wants to use [text templates](http://requirejs.org/docs/api.html#text)
|
17 | or [CoffeeScript](https://github.com/jrburke/require-cs) as part of
|
18 | their project, but get a tiny download in one file after using the
|
19 | [RequireJS Optimizer](http://requirejs.org/docs/optimization.html).
|
20 |
|
21 | If you are building a library, the wrap=true support in the RequireJS optimizer
|
22 | will wrap the optimized file in a closure, so the define/require AMD API does not
|
23 | escape the file. Users of your optimized file will only see the global API you decide
|
24 | to export, not the AMD API. See the usage section below for more details.
|
25 |
|
26 | So, you get great code cleanliness with AMD and the use of powerful loader plugins
|
27 | in a tiny wrapper that makes it easy for others to use your code even if they do not use AMD.
|
28 |
|
29 | If you want a single file build output but without the module APIs included, you might want to consider [AMDclean](https://github.com/gfranko/amdclean).
|
30 |
|
31 | ## Restrictions
|
32 |
|
33 | It is best used for libraries or apps that use AMD and:
|
34 |
|
35 | * optimize all the modules into one file -- no dynamic code loading.
|
36 | * all modules have IDs and dependency arrays in their define() calls -- the RequireJS optimizer will take care of this for you.
|
37 | * only have **one** requirejs.config() or require.config() call.
|
38 | * the requirejs.config/require.config call needs to be included in the build output. This is particularly important for making sure any [map config](http://requirejs.org/docs/api.html#config-map) use still works.
|
39 | * do not use the `var require = {};` style of [passing config](http://requirejs.org/docs/api.html#config).
|
40 | * do not use [RequireJS multiversion support/contexts](http://requirejs.org/docs/api.html#multiversion).
|
41 | * do not use require.toUrl() or require.nameToUrl().
|
42 | * do not use [packages/packagePaths config](http://requirejs.org/docs/api.html#packages). If you need to use packages that have a main property, [volo](https://github.com/volojs/volo) can create an adapter module so that it can work without this config. Use the `amdify add` command to add the dependency to your project.
|
43 |
|
44 | What is supported:
|
45 |
|
46 | * dependencies with relative IDs.
|
47 | * define('id', {}) definitions.
|
48 | * define(), require() and requirejs() calls.
|
49 | * loader plugins that can inline their resources into optimized files, and
|
50 | can access those inlined resources synchronously after the optimization pass.
|
51 | The [text](http://requirejs.org/docs/api.html#text) and
|
52 | [CoffeeScript](https://github.com/jrburke/require-cs) plugins are two such plugins.
|
53 |
|
54 | ## Download
|
55 |
|
56 | [Latest release](https://github.com/jrburke/almond/raw/latest/almond.js)
|
57 |
|
58 |
|
59 | ## Usage
|
60 |
|
61 | [Download the RequireJS optimizer](http://requirejs.org/docs/download.html#rjs).
|
62 |
|
63 | [Download the current release of almond.js](https://github.com/jrburke/almond/raw/latest/almond.js).
|
64 |
|
65 | Run the optimizer using [Node](http://nodejs.org) (also [works in Java](https://github.com/jrburke/r.js/blob/master/README.md)):
|
66 |
|
67 | node r.js -o baseUrl=. name=path/to/almond include=main out=main-built.js wrap=true
|
68 |
|
69 | This assumes your project's top-level script file is called main.js and the command
|
70 | above is run from the directory containing main.js. If you prefer to use a build.js build profile instead of command line arguments, [this RequireJS optimization section](http://requirejs.org/docs/optimization.html#pitfalls) has info on how to do that.
|
71 |
|
72 | wrap=true will add this wrapper around the main-built.js contents (which will be minified by UglifyJS:
|
73 |
|
74 | (function () {
|
75 | //almond will be here
|
76 | //main and its nested dependencies will be here
|
77 | }());
|
78 |
|
79 | If you do not want that wrapper, leave off the wrap=true argument.
|
80 |
|
81 | These optimizer arguments can also be used in a build config object, so it can be used
|
82 | in [runtime-generated server builds](https://github.com/jrburke/r.js/blob/master/build/tests/http/httpBuild.js).
|
83 |
|
84 |
|
85 | ## Triggering module execution <a name="execution"></a>
|
86 |
|
87 | As of RequireJS 2.0 and almond 0.1, modules are only executed if they are
|
88 | called by a top level require call. The data-main attribute on a script tag
|
89 | for require.js counts as a top level require call.
|
90 |
|
91 | However with almond, it does not look for a data-main attribute, and if your
|
92 | main JS module does not use a top level require() or requirejs() call to
|
93 | trigger module loading/execution, after a build, it may appear that the code
|
94 | broke -- no modules execute.
|
95 |
|
96 | The 2.0 RequireJS optimizer has a build config, option **insertRequire** that you
|
97 | can use to specify that a require([]) call is inserted at the end of the built
|
98 | file to trigger module loading. Example:
|
99 |
|
100 | node r.js -o baseUrl=. name=path/to/almond.js include=main insertRequire=main out=main-built.js wrap=true
|
101 |
|
102 | or, if using a build config file:
|
103 |
|
104 | ```javascript
|
105 | {
|
106 | baseUrl: '.',
|
107 | name: 'path/to/almond',
|
108 | include: ['main'],
|
109 | insertRequire: ['main'],
|
110 | out: 'main-built.js',
|
111 | wrap: true
|
112 | }
|
113 | ```
|
114 |
|
115 | This will result with `require(["main"]);` at the bottom of main-built.js.
|
116 |
|
117 | ## Exporting a public API
|
118 |
|
119 | If you are making a library that is made up of AMD modules in source form, but will be built with almond into one file, and you want to export a small public
|
120 | API for that library, you can use the `wrap` build config to do so. Build
|
121 | config:
|
122 |
|
123 | ```javascript
|
124 | {
|
125 | baseUrl: '.',
|
126 | name: 'path/to/almond',
|
127 | include: ['main'],
|
128 | out: 'lib-built.js',
|
129 | wrap: {
|
130 | startFile: 'path/to/start.frag',
|
131 | endFile: 'path/to/end.frag'
|
132 | }
|
133 | }
|
134 | ```
|
135 |
|
136 | Where start.frag could look like this:
|
137 |
|
138 | ```javascript
|
139 | (function (root, factory) {
|
140 | if (typeof define === 'function' && define.amd) {
|
141 | //Allow using this built library as an AMD module
|
142 | //in another project. That other project will only
|
143 | //see this AMD call, not the internal modules in
|
144 | //the closure below.
|
145 | define([], factory);
|
146 | } else {
|
147 | //Browser globals case. Just assign the
|
148 | //result to a property on the global.
|
149 | root.libGlobalName = factory();
|
150 | }
|
151 | }(this, function () {
|
152 | //almond, and your modules will be inlined here
|
153 | ```
|
154 |
|
155 | and end.frag is like this:
|
156 | ```javascript
|
157 | //The modules for your project will be inlined above
|
158 | //this snippet. Ask almond to synchronously require the
|
159 | //module value for 'main' here and return it as the
|
160 | //value to use for the public API for the built file.
|
161 | return require('main');
|
162 | }));
|
163 | ```
|
164 |
|
165 | After the build, then the built file should be structured like so:
|
166 |
|
167 | * start.frag
|
168 | * almond.js
|
169 | * modules for your lib, including 'main'
|
170 | * end.frag
|
171 |
|
172 | ## Common errors
|
173 |
|
174 | Explanations of common errors:
|
175 |
|
176 | ### deps is undefined
|
177 |
|
178 | Where this line is mentioned:
|
179 |
|
180 | if (!deps.splice) {
|
181 |
|
182 | It usually means that there is a define()'d module, but it is missing a name,
|
183 | something that looks like this:
|
184 |
|
185 | define(function () {});
|
186 | //or
|
187 | define([], function () {});
|
188 |
|
189 |
|
190 | when it should look like:
|
191 |
|
192 | define('someName', function () {});
|
193 | //or
|
194 | define('someName', [], function () {});
|
195 |
|
196 |
|
197 | This is usually a sign that the tool you used to combine all the modules
|
198 | together did not properly name an anonymous AMD module.
|
199 |
|
200 | ### x missing y
|
201 |
|
202 | It means that module 'x' asked for module 'y', but module 'y' was not available.
|
203 |
|
204 | This usually means that 'y' was not included in the built file that includes almond.
|
205 |
|
206 | almond can only handle modules built in with it, it cannot dynamically load
|
207 | modules from the network.
|
208 |
|
209 |
|
210 | ### No y
|
211 |
|
212 | It means that a `require('y')` call was done but y was not available.
|
213 |
|
214 | This usually means that 'y' was not included in the built file that includes almond.
|
215 |
|
216 | almond can only handle modules built in with it, it cannot dynamically load
|
217 | modules from the network.
|
218 |
|
219 | ## How to get help
|
220 |
|
221 | * Contact the [requirejs list](https://groups.google.com/group/requirejs).
|
222 | * Open issues in the [issue tracker](https://github.com/jrburke/almond/issues).
|
223 |
|
224 | ## Contributing
|
225 |
|
226 | Almond follows the
|
227 | [same contribution model as requirejs](http://requirejs.org/docs/contributing.html)
|
228 | and is considered a sub-project of requirejs. |
\ | No newline at end of file |