StackOverflower
StackOverflower

Reputation: 5761

How let users to access requirejs modules outside main?

I'm implementing an AMD module oriented js framework that will be used on third party sites.

With this line, framework users will configure necessary modules

<script data-main="/main.js" src="/require.js"></script>

The problem is that data-main reference is loaded asynchronously so any js logic depending on modules loaded by main.js would fail unless I can be sure that it finished loading.

I'm pretty new to requirejs so not sure what's the good practices to create a framework that will be used by other people.

How could resolve this very simple problem?

EDIT An example to explain my point

main.js

requirejs.config({
    paths: {
        jquery: '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min',
    }
});

main js reference + extra code

 <script data-main="/main.js" src="/require.js"></script>
 <script>
    require(['jquery'], function($) {
        // since main.js is not loaded yet, it will assume that there is a jquery.js 
        // file on the same folder that this file
        console.log('myModule was also loaded and can use jQuery');
    });
 </script>

Upvotes: 1

Views: 1804

Answers (2)

squid314
squid314

Reputation: 1395

If you want to depend on other libraries and are specifically targeting being in a Require pipeline, all you need to do is to declare some dependencies with

define(
    'myModule',    // module name
    ['foo'],       // module dependencies
    function(foo){ // module construction
        var myModule = {};

        .... code to set up the module ....

        return myModule;
    });

and Require will take care of things. This will register your module with Require and won't attempt to build your module until all of your dependencies are available. This functionality is discussed here.

Update with example

Require JS is designed to work both with and without a prebuilt configuration. The paths property of the Require config object only provides Require with information on how to attempt to find libraries which have not yet been registered. However, the registration and then dependency resolution is handled by Require regardless of how/where the module was registered. Please see this JSFiddle for a working example of how you can register and use dependencies.

Update 2 regarding config

Since RequireJS loads everything asynchronously, you are correct, your code example will not work. However, you're making an incorrect assumption about how it is "supposed" to work. You have an incorrect example of what your library's clients' Require configuration will look like. If someone else is building an application using RequireJS and they want to use your library, they should declare the path to your library in their require.config:

require.config({
    paths: {
        // this tells require how to load jQuery (a library maintained neither by you nor your clients).
        'jquery': '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min',
        // this tells require how to load myModule (the library you are building for your clients).
        'myModule': '//example.com/js/my-module.min',
        // this tells require how to load foo (a library built and hosted by your clients).
        'foo': 'scripts/foo'
    }
});

On the other hand, if your clients can't update their Require config to include your library in the declarations, then you're out of luck. All you can do is take all of your dependencies and bundle them up in your distribution file and then declare no dependencies:

define(
    'myModule',
    [], // can't declare any dependencies
    function() {
        // these dependencies are inside of the definition function to keep the global namespace clean
        // since we need jQuery, we have to inline it:
        var jQuery = ....
        // same goes for d3.js
        var d3 = ....

        // now we can set up the module itself
        var myModule = {};
        .... code to set up the module ....
        return myModule;
    }
);

Obviously, this option means that you can't use the libraries which are being used by your clients. This means your library will be a lot heavier and include effectively duplicate code and data.

Hope that helps you understand how Require works and how other people will use your library.

Upvotes: 3

StackOverflower
StackOverflower

Reputation: 5761

I've finally used this approach

<script src="http://mydomain/js/require.js"></script>
<script>
requirejs.config({  
    baseUrl: 'http://mydomain/js' 
});
require(['main'],function(){
    // here users can do anything they want as all required libraries are loaded
});
</script>

main.js is loaded with a require instruction instead of using data-main attribute from script tag , this provides a callback where users can put their code.

Upvotes: 1

Related Questions