JavaScript module loaders and bundlers — Past, Present and Future.
The buzzwords — AMD, CommonJS, UMD, SystemJS, WebPack, Imports, Exports, have returned to town and you don’t know how to deal with them? Don’t worry — In this article, I will try breaking the ice with our friends so that our community can go back to happily ever after. To understand module loaders better, we need to be aware of how it all started.
The year was 2002 and it was a beautiful Sunday morning in East Palo Alto. Sam fired up his computer running Windows XP and created a new index.html file. At the end of the day, he had a huge index.html with 40 lines of inline javascript. The next day, he created individual files to separate features. He felt great about his refactoring skills but his sense of accomplishment was short lived as he realized –
- That he needs to make sure his order of JavaScript files is correct.
- That his variables were polluting the global namespace. In other words, if any app updated/overwrote his variables, his app will be broken.
But at the time, JavaScript did not receive all the love other programming languages received. Sam was unhappy for years. But his agony was about to end. After half a decade, organizations started to spring up to solve his concerns. CommonJS entered the scene and it defined a module format. Unfortunately, it was not suited for the browser as it entailed synchronous module loads.
Here is what happened as per James Burke, creator of Require.js –
“…it became clearer that CommonJS modules allowed an imperative require() usage, which is awkward on the web. Many cases would not work in a web context, and a better solution was to allow for a callback-based require for those cases. However, some of the participants on the CommonJS list wanted to keep the imperative use even in a callback-style require
…Kris Zyp created a proposal on the CommonJS wiki for an Asynchronous Module Definition (AMD) API
..There was enough break down in communication that it made it difficult to continue discussing AMD on the CommonJS list
…Through the amd-implement list, the callback-require and loader plugin APIs got more definition and a set of unit tests. More AMD implementations were made.
…AMD loaders gained traction in the jQuery community among those that wanted modular JS loading capabilities.”
Read the full story here.
Finally, after almost a decade, Sam was happily writing AMD modules. He was also ecstatic using require.js (an AMD loader) as it handled dependency management and loaded desired modules when required; asynchronously. He then stopped worrying about the order of .js files and was confident that his global namespace was pristine.
A couple of years went by and once again, a group from the AMD community were not truly satisfied. They hated the fact that their code has to be wrapped with a define and they also didn’t like parameters in the callback be in same order as the defined dependencies. Sam, however, was happy with AMD. He was pumping out reusable widgets, frameworks, applications and was bundling all of his solutions with r.js for minification and obfuscation. What a life he had! And then came Browserify. Browserify bundled code written with CommonJS format in a single file which can be used in the browser, a feat which was impossible before.
This split the community into two and yes, of course, there were gymnasts who practiced both patterns (because they were flexible).
Since there were multiple patterns floating around, in came the module police — UMD (Universal Module Definition). It basically defined an if-else common ground to please all practitioners. Task runners such as grunt and gulp have plugins to wrap your code in UMD. And as expected, Browserify, Webpack, Rollup.js also take in a config to generate UMD wrappers.
Sam was glad JavaScript was gaining steam not only in the front end but also in the backend. He was amused by the word ‘isomorhpic’, that he started writing modules for the front end and backend. And how did he bundle his apps — Browserify. A loyal friend of the AMD just got converted. But he promised that he will return to maintain and care for ‘legacy’ code. With browserify, he wrote code to work on all available environments by only providing –standalone config.
Usage: browserify [entry files] {OPTIONS}
Standard Options:
...
--standalone -s Generate a UMD bundle for the supplied export name. This bundle works with other module systems and sets the name
given as a window global if no module system is found.
Time passed and there was Angular, React, Vue and many more now fallen, falling titans. With them came a myriad of tools which even now sends developers down the rabbit hole. To fix the tools armageddon, another tool was introduced to scaffold common build and runtime workflows. Sam noticed a pattern –
- angular CLI used SystemJS but moved to Webpack.
- create-react-app uses Webpack
- vue-cli uses Webpack.
He also noticed blogs and articles praise advantages of Webpack. It’s a bubble, he thought at first but the comparison table was telling! He switched to Webpack for his newer projects and his life has never been better. The future? Sam whispers “Come what may, I know it is for the better.”
Originally published at javascriptstore.com on April 13, 2018.