DEV Community

Rohan Bagchi
Rohan Bagchi

Posted on • Originally published at rohanbagchi.hashnode.dev

Building a custom RequireJS

Building a custom RequireJS

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;
})
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

Finished product:

Sentry blog image

How to reduce TTFB

In the past few years in the web dev world, we’ve seen a significant push towards rendering our websites on the server. Doing so is better for SEO and performs better on low-powered devices, but one thing we had to sacrifice is TTFB.

In this article, we’ll see how we can identify what makes our TTFB high so we can fix it.

Read more

Top comments (0)

Neon image

Next.js applications: Set up a Neon project in seconds

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Get started →

👋 Kindness is contagious

Dive into this informative piece, backed by our vibrant DEV Community

Whether you’re a novice or a pro, your perspective enriches our collective insight.

A simple “thank you” can lift someone’s spirits—share your gratitude in the comments!

On DEV, the power of shared knowledge paves a smoother path and tightens our community ties. Found value here? A quick thanks to the author makes a big impact.

Okay