Search code examples
javascriptprototypejsrequirejs

RequireJS and Prototype


I am considering using RequireJS to organize my scripts into modules.

Basically, each of my scripts define a class var MyScript = Class.create({...}) (except the scripts in ext/ which are third-party libraries).

Taking a real-world example, how would I be able to organize those imports as modules?

<script type="text/javascript" src="js/ext/prototype.js"></script>
<script type="text/javascript" src="js/ext/scriptaculous.js"></script>
<script type="text/javascript" src="js/ext/effects.js"></script>
<script type="text/javascript" src="js/ext/carousel.js"></script>
<script type="text/javascript" src="js/lib/sanityChecker.js"></script>
<script type="text/javascript" src="js/lib/logger.js"></script>
<script type="text/javascript" src="js/ext/modernizr.js"></script>
<script type="text/javascript" src="js/lib/localStorageChecker.js"></script>
<script type="text/javascript" src="js/lib/domNavigationUtils.js"></script>
<script type="text/javascript" src="js/lib/externalLinkDetector.js"></script>
<script type="text/javascript" src="js/lib/gondola.js"></script>
<script type="text/javascript" src="js/pages/common.js"></script>
<script type="text/javascript" src="js/pages/homepage.js"></script>

I fail to understand what I should pass as an argument for my modules depending on Prototype (basically, every one of them).

Thanks in advance for your help !

Rolf


Solution

  • In your situation it would be a two step process:

    1. Use the requirejs shim to load third party libraries that aren't AMD compatible
    2. Modify your existing classes to use define

    For third party libraries that are not AMD compatible (such as Prototype) you will need to setup shim properties

    An example of that might be:

    require.config({
        baseUrl: 'scripts/',
        paths: {
            'prototype': 'lib/prototype',
            'scriptaculous': 'lib/scriptaculous'
        },
        shim: {
            'prototype': {
                // Don't actually need to use this object as 
                // Prototype affects native objects and creates global ones too
                // but it's the most sensible object to return
                exports: 'Prototype'
            },
            'scriptaculous': {
                deps: ['prototype'],
                exports: 'Scriptaculous'
            }
            // Add more third party libs/plugins and their dependencies
        }
    });
    

    For the Classes that you write you can use a pattern like the following:

    classes/SomeClass.js

    // Sugar syntax - http://requirejs.org/docs/whyamd.html#sugar
    define(function(require){
        require('prototype'); // Ensure Prototype is present
    
        return Class.create({
            initialize: function(name) {
                console.log('name');    
            }
        })
    });
    

    Should you need to extend any of your existing classes just require those as well and assign them to a variable.

    And to use it, just require the class from the page that needs it:

    page.js

    require(['classes/SomeClass'], function(SomeClass){
        new SomeClass('john'); // logs 'John'
    });
    

    Using the shim config option will allow you to use any non-AMD scripts without needing to modify them.

    One final note, Modernizr is not intended to be used as an AMD module as that script needs to run synchronously. So don't include that!