Skip to content

Javascript module loaders considered harmful?

Apparently, module loaders are a bad thing now, based on some obscure points, according to an article from @ironfroggy. None of the points mentioned in the article make sense, and here’s why.

Point #1: Confused debuggers

Compression, transpiling, and other pre-processing in the pipelines that typically support module loaders (which are not always necessary, but are in use in tandem consistently) rewrite scripts from the input module to the source that actually gets parsed by the browser. There is a frequent mismatch when debugging in the browser between your actual source and the code you see in the debugger.

No. There is not. A module loader is supposed to load your modules, as defined in the module loading standard it supports, it shouldn’t, and doesn’t transform your source files in any way, and if it does, then the standard is at fault here. Neither AMD, nor the CommonJS modules standard specify anything like this. There should be absolutely no mismatch between your source files, and what your browser receives.

Often times, even when the source is unchanged or the source maps work properly, the simple nature of the dynamic tags used by module loaders causes issue. Debuggers might not recognize the same script between page loads, without an inline script node, causing breakpoints to be lost, for example.

I have never, ever had Firefox, or Chrome lose breakpoints, and I’m trying to reproduce this, right now. I set a breakpoint in a dynamically loaded file, and no matter how many times I refresh the page and trigger the action associated with the file, the breakpoint stays there, and the program flow does break there correctly. It also works on different pages using the same file, so it’s not dependent on some kind of load order or anything. I simply cannot get Firefox or Chrome to lose my breakpoints, no matter what I try.

RequireJS does have an optimizer tool called r.js, that can concatenate/minify your files, (and it can generate source maps for you) but whatever you do with it, is up to you, it’s not a requirement to use the loader. If you want to debug your minimized files, you will obviously need source maps, but minifying and concatenating your js files is usually done as a build step, and even if you want to use it in a development environment, there is a shallowExclude option just for this.

Point #2: Module Load Order

Perhaps the single most common and frustrating thing to deal with in module loaders is the order of load or script execution. Compared to the expected load order of a series of script tags in your page, understanding when each module will be executed can be an exercise in frustration quickly.

I don’t know where that frustration comes from, but a) the logic that figures out the order is documented (at least for RequireJS), b) it does not matter at all what order your modules load in, as long as they are loaded in the order that their dependencies are satisfied. That’s exactly what a module loader does: it figures out the correct loading order, by looking at the dependencies of your files. The author seems to know this too, so I really don’t get the point here, because this is a beneficial thing, as this enables the module loader to load files in parallel. If I have file A that is dependant on file D, and I have file B, also dependant on D, then the only thing that matters, is that D is loaded first, and after that, there is absolutely no difference if A, or B loads first. If there is, then that means there is a dependency between A and B.

This point is complete moot.

However, the fact is that the vast majority of our projects don’t have such complicated intra-module dependencies to really justify this.

That may be a good point, but declaring something harmful because it does not fit your needs is silly.

Point #3: Workflow Complication

Simply put, using a module loader instead of simple scripts is simply harder to work with.

Using a module loader forces you to:

  1. keep the global namespace clean
  2. explicitly define the dependencies of your files, instead of relying on the exact loading order
  3. let’s you load your scripts in a performant manner, since it knows which modules can be loaded in parallel

If anything, this makes your code cleaner, and easier to work with. You can no longer just tack a script tag onto the end of your page, and that is exactly what you want to avoid by using a module loader.

There are well known difficulties integrating other libraries that don’t use the same module system. That there are multiple such systems makes this worse. Library authors are forced to provide extra wrappers for all the different loaders or pick a side when their users have or care not to.

There may be difficulties in supporting every format, but you don’t have to. This is exactly what Backbone did, they offered an AMD compliant version of their library in the beginning, but later reverted the decision to support it, because of the various formats they would have to support, and now they only offer the “vanilla” version officially. You can still load it with any loader, that supports some kind of shim loading, so the burden is now on the loader, and not the library authors.

There is an added barrier to use with little apparent benefit to a developer who just expected another script tag to their existing project

If a new developer complains that he can’t just add a new script tag into the project for a library he wants to integrate, then you slap him on the wrists. This script tag mess is exactly what we (we, as in the people who see module loaders as a blessing) want to get out of. This problem is not unique to module loaders at all, it’s also true for any kind of tool you choose to use for your project: it will increase the learning curve, and you have to educate people about it. You have to weight the time needed to get people up to speed working with it, vs. the time it saves you by using it.

Conclusion

The harms are not justified compared to the benefit when the majority of web applications utilize such a small and constant set of Javascript.

I would love to see what kind of statistics this claim is made on, without that, it sounds more like a “I didn’t find it useful, so it’s probably not useful for the majority”. I don’t see the point in any of the problems that the author listed, and I’m questioning if he actually understands what problems module loaders are trying to solve, when he makes claims such as “Costs of not using a module loader are incurred when you have a large enough body of code that loading all of it at the start of your app is detrimental to performance, user experience, or both.”. You don’t use a module loader for performance reasons, yes it can help you with that, but the main point is the cleaner code it helps you achieve, by the separation, and dependency managing it provides.

2 Comments

  1. Thanks for the very thought out response to my post. Now, I’m going to admit I wrote my post with some frustration. I definitely agree with the *idea* of modules and loaders in Javascript, but I think my love of them was kind of lost under all the complaining I did on their implementation and integration.

    Also, I tried to keep the post general and in doing so I did not highlight enough some of the real world issues that made them more difficult to deal with.

    This deserves a follow up post in which I plan to be a bit more thoughtful and clear and hopefully my position and feelings will be better communicated.

    Thanks again for the response!

    2014.02.22. at 22:22 | Permalink
  2. Glad to see I helped a bit, I’m looking forward to your follow up.

    2014.02.23. at 15:23 | Permalink

Post a Comment

Your email is never published nor shared. You can use [php][/php], [html][/html], etc. tags around your code blocks, and they will receive syntax highlighting.

Please solve this totally random captcha