You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

245 lines
9.2 KiB

3 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. #almond
  2. A replacement [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) loader for
  3. [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.
  4. ## Why
  5. Some developers like to use the AMD API to code modular JavaScript, but after doing an optimized build,
  6. they do not want to include a full AMD loader like RequireJS, since they do not need all that functionality.
  7. Some use cases, like mobile, are very sensitive to file sizes.
  8. By including almond in the built file, there is no need for RequireJS.
  9. almond is around **1 kilobyte** when minified with Closure Compiler and gzipped.
  10. Since it can support certain types of loader plugin-optimized resources, it is a great
  11. fit for a library that wants to use [text templates](http://requirejs.org/docs/api.html#text)
  12. or [CoffeeScript](https://github.com/requirejs/require-cs) as part of
  13. their project, but get a tiny download in one file after using the
  14. [RequireJS Optimizer](http://requirejs.org/docs/optimization.html).
  15. If you are building a library, the wrap=true support in the RequireJS optimizer
  16. will wrap the optimized file in a closure, so the define/require AMD API does not
  17. escape the file. Users of your optimized file will only see the global API you decide
  18. to export, not the AMD API. See the usage section below for more details.
  19. So, you get great code cleanliness with AMD and the use of powerful loader plugins
  20. in a tiny wrapper that makes it easy for others to use your code even if they do not use AMD.
  21. 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).
  22. ## Restrictions
  23. It is best used for libraries or apps that use AMD and:
  24. * optimize all the modules into one file -- no dynamic code loading.
  25. * all modules have IDs and dependency arrays in their define() calls -- the RequireJS optimizer will take care of this for you.
  26. * only have **one** requirejs.config() or require.config() call.
  27. * 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.
  28. * do not use the `var require = {};` style of [passing config](http://requirejs.org/docs/api.html#config).
  29. * do not use [RequireJS multiversion support/contexts](http://requirejs.org/docs/api.html#multiversion).
  30. * do not use require.toUrl() or require.nameToUrl().
  31. * 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.
  32. What is supported:
  33. * dependencies with relative IDs.
  34. * define('id', {}) definitions.
  35. * define(), require() and requirejs() calls.
  36. * loader plugins that can inline their resources into optimized files, and
  37. can access those inlined resources synchronously after the optimization pass.
  38. The [text](http://requirejs.org/docs/api.html#text) and
  39. [CoffeeScript](https://github.com/requirejs/require-cs) plugins are two such plugins.
  40. ## Download
  41. [Latest release](https://github.com/requirejs/almond/raw/latest/almond.js)
  42. ## Usage
  43. [Download the RequireJS optimizer](http://requirejs.org/docs/download.html#rjs).
  44. [Download the current release of almond.js](https://github.com/requirejs/almond/raw/latest/almond.js).
  45. Run the optimizer using [Node](http://nodejs.org) (also [works in Java](https://github.com/requirejs/r.js/blob/master/README.md)):
  46. node r.js -o baseUrl=. name=path/to/almond include=main out=main-built.js wrap=true
  47. This assumes your project's top-level script file is called main.js and the command
  48. 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.
  49. wrap=true will add this wrapper around the main-built.js contents (which will be minified by UglifyJS:
  50. (function () {
  51. //almond will be here
  52. //main and its nested dependencies will be here
  53. }());
  54. If you do not want that wrapper, leave off the wrap=true argument.
  55. These optimizer arguments can also be used in a build config object, so it can be used
  56. in [runtime-generated server builds](https://github.com/requirejs/r.js/blob/master/build/tests/http/httpBuild.js).
  57. ## Triggering module execution <a name="execution"></a>
  58. As of RequireJS 2.0 and almond 0.1, modules are only executed if they are
  59. called by a top level require call. The data-main attribute on a script tag
  60. for require.js counts as a top level require call.
  61. However with almond, it does not look for a data-main attribute, and if your
  62. main JS module does not use a top level require() or requirejs() call to
  63. trigger module loading/execution, after a build, it may appear that the code
  64. broke -- no modules execute.
  65. The 2.0 RequireJS optimizer has a build config, option **insertRequire** that you
  66. can use to specify that a require([]) call is inserted at the end of the built
  67. file to trigger module loading. Example:
  68. node r.js -o baseUrl=. name=path/to/almond.js include=main insertRequire=main out=main-built.js wrap=true
  69. or, if using a build config file:
  70. ```javascript
  71. {
  72. baseUrl: '.',
  73. name: 'path/to/almond',
  74. include: ['main'],
  75. insertRequire: ['main'],
  76. out: 'main-built.js',
  77. wrap: true
  78. }
  79. ```
  80. This will result with `require(["main"]);` at the bottom of main-built.js.
  81. ## Exporting a public API
  82. 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
  83. API for that library, you can use the `wrap` build config to do so. Build
  84. config:
  85. ```javascript
  86. {
  87. baseUrl: '.',
  88. name: 'path/to/almond',
  89. include: ['main'],
  90. out: 'lib-built.js',
  91. wrap: {
  92. startFile: 'path/to/start.frag',
  93. endFile: 'path/to/end.frag'
  94. }
  95. }
  96. ```
  97. Where start.frag could look like this:
  98. ```javascript
  99. (function (root, factory) {
  100. if (typeof define === 'function' && define.amd) {
  101. //Allow using this built library as an AMD module
  102. //in another project. That other project will only
  103. //see this AMD call, not the internal modules in
  104. //the closure below.
  105. define([], factory);
  106. } else {
  107. //Browser globals case. Just assign the
  108. //result to a property on the global.
  109. root.libGlobalName = factory();
  110. }
  111. }(this, function () {
  112. //almond, and your modules will be inlined here
  113. ```
  114. and end.frag is like this:
  115. ```javascript
  116. //The modules for your project will be inlined above
  117. //this snippet. Ask almond to synchronously require the
  118. //module value for 'main' here and return it as the
  119. //value to use for the public API for the built file.
  120. return require('main');
  121. }));
  122. ```
  123. After the build, then the built file should be structured like so:
  124. * start.frag
  125. * almond.js
  126. * modules for your lib, including 'main'
  127. * end.frag
  128. ## License
  129. MIT
  130. ## Code of Conduct
  131. [jQuery Foundation Code of Conduct](https://jquery.org/conduct/).
  132. ## Common errors
  133. Explanations of common errors:
  134. ### incorrect module build, no module name
  135. In almond 3.0.0 and earlier, this would show up as "deps is undefined", where
  136. this line is mentioned:
  137. if (!deps.splice) {
  138. In 3.0.1+ the error is explicitly: "incorrect module build, no module name".
  139. This means that there is a define()'d module, but it is missing a name,
  140. something that looks like this:
  141. define(function () {});
  142. //or
  143. define([], function () {});
  144. when it should look like:
  145. define('someName', function () {});
  146. //or
  147. define('someName', [], function () {});
  148. This is usually a sign that the tool you used to combine all the modules
  149. together did not properly name an anonymous AMD module.
  150. Multiple modules built into a single file **must** have names in the define calls.
  151. Otherwise almond has no way to assign the module to a name key for use in the code.
  152. The fix is to use a build tool that understand AMD modules and inserts the module
  153. IDs in the build. The
  154. [requirejs optimizer](http://requirejs.org/docs/optimization.html) is a build tool
  155. that can do this correctly.
  156. ### x missing y
  157. It means that module 'x' asked for module 'y', but module 'y' was not available.
  158. This usually means that 'y' was not included in the built file that includes almond.
  159. almond can only handle modules built in with it, it cannot dynamically load
  160. modules from the network.
  161. ### No y
  162. It means that a `require('y')` call was done but y was not available.
  163. This usually means that 'y' was not included in the built file that includes almond.
  164. almond can only handle modules built in with it, it cannot dynamically load
  165. modules from the network.
  166. ## How to get help
  167. * Open issues in the [issue tracker](https://github.com/requirejs/almond/issues).
  168. ## Contributing
  169. Almond follows the
  170. [same contribution model as requirejs](http://requirejs.org/docs/contributing.html)
  171. and is considered a sub-project of requirejs.