Ok to start off, The JavaScript is executed in the order you have defined it in the document, either its a piece of code or a physical file the script tag points to, but the complete parsing depends on the file size and network response hence multiple files start off in ascending order as defined and finish loading at different time intervals.
You can make script loading asynchronous by using defer and async attributes. Link.
To understand the execution flow checkout this stackoverflow link who has similar piece of code using jquery.
To get a clear answer to your question please read below to get a clear picture of respective libraries
RequireJS (AMD):
RequireJS lookup firstly happens by name of the JS file defined in config in entrypoint or as dependency defined in array of require methods.
Please read this link RequireJS
For example let see the below code:
bundle.js
define("X", [],function(){ //named definition without any dependencies.
return function() {
alert("Loaded");
}
});
index.html
<body>
<script src="require.js" type="text/javascript" charset="utf-8"></script>
<script src="bundle.js"></script>
<script type="text/javascript">
require(["require", "X"],function (require) { //"X" is defined in the array of require definition
var X = require("X");
X();
});
</script>
</body>
All the dependencies are wired-up with a callback in AMD to solve the loading time difference, in the sense these modules are made available when the callback is executed with the required modules loaded in the memory.
Browserify:
Emulates the Node JS module loading for client side on the browsers.
How stuff works:
Extra build step does the trick in concatenating all the dependency function definition that will be made available before require functions. All the code file are bundled into one single file which becomes available in a single scope at the runtime. Similar can be achieved in RequireJS using r.js optimizer.
Please read this link about browserify
Example code for illustrations:
mod1.js:
module.exports = function(){
alert("Loaded");
};
Build command:
browserify -r ./mod1.js:mod > bundle.js
This generates a file called bundle.js with a module name mod which can be included in the index.html as below
<body >
<script src="bundle.js"></script>
<script type="text/javascript">
(function () {
var X = require('mod');
X();
})();
</script>
</body>
Here browserify stiches all the JS file starting from entrypoint code (Here its mod1.js) and recursively searches for require api and construct a closure scope on top of these modules.
Hence your bundle.js looks as below
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"mod":[function(require,module,exports){
module.exports = function(){
alert("Loaded");
};
},{}]},{},[]);
Conclusion:
Browserify: Functions are loaded at one shot as all the files are concatenated into one single JS file. Hence all the definition and functions share the same closure scope and get initialized and made available in the memory. When you require a module definition-> If its a variable the value is returned or if its a function then pointer the function is returned where you can make a functional call.
AMD as RequireJS: This is quite different comparatively as the files are loaded on require call execution at runtime, which later executes the callback attached to that require definition once all the dependencies are resolved.
Hence in this method memory is overloaded with functions progressively as and when require call happens (this is called as Lazy - loading).
Note:
r.js is requireJS plugin used to optimize and concat all the JS file, same as browserify.