1

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.

2 Answers 2

1

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;
} ());
Sign up to request clarification or add additional context in comments.

4 Comments

too bad that it doesn't work synchronously as expected : plnkr.co/edit/ErIS1MCgS9vcxEnw9AKt?p=preview
Require uses AMD syntax for module loading, not Common.js syntax. See the docs for usage information. Unless you are working with an AMD project, I don't suggest starting using it: common.js pretty much won the module war.
Do you know any library which can load modules using commonjs but(!) Synchrnously ?
I can't really help. I don't have much experience with CommonJS (I was on the losing side of that modules war). In theory though, if you believe your module is capable of being run synchronously (i.e. if its members and all of its dependencies are available immediately after declaration) then you probably can do it by compiling your application into a single CJS bundle. Or write your code as a module and make it available after its dependencies are available. A more modern solution is to use Webpack as a development tool and production bundler.
0

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.

1 Comment

In this case, it's not possible. The legacy_code.js actually is on dozens and dozens of pages and is unique to each page. What I'm doing now is to set up a sort of Facade pattern that replicates the old legacy code and simply records the calls so they can be executed later when the modules are loaded, but it struck me as backward to do it this way because the modules are clearly already present and should be accessible to as soon as main-build.js has been loaded.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.