Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 865
Basem Avatar asked Oct 02 '12 19:10

Basem


People also ask

How add RequireJS to HTML?

To include the Require. js file, you need to add the script tag in the html file. Within the script tag, add the data-main attribute to load the module. This can be taken as the main entry point to your application.

What is require () in JavaScript?

require() statement basically reads a JavaScript file, executes it, and then proceeds to return the export object. require() statement not only allows to add built-in core NodeJS modules but also community-based and local modules.

Is RequireJS still relevant?

RequireJS has been a hugely influential and important tool in the JavaScript world. It's still used in many solid, well-written projects today.

What is define in RequireJS?

The define() function can be used to load the modules (module can be an object, function, class or a code which is executed after loading a module). You can load different versions of the same module in the same page.


2 Answers

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?

like image 200
Simon Smith Avatar answered Sep 19 '22 08:09

Simon Smith


It seems like what is happening is that the main.js is being loaded asynchronously while the inline require is called right away. This is why there are inconsistent results. The solution is to NOT use the data-main attribute and call the main.js file via script tag underneath the require.js script tag.

You can still determine the baseUrl from the loaded main.js file by doing this in there:

//DETERMINE BASE URL FROM CURRENT SCRIPT PATH
var scripts = document.getElementsByTagName("script");
var src = scripts[scripts.length-1].src;
var baseUrl = src.substring(src.indexOf(document.location.pathname), src.lastIndexOf('/'));

//CONFIGURE LIBRARIES AND DEPENDENCIES VIA REQUIREJS
require.config({
    baseUrl: baseUrl,
....
like image 22
Basem Avatar answered Sep 18 '22 08:09

Basem