Andrew
Andrew

Reputation: 14526

Using requirejs synchronously

I have a requirejs project that has been optimized into a single file, which I am loading synchronously. The code loads as expected, but the modules are still loading asynchronous (they aren't available until later in the loading process) and it's causing problems for some legacy code I'm hoping it will work with.

Given the code below, is there any way of making main-build's methods available immediately after loading, before legacy_code.js is loaded?

<script type="text/javascript" src="/scripts/vendor/require.js"></script>
<script type="text/javascript" src="/scripts/main-build.js"></script>

<!-- At this point, the code is set up and it will be invoked later -->
<!-- ...but the next file requires to access methods in the modules.-->

<script type="text/javascript" src="/script/legacy_code.js"></script>

If worst comes to worst, I can write my own versions of define() and require() (which would also free up a lot of bandwidth since all it would need to do is catalogue and invoke the modules), but I'm hoping there's a built-in way to do this.

Upvotes: 1

Views: 4657

Answers (2)

Andrew
Andrew

Reputation: 14526

Answering my own question here. After looking around a long while, I can't see any way to load Requirejs code synchronously or invoke modules immediately after loading. So I ended up writing some code to temporarily overwrite require and declare methods. It works for my use case, but may require changes if anyone else needs it. I'm sure it can be optimized more than it is right now, but it works.

You can find the code on GitHub, which I will try to maintain.

The code at this point looks like this:

(function () {
    var self = {},
        originalDefine = window.define,
        originalRequire = window.require,
        modules = [];

    var define = function (id, deps, fn) {
        if (id !== 'requireLib' && id !== 'text') {
            modules.push({"id": id, "deps": deps, "fn": fn});
        }
    };



    var require = function (deps, fn) {
        var sortedModules = [],
            unsortedModules = [],
            resolvedDeps = {},
            maxAttempts = 1000,
            module,
            dep,
            depList,
            canAdd,
            i,
            j;

        unsortedModules = ([]).concat(modules);
        while (unsortedModules.length > 0 && --maxAttempts > 0) {

            for (i = unsortedModules.length - 1; i >= 0; i--) {
                canAdd = true;
                module = unsortedModules[i];

                for (j = 0; j < module.deps.length; j++) {
                    dep = module.deps[j];
                    if (resolvedDeps[dep] === undefined) {
                        canAdd = false;
                        break;
                    }
                }
                if (canAdd) {
                    resolvedDeps[module.id] = module;
                    sortedModules.push(unsortedModules.splice(i,1)[0]);
                }
            }
        }

        for (i = 0; i < sortedModules.length; i++) {
            module = sortedModules[i];
            depList = [];
            for (j = 0; j < module.deps.length; j++) {
                depList.push(resolvedDeps[module.deps[j]]);
            }
            resolvedDeps[module.id] = module.fn.apply(this, depList);
        }

        depList = [];
        for (i = 0; i < deps.length; i++) {
            depList.push(resolvedDeps[deps[i]]);
        }

        fn.apply(this, depList);

        window.define = originalDefine || function () {};
        window.require = originalRequire || function () {};
    };

    window.define = define;
    window.require = require;
    window.require.config = function() {};

    return self;
} ());

Upvotes: 1

chrisfrancis27
chrisfrancis27

Reputation: 4536

The easiest way to do this, without having to override define() and require(), would surely just be to wrap your legacy code in an AMD and specify your main-build.js module definition as a dependency.

I know the isn't technically 'synchronous', but it should achieve what you are looking for - the legacy code is only invoked after the require modules have loaded.

Upvotes: 0

Related Questions