Can someone provide some information about Module Loaders and Module Bundlers in JavaScript?
What are the differences?
When should I use a Module Loader and when a Module Bundler?
Why do we need them at all?
Module loaders and bundlers both make it more actionable to write modular JavaScript applications. Let me give you some background:
Module loaders
A module loader is typically some library that can load, interpret and execute JavaScript modules you defined using a certain module format/syntax, such as AMD or CommonJS.
When you write modular JavaScript applications, you usually end up having one file per module. So when writing an application that consist of hundreds of modules it could get quite painful to make sure all files are included and in the correct order. So basically a loader will take care of the dependency management for you, by making sure all modules are loaded when the application is executed. Checkout some popular module loaders such as RequireJS and SystemJS to get an idea.
Module bundlers
Module bundlers are an alternative to module loaders. Basically they do the same thing (manage and load interdependent modules), but do it as part of the application build rather than at runtime. So instead of loading dependencies as they appear when your code is executed, a bundler stitches together all modules into a single file (a bundle) before the execution. Take a look at Webpack and Browserify as two popular options.
When to use what?
Which one is better simply depends on your application's structure and size.
The primary advantage of a bundler is that it leaves you with far fewer files that the browser has to download. This can give your application a performance advantage, as it may decrease the amount of time it takes to load.
However, depending on the number of modules your application has, this doesn't always have to be the case. Especially for big apps a module loader can sometimes provide the better performance, as loading one huge monolithic file can also block starting your app at the beginning. So that is something you have to simply test and find out.
ES6/ES2015 Update
Note that ECMAScript 2015 (or ES6) comes with it's own, native implementation of modules. You can get a quick intro here and here.
Related
If you code an application using ES6 modules and classes, is there any need to use a module loader framework, or is the best practice to just use a build tool to concatenate all the code into a file (or files) and include those using a normal script tag?
Yes. Somebody, somewhere along the line has to load the module.
I think you're conflating compiling modules ahead of time vs loading them individually. Webpack is a module loader that outputs a single file for the browsers to use later, while the System API and requirejs et al load a number of individual files.
There are performance factors on both sides, particularly longer build time (when precompiling) vs longer load time (with multiple files).
Webpack, Browserify, and most other module loaders (with the notable exception of the System API) allow you to define some loaders for certain file types and automagically compile your (S)CSS or templates on the way through, as well as running other tools to uglify or obfuscate your code. The ES6 System API does not provide these features, but is a more robust runtime loader than most.
This boils down to two trade-offs:
support for non-JS modules (styles, templates) vs build time
single request and longer build vs many requests and short/no build
Evaluate them for your users (high-bandwidth vs mobile), environment (if you have two dozen CI agents, who cares if the build takes an extra 3s?), and stack (if you have a lot of template files, compiling them AOT could be important).
I read quite a few articles about requirejs and browserify. In 2 lines if one asks me to define it I will say.
AMD -> Client Side -> Implementaion : RequireJS -> asynchronous -> uese define keyword
CommonJs -> Server Side -> Implementaion : Browserify -> synchronous -> uses export keyword
What I want to understand is:-
Even being Server side why will one use browserify in client side?
When will you prefer one over other?
Webpack and Browserify don't replace requirejs directly, they replace the r.js optimizer that comes with require. Both modern bundlers run your code (and optionally stylesheets, templates, and other resources) through various filters, creating a single file with your whole application wrapped up.
RequireJS' asynchronous modules (AMD) has been replaced by the more commonly-used CommonJS and ES6 module definitions. This is, in part, so node modules play nicely with webpack and browserify, but also because the benefits of AMD largely stop applying when you have a single bundled file. Since all modules are available at the same time, you don't need the overhead of managing asynchronous loading.
Webpack and Browserify also expand on rjs' feature set, by adding extensive support for compiling templates, images, fonts, and other resources into your bundle. They can run transpilers (like Babel or Typescript), uglifiers, minifiers, and all sorts of other tools along the way. Webpack also supports outputting multiple bundles and loading them on-demand, while hiding most of those deployment details from the developer.
I'm approaching modules for the very first time and I'm a little bit confused.
I read from various docs that there are several modules systems, like commonjs (sync), and requirejs (AMD). From ES6 plain javascript has its own module sys, which is based on commonjs.
Then I started studying webpack, that resolves dependency using commonjs or requirejs module formats, and from here starts my confusion: as far as I understand, those two are module systems, they are designed to resolve the dependencies tree on its own; it's their purpose.
What is the sense to use the commonjs/requirejs format (aka syntax) and then implement webpack to resolve the graph?
CommonJS and AMD are both runtime module systems. Webpack is compiling your code, so you're not using it to resolve the graph specifically, you're using to create a build of an application from source files. To accomplish that, webpack 'understands' both types of modules so that it can analyze your code, identify dependencies, and bundle and optimize appropriately.
Webpack supports things that the original module systems don't: you can use more dynamic expressions to represent the module you're requiring; you can extend the require resolution behavior itself; you can specify an asynchronous runtime loading using its require.ensure syntax. Webpack's author could have defined a new module system to support these additional features, but then you'd have to rewrite all your existing source (and any third party modules) to accommodate the build tool. Instead, webpack is good about supporting whatever modules you already use, and giving you additional tools to handle more complex build needs.
So I've been building a single page web app for a while now and I've been writing all my code in an extremely modular approach. I've been using the javascript module pattern for all modules and my main API uses the revealing module pattern to expose a small API for plugins and other modules.
So even if I've been writing my code like this someone mentioned I should be using require.js as it gives a better modular approach.
I decided that require.js doesn't really make it more modular so my next thought was how require.js separates out dependencies. Require.js forces you to name dependencies in each module file. But this to me seems to be a task I have to do for every module and I have a lot of modules. At the moment all my files are concatenated into a single javascript file in my grunt build process so really all my files are loaded at the start. I need most of my modules loaded at the start so it made sense to do this.
So my question is... Should I use require.js even though my code is modular and all my files are concatenated together and loaded at the start? Do i need to worry about dependencies or loading order? Any help/advise or previous experience when dealing with this situation would really help. Thanks
Have you had annoyances putting <script> tags in the correct order to handle dependencies right?
Having a requirejs config file where you declare the third-party code and your own code dependency tree is a much more organised approach than declaring <script> tags by yourself.
When you are testing your app in dev environment, wouldn't be helpful to have all those modules in separated files that are easier to debug instead of all of them concatenated?
With requirejs you can switch between optimised/concatenated/minified code used in production environment and a list of independent files representing each module in the development environment.
Are you creating a global variable for each module in your app?
Requirejs avoids creating a global variable for each module so your global scope doesn't get cluttered.
It's usually a good practice to follow conventions in the way you declare modules. Requirejs implements AMD specification that is a well thought way of loading modules in client javascript.
http://requirejs.org/docs/whyamd.html
It's way easier to follow conventions if they're already implemented in a mature framework. And sometimes we don't notice but between apps we do the same thing differently and that affects in the maintenance phase.
Take a look at the requirejs optimizer. Look all the options it give you. It allows you to exclude files, to change versions of a given module, to change the minification tool, to integrate the optimization process with other tools like grunt or bower, etc.
http://requirejs.org/docs/optimization.html
If you don't need any of this, then just continue doing it in your way.
I've read a lot of articles on AMD solutions like RequireJS or module loaders that follow CommonJS style in Javascript.
Let's say I have an app splitted in this parts:
App definition that rely on the framework i use
Model 1 that rely on App definition and framework
Model 2 that rely on App definition, Model 1 and my framework
I may write each part as a RequireJS module or a common JS module and split my project in how many files I want but what's the advantage of writing each part as a module or splitting them in many files and then load them in the right order (to avoid dependency problems) maybe concatenatening all the files in a big one to reduce HTTP requets (as done by r.js optimizer)?
In my opinion, there are three rather important reasons:
You can create and re-use modules without polluting the global namespace. The more polluted your global namespace is, the bigger the chance of a function/variable collision. That means you define a function called "foo" and another developer defines the function "foo" = one of the functions gets overwritten.
You can structure your code into separate folders and files and requirejs will load them asynchronously when needed, so everything just works.
You can build for production. RequireJS comes with its own build tool called R.JS that will concat and uglify your javascript modules into a single (or multiple) packages. This will improve your page speed as the user will have to make less script calls and load less content (as your JS is uglified).
You can take a look at this simple demo project: https://c9.io/peeter-tomberg/requirejs (in cloud9ide).
To build your modules into a single app, all you have to do is have requirejs npm package installed and run the command: r.js -o build/build.properties.js
If there are any questions, ask away.
Edit:
In development, having all modules in separate files is just a good way to structure and manage your code. It also helps you in debugging (e.g. error on "Module.js line 17" instead of "scripts.js line 5373").
For production, you should use the build tool to concat and uglify the javascript into a single file. This will help the page load quicker as you are making less requests. Every request you make to load something slows down your page. The slower your page, the less points Google gives you. The slower the page, the more frustrated your users will be. The slower your page, the less sales you will get.
If you wish to read more about web page performance, look at http://developer.yahoo.com/performance/rules.html