Search code examples
asynchronousjavascriptrequirejsjs-amd

Load requireJS module inline the HTML body?


I am integrating RequireJS in a CMS so I placed this on the bottom of my page template:

<html>
<body>
  {Placeholder1}
  <script src="scripts/require.js" data-main="scripts/main"></script>
  {Placeholder2}
</body>
</html>

Then on each page, I would like to create a function that leverages RequireJS. So I tried placing this on the bottom of the page:

<html>
<body>
    <h1>Home</h1>
    <div class="slider">Slider content</div>

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

    <script type="text/javascript">
      require([
        'jquery',
        'utils',
        'slider'
      ], function ($, utils, slider) {
        slider.start();
      });
    </script>
</body>
</html>

But I am getting 404's on jquery, utils and slider js files. It seems like it is not reading my main.js configs that I have:

require.config({
    paths: {
        jquery: 'libs/jquery-1.8.1.min',
        utils: 'libs/utils',
        slider: 'libs/jquery.slider.min'
    },
    shim: {
        slider: ['jquery']
    }
});

require([ 'utils' ], function (utils) {
    utils.init();
});

I tried loading RequireJS and main in the page head, but got inconsistent results that way. Sometimes jquery, utils and slider would be loaded in time and other times not. It is as if the inline "require" on the bottom of the page is not aware of the main RequireJS on page or the dependency rules, but my breakpoint hits in main.js so I know it is being called. Is it because main.js gets loaded asynchronously but my inline "require" block on the bottom of the page is loaded on page render? How do I get around this?

I have used RequireJS successfully before but without a CMS. I always used "define" and had modules always called asychronously, but never had to call RequireJS function inline like this. Any ideas on the correct way to do this?


Solution

  • The important thing here is that the config options are set before any modules are requested. As you have rightly identified, there are race conditions that mean the config options in your main.js aren't loaded in time. Simplest way round it would be to put the config options inline before the require.js script is loaded.

    <script>
    var require = {
        baseUrl: <?= $someVar ?>,
        paths: {
            // etc
        }
    }
    </script>
    <script src="scripts/require.js" data-main="scripts/main"></script>
    

    Further down the page:

    <script>
        require([
            'jquery',
            'utils',
            'slider'
          ], function ($, utils, slider) {
            slider.start();
          });
    </script>
    

    See also How does RequireJS work with multiple pages and partial views?