==============
Grunt (>= 0.4.5 ) wrapper for uRequire, (>= v0.7.0)
Note: You 'll need npm install urequire
(version >- 0.7.0) already installed with your project - it comes only as a peerDependency
of grunt-urequire
.
uRequire config objects become grunt tasks as they are.
Using Grunt + uRequire saves you a huge amount of effort and the need for many grunt plugins + their tedious configuration. uRequire uses an in-memory conversion pipeline without the need for intermediate files and repetitive configurations listing the same source and destination paths all over again. Its like gulp on steroids.
You 'll keep it DRY (Dont Reapeat Yourself) and eliminate the need of many grunt plugins for tasks like compiling from coffee-script, coco, LiveScript etc, creating banners etc with grunt-contrib-concat
, minimizing with grunt-contrib-uglify
, watching with grunt-contrib-watch
, running hand written specrunners with grunt-mocha
and many many others.
All of these these features plus much more, become a single line of declarative uRequire config or the declarative invocation of a ResourceConverter
such as inject-version
or import-keys
or invoking an afterBuild
-er such as urequire-ab-specrunner
or urequire-ab-grunt-contrib-watch
.
Plus you can do many module, dependencies & code manipulation related tasks that no other task runner allows you to do, such as import
-ing, injecting or renaming dependencies, manipulating & merging common code and much more.
Ah, and did I mention full AMD, commonJS, UMD and combined (i.e all-in-one AMD, nodejs & </script>
) module transformation? Well, this is the primary goal of uRequire and it does it better that any other tool out there.
urequire:
_defaults:
path: 'source/lib'
main: 'myLibrary'
dependencies: imports: {'lodash': '_'}
resources: ['inject-version']
template: banner: true
UMD:
template: 'UMDplain'
dstPath: 'build/UMD'
dev:
template: 'combined'
dstPath: 'build/myLibrary-dev.js'
You can specify a derive: ['configname1', 'configname2']
to derive (inherit) from one or more configs.
The left most derive subconfigs (eg 'configname1'
) have precedence over others on their right.
Note that you also recursively inherit from all declared derive parent's and grand-parents etc as well.
Finally you can omit the Array [], if you derive only from one, eg derive: 'specs'
By default all sub-configs with an undefined derive
key, derive from _defaults
(if it exists) as in the example above.
If you do specify a derive
key (eg derive: ['UMD', 'production']
), you derive only those specified, but NOT from _defaults
.
If you want to NOT derive from an existing _defaults
and no other config at all, just use an empty array, i.e derive: []
.
Note that if you want to derive from one that implicitly derives fom _defaults
, you need to add _defaults
in its list of derive
s as well.
To solve the later situation, all configs irrespectively derive from _all
(if that exists), as the last implicit derive
.
As a summary, 2 + 1 rules:
a) an undefined derive
actually derives from ['_defaults', '_all']
, if any of those actually exist, in that order.
b) a specified derive
like derive: ['config1', 'config2']
actually becomes ['config1', 'config2', '_all']
(it omits _defaults
).
b2) a specified but empty derive
like derive: []
actually becomes derive: ['_all']
, if _all
exists at all.
Here's 3 different library
& 3 different spec
builds for the sake of the example:
urequire:
_all: # used by all irrespectively
dependencies: imports: { lodash: ['_'] }
template: banner: true
_defaults: # used only for lib
path: 'source/lib'
main: 'myLibrary'
resources: ['inject-version']
UMD:
template: 'UMDplain'
dstPath: 'build/UMD'
dev:
template: 'combined'
dstPath: 'build/myLibrary-dev.js'
min:
derive: ['dev', '_defaults'] # need `_defaults` specifically if (for some reason) we want
# to derive from 'dev', which implicitly derives from `_defaults`
dstPath: 'build/myLibrary-min.js'
optimize: 'uglify2'
spec:
derive: [] # doesn't derive from `_defaults`, only `_all`
path: 'source/specs'
main: 'specs-index'
dstPath: 'build/specs'
dependencies: imports: {'chai': 'chai'}
specDev:
derive: 'spec' # derive only from `spec` above and `_all` (not `_defaults`)
dstPath: 'build/specs-dev.js'
template: 'combined'
specMin:
derive: ['specDev'] # derive only from `specDev` (and consequently `spec`, followed by `_all`)
optimize: true
Note that urequire configs starting with a '_'
are ignored as grunt tasks - they are considered abstract configs and wont execute.
See the uRequire docs for deriving for more info.
You can use grunt-contrib-watch
v0.5.x that invokes a urequire:task target, issuing a partial build of changed files only.
You can do it in two ways:
The grand daddy way & boring way is to manually write it (DRY warning: with information already in your urequire config):
```coffeescript
watch:
UMD:
files: ['source/lib/**/*']
tasks: ['urequire:UMD']
options: spawn: false
```
Important note: Use watch: xxx: {options: spawn: false}
to allow uRequire to use the the already loaded bundle/modules information for rapid rebuilds of only changed files.
Use the auto configuring urequire-ab-grunt-contrib-watch
The simpler way is to have grunt-urequire
auto configure and invoke a watch task, since the paths & tasks information is already in your urequire config. Just use the special 'grunt-urequire'
keyword instead of true
for urequire's watch:
```
urequire:
UMD:
...
watch: 'grunt-urequire'
...
```
that auto configures and runs the above.
Is you want to pass grunt-contrib-watch
options use this syntax:
```
watch:
info: 'grunt-urequire'
debounceDelay: 1439
someOtherGruntContribOption: 'value'
```
but be warned that atBegin: true
and spawn: true
should not be set.
You can pass more options to urequire-ab-grunt-contrib-watch
, like any grunt (or grunt-urequire) tasks that run before
or after
the current task at each watch cycle, or other files
to be watched and trigger a watch cycle if they change:
```
urequire:
UMD:
path: 'source/code'
watch:
info: 'grunt-urequire'
before: ['clean:cache', 'concat:useless'] # an `Array` of grunt tasks
after: 'urequire:spec zip:UMD email:me' # a `String` with space separated grunt task is also fine
files: ['some/path/files/**/*', ...]
spec: ....
```
If the task is a urequire:someTask
, then its bundle.path
as a files pattern is added to grunt-contrib-watch
files automatically.
For more information see urequire-ab-grunt-contrib-watch
that is powering the auto grunt-contrib-watch
feature.
Manually configuring watch
, mocha
tasks and phantomjs, requirejs/AMD & all their relative paths, configs, shims, HTMLs etc against each different build, can be a huge pain. You 'll find repeating your self too much, fiddling with what paths work and what breaks, instead of writing awesome libs and specs.
So do check out the urequire-ab-specrunner afterBuild
-er which uses the uRequire bundle
& build
information already in your urequire config, auto discovers the bower paths and automagically generates, configures and runs your specs against a lib.
It works perfectly with watching through grunt-contrib-watch
, which you dont need to configure at all. And it knows if your bundle sources really changed or if build failed, so it wont run the specs until resolved or really changed.
All with a single declaration, no other configuration! It even auto generates the SpecRunner HTML, the RequireJs config & paths (or depending on the templates used the <script src='../../../tedious/paths/to/somedep.js'/> that still respect the requirejs config's shim
) and runs them!
All you 'll need is:
```coffeescript
specRun:
derive: ['spec']
dependencies: paths: bower: true
afterBuild: require('urequire-ab-specrunner')
```
or just add the afterBuild: require('urequire-ab-specrunner')
to spec
so that all specXXX
inherit it, and hit $ grunt UMD specMin
.
Add a watch: true
to your config, and watch
-ing starts automatically after the first build (it actually auto configures and invokes grunt-contrib-watch
) through urequire-ab-grunt-contrib-watch
just like grunt-require
does with 'watch: 'grunt-urequire'
).
For all config options check out the documentation at uRequire.org.
Check out urequire-example & uBerscore for a full working examples.