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?
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.
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.
RequireJS has been a hugely influential and important tool in the JavaScript world. It's still used in many solid, well-written projects today.
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.
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?
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,
....
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With