A Grunt wrapper around uRequire <>

npm install grunt-urequire
20 downloads in the last day
25 downloads in the last week
250 downloads in the last month

grunt-urequire 0.6.0


Grunt wrapper for uRequire, version >= v0.6.0

Requires grunt 0.4.x


config objects

uRequire config objects can become grunt tasks, as-is from the file format.


You can use grunt-contrib-watch v0.5.x watch task to invoke a partial build of changed files only.

Important notes:

  • You DO need watch: xxx: options: nospawn: true (or spawn: false on newer versions). This allows uRequire to use the already loaded bundle/modules information for rapid builds of only changed files.

  • You DONT need urequire: xxx: build: watch: true

  • NEW BEHAVIOUR IN 0.6: Each watch event is a partial build. The first time a partial build is carried out, a full build is automatically performed instead. You don't need (and shouldn't) perform a full build before running the watched task (i.e dont run the urequire:xxx grunt task before running watch: xxx: tasks: ['urequire:xxx']). A full build is always enforced by urequire to make sure everything is loaded and temp files of 'combined' almond builds are in place.


Simple example

Example config (using the uRequire >= v0.4.0 format) :

      myLibAsUMD: {
        template: "UMD", // default, can be ommited
        path: "lib/",
        dstPath: "umdLib"

      myLibCombinedToWorkEverywhere: {
        path: "lib/",
        main: 'myLibraryMain-Index',
        dstPath: "combinedLib.js"

      _defaults: {
        verbose: true,
        scanAllow: true,
        allNodeRequires: true,
        noRootExports: false
  • Note the new format - version 1.x grunt-urequire format should still be supported, but DEPRECATED.*

uBerscore Example

A more involved example (in coffeescript), taken from uBerscore.

Its also using grunt-contrib-watch to watch and build changed files as needed (partial build).

   ### NOTE: uRequire config is used as a testbed & example, thus so many comments :-) ###

    # The `'urequire:XXX'` tasks in summary do some or all of those
    #  * derive from 'someTask' (and/or '_defaults') with some differences
    #  * have a `path` as a source
    #  * filter `filez` within the `path`
    #  * save everything at `dstPath`
    #  * converts all modules to UMD/AMD or a single `uberscore-min.js` with `combined` template
    #  * copies all other (non-module) files at `dstPath`
    #  * export a global `window._B` with a `noConflict()`
    #  * uglifies combined file with some `uglify2` settings
    #  * injects deps in modules
    #  * injects strings inside code bodies
    #  * add banners etc
    #  * manipulate modules:
    #     * remove some matched code 'skeletons'
    #     * replace some deps in arrays, `require`s etc
    #     * remove some code and a dependency from a specific file.
      # @note any urequire task starting with '_' is ignored as grunt target
      # and only used for `derive`-ing.
      # These are the defaults, when a task has no 'derive' at all.
      # Use `derive:[]` to skip deriving it in tasks with no 'derive'.
          path: "#{sourceDir}"

          # include all but exclude some filez
          filez: [/./, '!**/draft/*.*', '!uRequireConfig*']

          # 2 ways to say "I want all non-`resource` matched filez to
          # be copied to build.dstPath"
          copy: [/./, '**/*.*']


            # 'util' will not be added to deps array, will be available only
            # on nodejs execution. Same as 'node!myDep', but allows module
            # to run on nodejs without conversion. Not really need,
            # `node` defaults to all known 'nodejs' core packages
            node: 'util'

            # export to bundle (i.e inject some dependencies to all modules)
            exports: bundle:
              # simple syntax: depsVars infered from dep/variable bindings
              # of bundle or other known sources
              ['lodash', 'agreement/isAgree']
              # precise syntax: deps & their corresponding vars
              #  {'lodash': ['_'], 'agreement/isAgree': ['isAgree', 'isAgree2']}

          # define some Resource Converters
          resources: [

            # example: declare an RC to perform some 'concat/inject' job.
              # Name this RC - note: '+' sets `isBeforeTemplate` flag:
              # this RC runs AFTER our Module's code is parsed and deps extracted/adjusted
              # right BEFORE running the template. Hence it  enables you do manipulate
              # the body & dependencies (it runs on Modules only).
              # Note: The `m.converted` IS NOT considered at this stage,
              # we are dealing with AST code & Module dependencies only.

              # note: '~' in name means `isMatchSrcFilename:true`, so its matching
              # ``, instead of dstFilename `uberscore.js`

              # Our `convert` callback, receives a Module instance
                # inject 'var VERSION=xxx' before the module's body code
                # m.afterBody also exists
                # inject any text (no need to be parseable code)
                m.beforeBody = "var VERSION='#{pkg.version}';"
                # no convFilename needed


          # 0 is default, 100 the max
          debugLevel: 0

          # false is default, auto enabled if debugLevel >= 50
          verbose: false

      # The `'urequire:UMD'` task:
      #  * derives all from `'_defaults'` with the following differences:
      #  * converts each module in `path` to UMD
      #  * everything saved at `dstPath`
      #  * adds a banner (after UMD template conversion)
        # `build` and `bundle` hashes are not needed
        # keys are safelly recognised, even if they're not in them.

        # 'derive' is also not needed - by default it deep uDerives all '_defaults'.
        # To avoid use `derive:[]`.
        #'derive': ['_defaults']

        # template is not needed - 'UMD' is default
        #template: 'UMD'

        # all files converted files are written here
        dstPath: "#{buildDir}"

        resources: [

          # example: perform some 'concat' job, AFTER the template conversion is done.
          [ # '!' means 'isAfterTemplate: true'
            # some description
            'concat/add banner to uberscore.js'
            # note we are looking to change the dstFilename `uberscore.js` (not ``).
            # We could have used ~ to match srcFilename
            # r.converted holds our converted UMD code,
            # since this RC runs AFTER the template conversion
            # no convFilename needed

      # a 'combined' build, - works with or without AMD loaders
      # on Web & nodejs as a plain `<script>` or `require('dep')`
        template: 'combined'

        # template: 'combined' requires a 'main' module.
        # if 'main' is missing, then main is assumed to be `bundleName`,
        # which in turn is assumed to be grunt's @target ('dev' in this case).
        # Having 'dev' as the, but no 'dev' module (or 'index' or 'main')
        # will cause a compilation error. Its better to be precise anyway,
        # in case this config is used outside grunt :-)
        main: 'uberscore'

        # the name of the combined file instead of a directory is needed for 'combined'
        dstPath: './build/dist/uberscore-dev.js'

      # The `'urequire:min'` task :
      #  * derives all from 'dev' (& '_defaults') with the following differences:
      #  * filters some more `filez`
      #  * converts to a single `uberscore-min.js` with `combined` template (r.js/almond)
      #  * uglifies the combined file with some `uglify2` settings
      #  * injects different deps in each module
      #  * manipulates each module:
      #     * removes some matched code 'skeletons'
      #     * replaces some deps in arrays, `require`s etc
      #     * removes some code and a dependency from a specific file.

        # need to specify we also need '_defaults', in this order.
        derive: ['dev', '_defaults']

        dstPath: './build/dist/uberscore-min.js'

        # doesn't have to be a String. `true` selects 'uglify2' with sane defaults.
        # It can also be 'uglify'.
        # Even more interestingly, u can pass any 'uglify2' (or 'uglify') keys,
        # the r.js way (
        # eg optimize: {uglify2: output: beautify: true}
        optimize: 'uglify2'

        # leave this file out (`filez` inherits its parent's `filez`, adding this spec)
        filez: ['!blending/']

        resources: [
            # An RC with the `isBeforeTemplate` '+' flag, runs ONLY on Modules
            '+remove:debug/deb & deepExtend'

            # All filez considered

            # `convert` function, passing a Module instance as the only argument
              # replace with nothing (i.e delete whole expression/statement)
              # any code that matches these code skeletons
              # Eg it matches `if (l.deb(30)){statement1;statement2;...}`
              # It MUST BE a valid Javascript String OR an AST sub-tree object
              # (only present keys are compared) - see esprima/Mozila AST parser specification
              for c in ['if (l.deb()){}', 'if (this.l.deb()){}', 'l.debug()', 'this.l.debug()']
                m.replaceCode c

              # Remove `deepExtend` key & dependency from this build
              # Since this RC runs on all Modules, limit to this one for efficiency
              if m.dstFilename is 'uberscore.js'

                # remove property/key `deepExtend: ...` from 'uberscore.js'
                m.replaceCode {type: 'Property', key: {type: 'Identifier', name: 'deepExtend'}}

                # actually remove dependency from all (resolved) arrays (NOT THE AST CODE).
                m.replaceDep 'blending/deepExtend'

                # With `isBeforeTemplate` rcs you can also :
                #   m.injectDeps {'deps/dep1': ['depVar1', 'depVar2'], ....}
                #   m.replaceDep 'types/type', 'types/myType'

      # uRequire-ing the specs: we also have two builds as 'UMD' & # as 'combined'

        # disable derive-ing from '_defaults'
        derive: []
        path: "#{sourceSpecDir}"
        copy: [/./]
        dstPath: "#{buildSpecDir}"

        # declarativelly inject these dependencies on all modules
        dependencies: exports: bundle:
          chai: 'chai'
          lodash: '_'
          'uberscore': '_B'
          'spec-data': 'data'

      # deep inherits all of 'spec' BUT none of '_defaults':-)
        derive: ['spec']
        dstPath: "#{buildSpecDir}_combined/index-combined.js"
        template: 'combined'

        # 'main' not needed: if `bundle.main` is undefined it defaults to `bundle.bundleName`
        # or 'index' or 'main' (whichever found 1st as a module on bundleRoot)
        # with the price of a warning! In spec's case, THERE IS a module
        # '' which is picked (with the price of a warning).
        #main: 'index'

      ### Examples showing off uRequire ###

      # EXAMPLE: how to reference (& `derive`-ing from) external urequire config file(s)
      # Its effectivelly equivalent to issuing:
      #  `$ urequire config source/code/ -o ./build/UMDFileConfigBuild -t UMD`

        # note: not deriving at all from '_defaults', unless its specified.
        derive: ['source/code/']

        # overriding some of its parent (config file) options
        template: 'UMD'
        dstPath: 'build/UMDFileConfigBuild'

      # EXAMPLE: building only a sub-tree of the whole bundle.
        # 'main' Not needed: `name` & consequently `main` inherit grunt's task/target 'Logger'
        #main: 'Logger'

        # We build only 'Logger' (& its dependencies) in a 'combined' build.
        # @todo: Its ineffiecient in urequire 0.6, cause ALL modules are converted to AMD first,
        #  and then used as input to rjs.optimize which picks only dependent ones.
        template: 'combined'

        # export the module on `window._L`, # with a `noConflict()` baked in
        dependencies: exports: root: 'Logger':'_L'

        # minify it with uglify2
        optimize: true

        dstPath: 'build/Logger-min.js'

      # EXAMPLE: replace a bundle dependency with another, perhaps a mock

        # derive from these two configs
        derive: ['UMD', '_defaults']

        # save to this destination path
        dstPath: "build/UMDreplaceDep"

        resources: [

          # first, create our hypothetical mock out of an existing module
          [ # a title with default flags
            "rename to 'types/isHashMock.js'"

            # a self descriptive RC.filez :-)

            # undefined `convert()` function - we only need to change the filename

            # convFilame is a String: the `dstFilename` will change to that, and all modules
            # in bundle will noe know this resource/module by its new name (AND NOT the old)

          # lets replace our dep
          [ # `isBeforeTemplate` flag '+', running on Modules only, just before Template is applied
            "+replace dependency 'types/isHash'"

            # run all on all matching `bundle.filez` (in all modules due to `isBeforeTemplate`)

            # call `m.replaceDep` in each module, passing old & new dep in bundleRelative format
            (m)-> m.replaceDep 'types/isHash', 'types/isHashMock'

      # EXAMPLE: replace a global dependency, whether existing in module code
        template: 'AMD'
        dstPath: "build/AMDunderscore"

        # defaults have a ['lodash',..]` - it will complain about 'lodash's
        # var binding, so use the '{dep: 'varName'} format
        dependencies: exports: bundle: 'lodash': '_'

        resources: [
          # although we inject 'lodash' in each module, change it
          # in modules  that still specifically may require it
          [ "+replace 'lodash' with 'underscore'", [/./]

            # note: `module.replaceDep` replaces all deps - even injected dependencies
            # in modules via `depenencies.exports.bundle` like lodash in this example.
            # The exception is 'combined' template, cause deps are NOT injected in modules
            # (they are available through closure). So if we were using 'combined' here,
            # we would need to change `depenencies.exports.bundle` to inject
            # the right ones (instead of just `replaceDep`-ing them).
            (m)->m.replaceDep 'lodash', 'underscore'

      # EXAMPLE: simple derivation
        derive: ['AMDunderscore', '_defaults']
        template: 'UMD'
        dstPath: "build/UMDunderscore"

      # EXAMPLE: marking as Resources, changing behaviors
        template: 'nodejs'
        filez: ['uRequireConfig*.*']
        dstPath: "build/nodejsCompileAndCopy"
        resources: [

          # EXAMPLE: compile a .coffee to .js, but dont treat it as a Module
          # marking a .coffee as 'TextResource' ('#' flag) is enough to compile as .js,
          # but exclude it from becoming a Module (i.e no UMD/AMD template is applied)
          [ "#~markAsTextResource", [""] ]

          # read file content, alter it & save under different name
            # Mark as a FileResource - its content is not read on refresh

            # matching `filez` for this RC is just one file

            # `convert()` function

              # calling read() on the resource read its content, using @srcFilename within `bundle.path`
              content = '\n' +

              # save() under a different name (relative to bundle.path) & changed content
     'changedBundleFileName.json', content

        files: ["#{sourceDir}/**/*.*", "#{sourceSpecDir}/**/*.*"]  # note: new subdirs dont work -
        tasks: ['urequire:UMD' , 'urequire:spec', 'mocha', 'run']

        files: ["#{sourceDir}/**/*.*", "#{sourceSpecDir}/**/*.*"]
        tasks: ['urequire:dev', 'urequire:specCombined', 'concat:specCombinedFakeModule', 'mochaDev', 'run']

        files: ["#{sourceDir}/**/*.*", "#{sourceSpecDir}/**/*.*"]
        tasks: ['urequire:min', 'urequire:specCombined', 'concat:specCombinedFakeModuleMin', 'mochaDev', 'run']

        # WARNING: urequire watch works ONLY with `spawn: false` (or nospawn:true in older versions)
        spawn: false
        # atBegin NOT WORKING: watch is not registered & __temp gets deleted.
        # Also occasional bug with grunt-watch causes constant rerun of tasks when mocha has errors
        #atBegin: true

        options: banner: '{"name":"uberscore", "main":"../../../dist/uberscore-dev.js"}'
        dest: 'build/spec_combined/node_modules/uberscore/package.json'

        options: banner: '{"name":"uberscore", "main":"../../../dist/uberscore-min.js"}'
        dest: 'build/spec_combined/node_modules/uberscore/package.json'

Look for more documentation on's docs.

npm loves you