Building a custom RequireJS
Rohan Bagchi
Posted on September 5, 2022
RequireJS works on the principle that we can define functions that depend on values returned by other functions. This helps us write modular code. Here, we will assume all functions are in a single file.
The ask goes like this:
define('moduleName',function(){
return 1;
})
require(['moduleName'],function(module1){
console.log(module1) // 1;
})
Here, we add dependencies using define
and functions
using require.
1st param to require
is a dependency array. Dependencies can be registered using define
function.
Sometimes we can also require beforehand and then define functions. Once all dependencies are resolved, the user defined callback will be triggered automatically.
First let us declare module level variables to hold our results, dependencies and a registry of functions
to dependency mapping.
const fnMap = {}; // mapping between a dependency function name to actual function reference
let registry = [] // list of functions and the names of their dependencies
const resultMap = {}; // mapping between dependency name and it's return value
Now that we have the vars, let us define define
:)
function define(name, cb){
fnMap[name] = cb;
const unresolvedRegistryItems = registry.filter(({ cb: userDefinedCb, dependencies }) => {
const unresolvedDeps = dependencies.filter(dependencyName => {
const fn = fnMap[dependencyName];
return !fn;
});
if (unresolvedDeps.length === 0) {
require(dependencies, userDefinedCb);
} else {
return true;
}
});
registry = unresolvedRegistryItems;
}
As you can see, we are first recording the dependency in fnMap
and then checking the registry
for functions
whose all dependencies are resolved. If so, we are triggering the require
(to be implemented).
Finally, we update the registry
list with the filtered list containing only functions with unresolved dependencies.
Let us now define require
function require(dependencies, cb){
const results = [];
let isResolved = true;
for (let i = 0; i < dependencies.length; i++) {
const dependencyName = dependencies[i];
const fn = fnMap[dependencyName];
if (!fn) {
isResolved = false;
registry.push({
cb,
dependencies
});
return;
}
const result = resultMap[dependencyName] || fn();
results.push(result);
resultMap[dependencyName] = result;
}
isResolved && cb.apply(null, results);
}
Finished product:
Posted on September 5, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024