The JavaScript Universal Module Converter & Resource Builder
define(['Modular', 'Development', 'Deployment'], function(){ return 'that just works, painlessly!' });
Why use modules like AMD or Common/JS ?
Write modular, maintainable & reusable code:
Clearly stated dependencies & imports.
Employ standards and trusted tools.
Have a dynamic code loading mechanism.
The damnation of one huge .js file or concatenation must end!
Are U still concatenating .js files ?
But javascript developers hate modules!
Many woes on Module formats & incompatibilities:
Verbose syntax, boilerplate ceremony & intricacies (especially AMD)
execution environment (AMD only for Web, CommonJs only for nodejs)
capabilities, dependency/path resolutions, plugins, semantics etc are a mess
UMD is a semi-standard boilerplate, far from usable.
U need a bridge to enjoy the richness of modules.
require('more').than(this);
Why use uRequire ?
Convert from any format to any other:
from AMD and CommonJS
to AMD, CommonJS, UMD, Combined for nodejs-Web/AMD-Web/Script
ES6/Harmonywhen standard/parsers mature
Forget the woes or Module formats incompatibilities
Eliminate boilerplate & write modular Javascript code once, run everywhere : Web/Script, Web/AMD, nodejs
A Universal Module Format with the power, goodies & standards from all.
Convert to a single
combined.js
, that runs everywhere & is super optimized
If U require
d it or define
d it, uRequire will find it.
Simplest Module Authoring
var dep1 = require('./rel/path/dep1'),
dep2 = require('abs/path/dep2');
// do stuff with dep1, dep2
module.exports = {my: 'module'}
// or
define(['./rel/path/dep1','abs/path/dep2'],
function(dep1, dep2) {
// do stuff with dep1, dep2
return {my:'module'}
});
// or both, in a relaxed, non-weird way
define(['some/dirName','dep2'],
function(dirNameIndex, dep2) {
var dep3JSON = require('json!dep3AsJSON');
// do stuff with dirNameIndex, dep2, dep3JSON
return {my:'module'}
});
// mix well known features from both
define(['my/dep1'], function(dep1) {
exports.prop = dep1 + require('./your/dep3');
});
dependencies: imports: bundle: { 'lodash': '_', 'backbone': 'Backbone'}
A Modules & Dependencies aware builder.
Exporting modules to window
/global
variables (like window._
, window.$
etc), demystified and with no boilerplate.
Want noConflict()
, baked in? Its a simple declaration away.
// file `uberscore.js` - export it to root (`window`) as `_B`
({ urequire: { rootExports: '_B', noConflict: true }});
module.exports = {...}
The same in a config is
dependencies: { imports: { root: { 'uberscore': '_B' }}}
How about exporting to your bundle only?
// inject `lodash` as `_` in (all) bundle's modules
dependencies: { imports: { 'lodash': '_' }}
Want to replace deps with mocks or alternative versions ?
Inject, replace or even delete dependencies with a simple declaration or a callback:
// underscore is dead, long live _
dependencies: { replace: { lodash: 'underscore'}}
// with code
function(modyle){ modyle.replaceDeps('models/PersonModel', 'mock/models/PersonModelMock'); }
[ '$coco', [ '**/*.co'], ((r)-> require('coco').compile r.converted), '.js']
A versatile in-memory Resource Conversion
Manipulate Module code while building:
inject, replace or delete code fragments or AST nodes or dependencies with one liners.
// delete matching code of code skeleton function(m){ m.replaceCode('if (debug){}') } // traverse matching nodes, replace or delete em function(m){ m.replaceCode('console.log()', function(nodeAST){return nodeOrStringOrUndefined}) }
Perform any code manipulation - eg remove debug code, inject initializations etc
Inject code before (or after) each module's body eg. to initialize custom module code, for common module tasks:
function(m) { m.beforeBody = "var l = new _B.Logger('" + m.dstFilename + "');"; }
Inject common or merged repeating statements: keep DRY, save space & speed when
combined
in a single.js
// each module will have before its main body, in all templates bundle: commonCode: 'var expect = chai.expect;' // added before beforeBody for all templates except 'combined', where its merged function(m) { m.mergedCode = '"var p1 = myModule.p1, p2 = myModule.p2, ..., pN = myModule.pN;"' }
Who needs bloated plugins ? Here's a ResourceConverter for our coco files (included along with coffeescript, LiveScript, iced-coffee-script.
[ '$coco', [ '**/*.co'], ((r)-> require('coco').compile r.converted), '.js']
['+inject:VERSION', ['uberscore.js'], (m)-> m.beforeBody = "var VERSION = '0.0.15';"]
A spartan Module builder & config
This 'uberscore'
config (coffeescript) will:
convert each module in
path
to UMD (default)copy all other files there
Allow
runtimeInfo
(eg__isNode
,__isAMD
) selectivelyinject
lodash
dep in each module as_
export a global
window._B
with anoConflict()
inject
'var VERSION =...'
before body ofuberscore.js
minify each module with UglifyJs2's defaults
add a banner (after UMD template & minification)
watch for changes, convert only what's really changed
// Config as a `Gruntfile.coffee` task
// Can be a .coffee, .js, .json, .yml & more
uberscore:
path: 'source'
dstPath: 'build'
filez: ['**/*', (f)-> f isnt 'badfile']
copy: [/./]
runtimeInfo: ['!**/*', 'Logger']
dependencies: imports:
bundle: 'lodash': '_'
root: 'uberscore': '_B'
resources: [
['+inject:VERSION', ['uberscore.js'],
(m)-> m.beforeBody = "var VERSION = '0.0.15';" ]
]
template: banner: "// uBerscore v0.0.15"
optimize: 'uglify2'
watch: true
{ derive: ['uberscore'], filez: [ /.*\.(coffee\.md|litcoffee|coffee)$/ ] }
Parent configs ? Lets derive!
The 'distribute'
config will:
derive (i.e deep inherit & modify) the above
filter some more filez
change template to 'combined'
output to a different filename
See more simple examples and a detailed real project
Lets derive some children
distribute:
derive: ['uberscore']
filez: ['!', /useRegExpsAsFileSpecs/]
template: 'combined'
dstPath: 'build/uberscore-combined.js'
optimize: uglify2: {more: uglify2: options}
`_.extend(window.libraryExported, exports)`
How about declarative, either per module or whole bundle:
have
window === global
, either in Browser or nodejs, at all timesruntimeInfo have
__isWeb
,__isNode
&__isAMD
always availableinject
'use strict;'
on all/filtered modules or combined bundle's closureinject
imports
&module
(along withrequire
), so you never miss 'em & solve any circular dependencies problems with AMD.and more :-)
All of these are tweaked to work in all templates, with the miminum required generated code.
build:
globalWindow: false
runtimeInfo: ['Logger']
useStrict: true
injectExportsModule: ['uberscore', 'circular/Dependency']
bare: true
allNodeRequires: ['/data/preCached']
noRootExports: true
scanAllow: false
How do I get started?
Read the Quick Introduction on using uRequire to modularize your code. See how trivial Using uRequire is. Learn more about Module Authoring and the Universal Module Format. Check out the wicked uRequire config and how to easily Convert Resources.