41

I'm looking into RequireJS but I'm uncertain about some things.

I understand how I can load all my dependencies with main.js. But do I need to add any logic to work with those dependencies in main.js?

To me, main.js seems like a document.ready state and you enter logic there when the document has loaded, right?

And for other pages and partial views, do I need to create multiple main.js or can I just reference loaded functions in dependencies from the views in a <script> for example?

Johan Alkstål
  • 5,225
  • 9
  • 36
  • 48

2 Answers2

93

Update - I've added an example of using RequireJS with modular HTML components. Build tool example included - https://github.com/simonsmith/modular-html-requirejs

I have also written a blog article about this - http://simonsmith.io/modular-html-components-with-requirejs/


The approach of just using main.js for everything is probably more suited to a single page application.

The way I've handled this situation is to only include common site-wide JS in the main.js file:

On every page:

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

main.js

require.config({
// config options
});

require(['jquery', 'common/ajaxLoader', 'common/someOtherModule'], function($, ajax, otherModule) {
    // Modules that do stuff on every page are instantiated here 
});

page1.html

<script>
    require(['scripts/page1']);
</script>

page1.js

require(['jquery', 'page1Module'], function($, module){
    // page1 specific stuff here
});

The above example is just one of a couple of ways to handle it. Note the difference between loading a plain JavaScript file and a module.

A rule of thumb I follow is to keep all reusable modules (or Classes if it makes it easier to conceptualise) inside a define with their own dependencies etc and then use require to grab those modules, use their methods or interact with them in some way.

Using this pattern will almost certainly require use of the domReady module that is a separate plugin for RequireJS. Use this instead of a ready function in jQuery for example, as it allows modules to begin downloading before the DOM is ready which reduces the wait for your code to execute.

Edit You may wish to see another example of multi-page application in the RequireJS repo

Simon Smith
  • 8,024
  • 2
  • 30
  • 40
  • Thanks for the very well written answer. I have a better understanding of how to use RequireJS now. – Johan Alkstål May 30 '12 at 19:44
  • the above method works perfectly on pages, but when the page loaded via ajax call into a div , the modules are not loading.. any help ? – Vijayant Katyal Oct 18 '12 at 10:12
  • 9
    This approach doesn't appear to be completely reliable because the code in the inline script tags may well be executed before the code in main.js, leading to occasional failures. See [this answer](http://stackoverflow.com/a/14345709) to a related question. – Rob Smallshire Feb 24 '13 at 14:32
  • 1
    This is true and since answering the question I tend to inline my config options or possibly `main` could be listed as a dependency inside `page1.js`. I need to test that approach though. – Simon Smith Feb 25 '13 at 09:53
  • 1
    I agree with most of this, but I wouldn't inline the `require` call for the page script. Seems like a bad practice for several reasons. – Esteban Araya Oct 25 '13 at 04:27
  • @EstebanAraya could you elaborate your answer? As Simon Smith said above, setting the require common modules that are commonly loaded at main.js as dependencies of page1.js will ensure that page1.js is loaded with all it's depencies ready. Why do you consider this a bad practice? – Lothre1 Jan 06 '14 at 10:30
  • Absent from this answer (but in my blog post/repo) is the practice of wrapping the page require call in another require that loads main. This way you can be sure the deps will load in correct order. Duplicate modules can be excluded at build time. – Simon Smith Jan 06 '14 at 16:52
  • if page1 needs stuff from main then put that as a dependency. If page1 stands alone, then not needed and you can load main and page1 in parallel (which is the point) – dalore Jul 29 '15 at 10:10
3

I have recently gone through the exercise of setting up RequrieJS with automatic build optimization in an ASP.NET MVC application. There are a lot of helpful blog articles such as Simon's that are a great reference. From an ASP.NET perspective one of the most useful I found in terms of configuring the RequireJS optimizer for multi-page ASP.NET applications was Making RequireJS play nice with ASP.NET MVC.

Using the great information already out there I have put up my own ASP.NET MVC RequireJS example on GitHub. Much of what is included is similar to examples already out there, however to address the issue of partial views, and multi-page require dependencies I have taken a slightly different approach.

_Layout.cshtml

The most notable difference from existing examples is the creation of a custom RequireViewPage that exposes methods to pass configuration data to RequrieJS as well as reference page specific require dependencies.

So your _Layout.cshtml will look much like what you'd expect with:

<head>
    ...
    @RenderModuleConfig()
    <script type="text/javascript" src="@Url.Script("vendor/require.js")" data-main="main"></script>
</head>
<body>
    ...

Views & Partials

To wire up views (and in my case knockout view models), an additional script fragment has been added to the bottom of _Layout.cshtml as follows

    ...
    @RenderSection("scripts", required: false)
    <script type="text/javascript">require(['main'], function () { require(['lib/knockout/knockout.require']); });</script>
</body>

This will ensure that for any view dependency, the main module has been loaded (assuming dependencies for main have being defined in main.js and then allows for view specific dependencies to be wired up via data attributes.

<div data-require="@MainModule"> ... </div>
<div data-require="@Module("address")"> ... </div>
<div data-require="view\home\index\model"> ... </div>

For a full explaination of the design and choices, see the README on GitHub

Chris Baxter
  • 16,083
  • 9
  • 51
  • 72