• Stars
    star
    2,414
  • Rank 19,056 (Top 0.4 %)
  • Language
    JavaScript
  • License
    Other
  • Created over 13 years ago
  • Updated over 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A minimal AMD API implementation for use after optimized builds

almond

A replacement AMD loader for RequireJS. It provides a minimal AMD API footprint that includes loader plugin support. Only useful for built/bundled AMD modules, does not do dynamic loading.

Why

Some developers like to use the AMD API to code modular JavaScript, but after doing an optimized build, they do not want to include a full AMD loader like RequireJS, since they do not need all that functionality. Some use cases, like mobile, are very sensitive to file sizes.

By including almond in the built file, there is no need for RequireJS. almond is around 1 kilobyte when minified with Closure Compiler and gzipped.

Since it can support certain types of loader plugin-optimized resources, it is a great fit for a library that wants to use text templates or CoffeeScript as part of their project, but get a tiny download in one file after using the RequireJS Optimizer.

If you are building a library, the wrap=true support in the RequireJS optimizer will wrap the optimized file in a closure, so the define/require AMD API does not escape the file. Users of your optimized file will only see the global API you decide to export, not the AMD API. See the usage section below for more details.

So, you get great code cleanliness with AMD and the use of powerful loader plugins in a tiny wrapper that makes it easy for others to use your code even if they do not use AMD.

If you want a single file build output but without the module APIs included, you might want to consider AMDclean.

Restrictions

It is best used for libraries or apps that use AMD and:

  • optimize all the modules into one file -- no dynamic code loading.
  • all modules have IDs and dependency arrays in their define() calls -- the RequireJS optimizer will take care of this for you.
  • only have one requirejs.config() or require.config() call.
  • the requirejs.config/require.config call needs to be included in the build output. This is particularly important for making sure any map config use still works.
  • do not use the var require = {}; style of passing config.
  • do not use RequireJS multiversion support/contexts.
  • do not use require.toUrl() or require.nameToUrl().
  • do not use packages/packagePaths config. If you need to use packages that have a main property, 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.

What is supported:

  • dependencies with relative IDs.
  • define('id', {}) definitions.
  • define(), require() and requirejs() calls.
  • loader plugins that can inline their resources into optimized files, and can access those inlined resources synchronously after the optimization pass. The text and CoffeeScript plugins are two such plugins.

Download

Latest release

Usage

Download the RequireJS optimizer.

Download the current release of almond.js.

Run the optimizer using Node (also works in Java):

node r.js -o baseUrl=. name=path/to/almond include=main out=main-built.js wrap=true

This assumes your project's top-level script file is called main.js and the command 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 has info on how to do that.

wrap=true will add this wrapper around the main-built.js contents (which will be minified by UglifyJS:

(function () {
    //almond will be here
    //main and its nested dependencies will be here
}());

If you do not want that wrapper, leave off the wrap=true argument.

These optimizer arguments can also be used in a build config object, so it can be used in runtime-generated server builds.

Triggering module execution

As of RequireJS 2.0 and almond 0.1, modules are only executed if they are called by a top level require call. The data-main attribute on a script tag for require.js counts as a top level require call.

However with almond, it does not look for a data-main attribute, and if your main JS module does not use a top level require() or requirejs() call to trigger module loading/execution, after a build, it may appear that the code broke -- no modules execute.

The 2.0 RequireJS optimizer has a build config, option insertRequire that you can use to specify that a require([]) call is inserted at the end of the built file to trigger module loading. Example:

node r.js -o baseUrl=. name=path/to/almond.js include=main insertRequire=main out=main-built.js wrap=true

or, if using a build config file:

{
    baseUrl: '.',
    name: 'path/to/almond',
    include: ['main'],
    insertRequire: ['main'],
    out: 'main-built.js',
    wrap: true
}

This will result with require(["main"]); at the bottom of main-built.js.

Exporting a public API

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 API for that library, you can use the wrap build config to do so. Build config:

{
    baseUrl: '.',
    name: 'path/to/almond',
    include: ['main'],
    out: 'lib-built.js',
    wrap: {
        startFile: 'path/to/start.frag',
        endFile: 'path/to/end.frag'
    }
}

Where start.frag could look like this:

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        //Allow using this built library as an AMD module
        //in another project. That other project will only
        //see this AMD call, not the internal modules in
        //the closure below.
        define([], factory);
    } else {
        //Browser globals case. Just assign the
        //result to a property on the global.
        root.libGlobalName = factory();
    }
}(this, function () {
    //almond, and your modules will be inlined here

and end.frag is like this:

    //The modules for your project will be inlined above
    //this snippet. Ask almond to synchronously require the
    //module value for 'main' here and return it as the
    //value to use for the public API for the built file.
    return require('main');
}));

After the build, then the built file should be structured like so:

  • start.frag
  • almond.js
  • modules for your lib, including 'main'
  • end.frag

License

MIT

Code of Conduct

jQuery Foundation Code of Conduct.

Common errors

Explanations of common errors:

incorrect module build, no module name

In almond 3.0.0 and earlier, this would show up as "deps is undefined", where this line is mentioned:

if (!deps.splice) {

In 3.0.1+ the error is explicitly: "incorrect module build, no module name".

This means that there is a define()'d module, but it is missing a name, something that looks like this:

define(function () {});
//or
define([], function () {});

when it should look like:

define('someName', function () {});
//or
define('someName', [], function () {});

This is usually a sign that the tool you used to combine all the modules together did not properly name an anonymous AMD module.

Multiple modules built into a single file must have names in the define calls. Otherwise almond has no way to assign the module to a name key for use in the code.

The fix is to use a build tool that understand AMD modules and inserts the module IDs in the build. The requirejs optimizer is a build tool that can do this correctly.

x missing y

It means that module 'x' asked for module 'y', but module 'y' was not available.

This usually means that 'y' was not included in the built file that includes almond.

almond can only handle modules built in with it, it cannot dynamically load modules from the network.

No y

It means that a require('y') call was done but y was not available.

This usually means that 'y' was not included in the built file that includes almond.

almond can only handle modules built in with it, it cannot dynamically load modules from the network.

How to get help

Contributing

Almond follows the same contribution model as requirejs and is considered a sub-project of requirejs.

More Repositories

1

requirejs

A file and module loader for JavaScript
JavaScript
12,930
star
2

r.js

Runs RequireJS in Node and Rhino, and used to run the RequireJS optimizer
JavaScript
2,568
star
3

text

An AMD loader plugin for loading text resources
JavaScript
932
star
4

example-multipage

Example RequireJS-based project that has multiple pages that share a common set of modules.
JavaScript
840
star
5

example-multipage-shim

Example RequireJS-based project that has multiple pages that share a common set of modules with shim config
JavaScript
382
star
6

require-cs

An AMD loader plugin for CoffeeScript
JavaScript
335
star
7

require-jquery

A RequireJS+jQuery sample project
JavaScript
261
star
8

alameda

AMD loader, like requirejs, but with promises and for modern browsers
JavaScript
195
star
9

example-jquery-shim

Example project that uses jQuery and jQuery plugins via shim config
JavaScript
190
star
10

domReady

An AMD loader plugin for detecting DOM ready
JavaScript
182
star
11

example-jquery-cdn

Example project that uses jQuery and jQuery plugins wrapped as modules
JavaScript
151
star
12

cajon

JavaScript module loader for the browser that can load CommonJS/node and AMD modules
JavaScript
117
star
13

i18n

An AMD loader plugin for loading internationalization/localization string resources
JavaScript
98
star
14

xrayquire

An auxillary script that gives extra info on the use of requirejs in a web page.
JavaScript
74
star
15

example-libglobal

Use AMD modules to develop a JS library that builds to a lib that can be used by "globals only" scripts or as an AMD module
JavaScript
61
star
16

element

An AMD loader plugin for custom elements
JavaScript
56
star
17

requirejs-bower

Repo hold assets for publishing to the bower package manager.
JavaScript
34
star
18

requirejs-npm

Wrappers to allow using RequireJS-related scripts
JavaScript
22
star
19

step

AMD loader plugin that takes a step config to know how to sequential load some files
JavaScript
20
star
20

prim

Promise lib for use inside requirejs-related projects
JavaScript
7
star
21

requirejs-branding

Branding/images/design for RequireJS web site
CSS
6
star
22

browsertests

Standalone browser capability tests to help inform what is possible in a loader
PHP
3
star
23

alameda-prim

The alameda AMD loader that includes private promise shim
JavaScript
3
star
24

requirejs.github.io

requirejs.org site
HTML
2
star
25

requirejs-nuget

Artifact used for pushing to NuGet
JavaScript
2
star