12

I am trying to load the Modernizr feature detects dynamically with requireJS.
As Modernizr has built in AMD support this shouldn't be a problem.

My requireJS configuration contains the paths to the Modernizr source directory and to the feature detects directory:

requirejs.config({
  paths: {
    "modernizr" : "components/modernizr/src",
    "feature-detects": "components/modernizr/feature-detects"
  }
});

Lets assume one of my views would require the svg test.
My view definition might look like this

define(["feature-detects/svg"], function() { .. });

Unfortunately the svg.js can't find Modernizr.js because all feature detects and Modernizr source files load Modernizr without specifying any directory: define(['Modernizr'], ...

Which results in a very ugly require.config

requirejs.config({
  paths: {
    "Modernizr": "components/modernizr/src/Modernizr",
    "addTest": "components/modernizr/src/addTest",
    "ModernizrProto": "components/modernizr/src/ModernizrProto",
    "setClasses": "components/modernizr/src/setClasses",
    "hasOwnProp": "components/modernizr/src/hasOwnProp",
    "tests": "components/modernizr/src/tests",
    "is": "components/modernizr/src/is",
    "docElement": "components/modernizr/src/docElement",
    "feature-detects": "components/modernizr/feature-detects"
  }
});

Is there a cleaner way to tell requireJS to search in components/modernizr/src/ whenever it couldn't find the file?

Update

I created an example github project which includes the basic setup and a running demonstration.

jantimon
  • 36,840
  • 23
  • 122
  • 185
  • Curious as to the reason for using AMD with Modernizr? You need the file to load synchronously so that the tests have run before the rest of the page renders. If I remember correctly, AMD was primarily chosen to aid the build process - https://github.com/Modernizr/Modernizr/issues/713 – Simon Smith Aug 08 '13 at 15:51
  • @SimonSmith I am using the requireJS `r.js` script to build my app into one file. It would be awesome if I could define modernizr dependencies using requireJS. – jantimon Aug 08 '13 at 19:15
  • I assume you're using something like Bower for managing assets, hence your `components` folder is not the same as the project folder (in other words, you can't use the `baseUrl` in RequireJS to point to Modernizer). Unfortunately, it seems like there is no easy way to add those dependencies and the way you solved it, is the only option. The alternative would be running `r.js` on Modernizer and then including the packaged file in your app. Still not great. – danielepolencic Aug 09 '13 at 21:46

3 Answers3

19

Modernizr's AMD structure is (currently) just for its own internal build process. We've discussed exposing this so that it can be used as you've tried, but haven't agreed on a convenient way to do this yet. A Modernizr plugin for RequireJS could be one option.

Are you using Bower? If so, it's worth noting Modernizr isn't suitable for use with Bower yet.

The recommended way to tie Modernizr into your build process at the moment is using grunt-modernizr, which will automatically find references to Modernizr detects in your code (or you can explicitly define them), then you can just use the resulting Modernizr build like any other AMD dependency whenever you need it:

define(['path/to/built/modernizr.js'], function (Modernizr) {
    if (Modernizr.svg) {
        ...
    }
});
Stu Cox
  • 4,486
  • 2
  • 25
  • 28
  • Thank you very much! If this is the only way by now I will switch to grunt. – jantimon Aug 14 '13 at 11:51
  • If I already have a custom build of Modernizr (got it with Zurb Foundation), how does it support AMD? I don't see any define() for the module. I see that there's a global variable attached to the window at the first line. Can you elaborate? – elanh Oct 10 '13 at 12:29
  • 3
    @elanh A built Modernizr script isn't AMD-compatible, so you should use a [shim config](http://requirejs.org/docs/api.html#config-shim). – Stu Cox Nov 03 '13 at 14:23
11

My suggestion would be to have a shim

Config

paths: {
    'Modernizr': 'PATH TO MODERNIZR'
},
shim: {
    'Modernizr': {
         exports: 'Modernizr'
    }
}

=================

You can use define in your script

define(['Modernizr'],function(Modernizr) {
    'use strict';

    console.log(Modernizr)
    // This should log the Modernizr function

    //For Example
    if(Modernizr.boxshadow){
        // Do something here
    }

});
Mohamed Rafi
  • 113
  • 1
  • 4
-1

If I understand your question correctly, wouldn't you just define your feature like so:

define([
    "modernizr",
    "feature-detects/svg"
 ], function(Modernizr) {
     Modernizr.addTest();
});

This way modernizr will be loaded before your feature detection code runs.

Matt Derrick
  • 5,674
  • 2
  • 36
  • 52