|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- # amdefine
-
- A module that can be used to implement AMD's define() in Node. This allows you
- to code to the AMD API and have the module work in node programs without
- requiring those other programs to use AMD.
-
- ## Usage
-
- **1)** Update your package.json to indicate amdefine as a dependency:
-
- ```javascript
- "dependencies": {
- "amdefine": ">=0.1.0"
- }
- ```
-
- Then run `npm install` to get amdefine into your project.
-
- **2)** At the top of each module that uses define(), place this code:
-
- ```javascript
- if (typeof define !== 'function') { var define = require('amdefine')(module) }
- ```
-
- **Only use these snippets** when loading amdefine. If you preserve the basic structure,
- with the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer).
-
- You can add spaces, line breaks and even require amdefine with a local path, but
- keep the rest of the structure to get the stripping behavior.
-
- As you may know, because `if` statements in JavaScript don't have their own scope, the var
- declaration in the above snippet is made whether the `if` expression is truthy or not. If
- RequireJS is loaded then the declaration is superfluous because `define` is already already
- declared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var`
- declarations of the same variable in the same scope gracefully.
-
- If you want to deliver amdefine.js with your code rather than specifying it as a dependency
- with npm, then just download the latest release and refer to it using a relative path:
-
- [Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js)
-
- ### amdefine/intercept
-
- Consider this very experimental.
-
- Instead of pasting the piece of text for the amdefine setup of a `define`
- variable in each module you create or consume, you can use `amdefine/intercept`
- instead. It will automatically insert the above snippet in each .js file loaded
- by Node.
-
- **Warning**: you should only use this if you are creating an application that
- is consuming AMD style defined()'d modules that are distributed via npm and want
- to run that code in Node.
-
- For library code where you are not sure if it will be used by others in Node or
- in the browser, then explicitly depending on amdefine and placing the code
- snippet above is suggested path, instead of using `amdefine/intercept`. The
- intercept module affects all .js files loaded in the Node app, and it is
- inconsiderate to modify global state like that unless you are also controlling
- the top level app.
-
- #### Why distribute AMD-style modules via npm?
-
- npm has a lot of weaknesses for front-end use (installed layout is not great,
- should have better support for the `baseUrl + moduleID + '.js' style of loading,
- single file JS installs), but some people want a JS package manager and are
- willing to live with those constraints. If that is you, but still want to author
- in AMD style modules to get dynamic require([]), better direct source usage and
- powerful loader plugin support in the browser, then this tool can help.
-
- #### amdefine/intercept usage
-
- Just require it in your top level app module (for example index.js, server.js):
-
- ```javascript
- require('amdefine/intercept');
- ```
-
- The module does not return a value, so no need to assign the result to a local
- variable.
-
- Then just require() code as you normally would with Node's require(). Any .js
- loaded after the intercept require will have the amdefine check injected in
- the .js source as it is loaded. It does not modify the source on disk, just
- prepends some content to the text of the module as it is loaded by Node.
-
- #### How amdefine/intercept works
-
- It overrides the `Module._extensions['.js']` in Node to automatically prepend
- the amdefine snippet above. So, it will affect any .js file loaded by your
- app.
-
- ## define() usage
-
- It is best if you use the anonymous forms of define() in your module:
-
- ```javascript
- define(function (require) {
- var dependency = require('dependency');
- });
- ```
-
- or
-
- ```javascript
- define(['dependency'], function (dependency) {
-
- });
- ```
-
- ## RequireJS optimizer integration. <a name="optimizer"></name>
-
- Version 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html)
- will have support for stripping the `if (typeof define !== 'function')` check
- mentioned above, so you can include this snippet for code that runs in the
- browser, but avoid taking the cost of the if() statement once the code is
- optimized for deployment.
-
- ## Node 0.4 Support
-
- If you want to support Node 0.4, then add `require` as the second parameter to amdefine:
-
- ```javascript
- //Only if you want Node 0.4. If using 0.5 or later, use the above snippet.
- if (typeof define !== 'function') { var define = require('amdefine')(module, require) }
- ```
-
- ## Limitations
-
- ### Synchronous vs Asynchronous
-
- amdefine creates a define() function that is callable by your code. It will
- execute and trace dependencies and call the factory function *synchronously*,
- to keep the behavior in line with Node's synchronous dependency tracing.
-
- The exception: calling AMD's callback-style require() from inside a factory
- function. The require callback is called on process.nextTick():
-
- ```javascript
- define(function (require) {
- require(['a'], function(a) {
- //'a' is loaded synchronously, but
- //this callback is called on process.nextTick().
- });
- });
- ```
-
- ### Loader Plugins
-
- Loader plugins are supported as long as they call their load() callbacks
- synchronously. So ones that do network requests will not work. However plugins
- like [text](http://requirejs.org/docs/api.html#text) can load text files locally.
-
- The plugin API's `load.fromText()` is **not supported** in amdefine, so this means
- transpiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs)
- will not work. This may be fixable, but it is a bit complex, and I do not have
- enough node-fu to figure it out yet. See the source for amdefine.js if you want
- to get an idea of the issues involved.
-
- ## Tests
-
- To run the tests, cd to **tests** and run:
-
- ```
- node all.js
- node all-intercept.js
- ```
-
- ## License
-
- New BSD and MIT. Check the LICENSE file for all the details.
|