Targets
vaccine.js is the shim that makes CommonJS or AMD modules work in the browser. It includes a function to define module factories. It also implements the "require" functionality that lets a module obtain the exports from another module. Finally it provides the library as either an AMD module or a "window" global. If it defines an AMD module, it also lists dependencies.
This shim will be bundled with the rest of the modules inside an immediately invoked function. This prevents leaking any unwanted globals.
build.sh wraps all source files including vaccine.js (at the end) inside an immediately invoked function. In the case of CommonJS, it also wraps each module individually in a "define" call, which turns each module into a factory function (closure). If it is AMD with an optional id, build.sh will also give each module an id (if one wasn't specified).
Run build.sh on the command line to produce the built file:
$ sh build.sh > my_library.js
The sources must be in a separate directory, which includes only source files. Of course, build.sh is very small, so you can extend it to fit your need.
vaccine_dev.js is useful when doing development. Developing with a single built file (from build.sh) is difficult, especially as libraries grow to many files. This dev version of Vaccine separates out each module in its own script tag, so finding things is easier.
vaccine_dev.js provides a requireDev function that by default
will give the exports of the main (entry) file. Specifying a module id as
the only parameter will give the exports of that module.
Below is an example of how vaccine_dev.js is used
<!-- Must be before sources -->
<script src="/vaccine_dev.js"></script>
<!-- Sources can be in any order -->
<script src="/src/underscore.js"></script>
<script src="/src/underscore/arrays.js"></script>
<script src="/src/underscore/collections.js"></script>
<script src="/src/underscore/each.js"></script>
<script src="/src/underscore/functions.js"></script>
<script src="/src/underscore/objects.js"></script>
<script src="/src/underscore/utils.js"></script>
<!-- Get the main exports with "requireDev()" -->
<script>var _ = requireDev();</script>
Note that in order for the script tags to work with CommonJS, a development server is needed to wrap the modules in "define" calls. AMD does not have this problem.
dev_server.js is a simple development server that serves up static files from the project's root directory. It will also wrap CommonJS modules under the source directory so that they can work in a script tag.
To use the dev server, copy down dev_serve.js to your project. This
server uses Express on top of
Node.js. With Node.js installed, install
express with: npm install express.
Run the server with $ node dev_server.js
The other functionality in the server is being able to run build.sh and having the results used in a script tag with href set to "build.sh". In fact any file with a path that starts with "build" will be executed before returning the results.
sh build.sh > my_library.js can just be make.
Project Settings
- AMD
- How AMD works.
AMD requires a build step with
sh build.sh > library.js. An AMD module is written with a call todefine. Currently, the supported method signature isdefine(id?, factory). The factory parameters arefactory(require, exports?, module?)with the last two depending on the exports configuration. - CommonJS
- How CommonJS works.
CommonJS requires a build step with
sh build.sh > library.js. The format is very similar to the inside of thefactoryof an AMD module. There are three free variables:require, exports, and module. - UMD - How UMD works. UMD is a pattern for a single file to support multiple environments, such as CommonJS, AMD, or a regular browser global. It does not need a build.
- Global (window) - This is the standard method of creating a single global variable for a library (or application). Then, any code that uses this library will have access via the global variable.
- AMD - This option means that the library will
work in any application that uses an AMD module loader, such as RequireJS.
That is, this option adds a
define('library_name', factory)if AMD is detected. - CommonJS - This option means that the project will support CommonJS environments, such as Node.js.
- Name - The name of the project. The global variable as well as the AMD module id will be set to this.
- Dependencies - The names of the library's
dependencies. This will be used if supporting an AMD environment, with the
definecall. - Main (entry file) - The relative path of the main file from the project's root directory. For built libraries (AMD, CommonJS), all the source files must be in a separate directory with only sources. This source directory is extracted from the path to the main file, but can be overwritten with a variable override.
Optimizations
var b = require('./b'). Note the lack of a ".js" at the end
of the id string. This must be left out to work. Certain projects have only
one level of code, which means they can use simpler "require" functionality.
- full relative - A full "require" implementation
that supports complex relative require's such as
require('../../module.js'). It also supports a single relative or absolute id, which is why those options don't do anything when this one is checked. - single relative - A simple single directory
require of the format
require('./{{module}}'). This means a file at "src/a.js" could require "src/b.js" withrequire('./b'), but it wouldn't be able to require "src/some_dir/c.js" with just this option checked. See the extra optimization at the end of the "absolute id" section. -
absolute id - Require a module with the full AMD path (which doesn't include the source directory). For example, the "src/my_lib.js" file could require "src/my_lib/utils.js" with
require('my_lib/utils'). Note the lack of a "./" or "../" at the beginning signifying that this is an absolute path. This option is only available to the AMD format.An extra optimization can occur if an AMD project has "single relative" requires only in files immediately under the directory of the same name as the project, and "absolute" requires everywhere else. The optimization is to use only "absolute" and "single relative" options, and the single relative requires will be translated into absolute ones by replacing the dot with the name of the project.
- w/o index - This means that the "/index" is
left off the end of requiring an "index.js" module. So, for example,
module "src/foo.js" must require "src/utils/index.js" with
require('./utils'). Note that the module can not also be required with the "/index" at the end, so beware. This only works for CommonJS format with a full relative implementation.
- exports - Export via attaching properties to
the exports object (free variable for CommonJS; second factory parameter
for AMD). A module can export a "foo" method via
exports.foo = .... The exports object becomes the module's API. - module.exports - Export via setting
module.exports with the module's API. If, for example, "bar.js" wanted to
have a function as the API, it could
module.exports = function() .... Then, another module couldvar bar = require('./bar'); ... bar()to run the function. - return - Export the API via returning an object from the AMD factory. This only works for AMD.
- optional id - This option makes it possible
to leave out the module id in the "define" call, so:
define(factory). It makes the build step (build.sh) slightly more complex, but saves some typing. When unchecked, the module id must be included:define(id, factory). - array - This option hasn't been implemented yet, but is there to signify that the dependency array in the "define" call is not supported.
Miscellaneous
- debug - Logs different actions to the console, such as when a module is defined or required. It also throws an error if a module is redefined, or required but never defined.
- performance - Calculates the time it takes to define all the modules and run their factories.
- "use strict"; - Adds a "use strict" into the built library to enable strict mode.
- Source directory - Sets the source directory used in "build.sh".
- Global variable name - Sets the name of the global variable when supporting that environment.
- Save - Remember the current configuration as a "saved" version of the shim. Multiple presses will overwrite the saved version.
- Swap - Swap the current configuration with the one that is saved.
- Diff with saved - Do a "diff" between the current configuration and the saved configuration. Red lines are lines the current configuration removed. Green lines are lines added in the current shim. Black ones are in both. Also notice that the sizes report the difference between the two.
When in Diff mode, the numbers are the difference between the configurations under comparison. When red, the current configuration is smaller (showing bytes removed). When green, the current configuration is larger (showing bytes added).
The bytes minified are calculated by running
UglifyJS on the text of
vaccine.js wrapped in an immediately evaluated function
(function() { ... }()).
Gzipped size was calculated by gzipping various vaccine.js versions with a 4.8k sized library. A linear regression fit the resulting gzipped sizes with a 0.997 correlation coefficient. Note that when compressing with smaller libraries, the amount added tends to be more.