The JavaScript Ecosystem Demystified


by Nick Wientge

A crash course for Meteor Developers

The JavaScript ecosystem can be a confusing place. With the rapid pace of progress on both the server-side and client-side it can be hard to keep up. And as Meteor developers, we’re often sheltered from a lot of this turmoil. But as Meteor continues to “embrace the ecosystem” by including ES6/ES2015 support, React and Angular integration - and in the future - ES6 modules, I think it’s important for Meteor developers to have a good understanding of the broader ecosystem.

Overview

For this article we’ll break down the various JavaScript tools into the following tasks:

  1. Installing and Managing Packages Package Managers (Bower, NPM)

  2. Requiring Modules from Packages Module Systems (AMD, CommonJS, ES6/ES2015)

  3. Making our ES6/ES2015 code compatible with ES5 Transpilers (Babel, Traceur)

  4. Making our Modules compatible with ES5 Module Builders (Browserify, Webpack)

  5. Putting It All Together (Compile, Preview, Deploy, etc) Build Tools (Gulp, Grunt)

1. Package Managers

Package Managers are used for installing and managing third party dependencies in your app.

Bower (Client)

In the dark old days of client side web development, the only way to utilize third party libraries was to scour the web looking for jQuery plugins and CSS frameworks and then manually copy those files into your project. Server-side developers had long had access to robust package management and dependency systems for their languages (Ruby, Java, Python) and Bower was introduced to bring that power to the client-side.

NPM (Server)

NPM stands for Node Package Manager. As its name suggests, it’s the package manager for Node.js. The advantage of NPM is the large number of community packages. The disadvantage is that NPM packages only run in Node.js, on the server.

Browserify (Client + Server)

Browserify isn’t a package manager, it’s a tool that allows you to use NPM packages in your client-side app. This allows you to use a single package manager (NPM) for both your client and server apps. The React community in general has embraced NPM as the package manager of choice for client-side React packages. We’ll talk about Browserify more later on in our Module Builders section.


Meteor: Package Systems

Meteor has it’s own package system, which you can browse on the web via Atmospherejs.com. It handles both client-side and server-side packages, as well as “isomorphic” packages that combine both.


2. Module Systems

Now that you’ve installed your dependencies, you’ll want to use a Module System for loading and using your third party dependencies in a “modularized” fashion. You can read more about why modularity is important in this great post by Addy Osmani.

AMD (The Past)

AMD stands for Asynchronous Module Definition. It was one of the first module systems for JavaScript and has been embraced by large open source projects like jQuery, Dojo, etc. It also heavily inspired the module system in Angular. Here’s what it looks like:

define('sayHello', function(name) {
  return function(name) {
    alert('Hi ' + name + '!');
  }
});
require(['sayHello'], function(sayHello) {
  let name = 'Nick';
  sayHello(name);
});

CommonJS (The Present)

CommonJS was created in an attempt to build a standardized module system for JavaScript. It is currently used by Node.js as its module system. As you can see below it is a much cleaner, simpler way of defining modules in comparison to AMD:

function sayHello(name) {
  alert('Hi ' + name + '!');
}

module.exports = sayHello;
let sayHello = require('sayHello');
let name = 'Nick';
sayHello(name);

ES6/ES2015 (The Future)

ES6/ES2015 introduces an official module system thats goal is “to create a format that both users of CommonJS and of AMD are happy with.” As you can see, the syntax is very similar to CommonJS:

exports function sayHello(name) {
  alert('Hi ' + name + '!');
}
import sayHello from 'sayHello';
let name = 'Nick';
sayHello(name);

Meteor: Module Systems

Meteor doesn’t currently use a module system, opting instead to automatically include files based on directory structure. This is great for new developers, but can quickly become frustrating for experienced developers who want more control. Fortunately, a future version of Meteor will include the native ES6/ES2015 module system.


3. Transpilers

ES6/ES2015 (in case you’ve been living under a rock) is the latest version of JavaScript that brings with it a bunch of handy features like object oriented Classes, less confusing variable scoping, and tons of fun and cool sounding tricks like “destructuring”. Unfortunately most browsers don’t support ES6/ES2015 yet. That’s where Transpilers come in. Transpilers allow you to write ES6/ES2015 code today, but “transpile” it to more widely compatible ES5 code.

Traceur

Traceur is a ES6/ES2015 transpiler From Google. In my research it appears it was one of the first transpilers on the scene, but hasn’t been widely adopted.

Babel

Babel (previously called 6to5) is one of the newer transpilers, and seems to have been widely embraced by the JavaScript community. In addition to transpiling ES6/ES2015 to ES5, it also includes built-in React/JSX support.


Meteor: Transpilers

As of version 1.2, Meteor automatically transpiles your ES6/ES2015 files using Babel.


4. Module Builders

Ok great, your fancy new ES6/ES2015 code is now being transpiled to ES5 so that it can run in your browser. The only problem is neither your ES5 code or the browser knows anything about requireing or importing files from a Module System. That’s where Module Builders come in. A Module Builder basically polly-fills a Module System to run in the browser.

Babel (ES6/ES2015 Module System)

Yep, in addition to transpiling ES6/ES2015 code, Babel can also transpile the ES6/ES2015 Module System to either AMD or CommonJS - your choice!

Browserify (NPM / CommonJS Module System)

Browserify describes itself as “browser-side require() the node way”. It allows you to use Node’s NPM packages in your client-side applications and include them in a CommonJS-style fashion.

Webpack (Any Module System)

Webpack is the workhorse of the bunch. I’ll talk more about Webpack later on as it is quite a bit more than just a Module Builder - but when it comes to modules, Webpack’s philosophy is to “Give the developer the choice of the module style. Allow existing code to work. Make it easy to add custom module styles.”


Meteor: Module Builders

Again, Meteor doesn’t currently use a Module System, so a Module Builder isn’t necessary. However Meteor currently endorses Browserify as part of its React support - due to the React community’s widespread use of NPM.


5. Build Tools

Whew. We have our third party dependencies installed from a Package Manager, imported them into our app using a Module System, converted our ES6/ES2015 code to more-widely-compatible ES5 using a Transpiler, and poly-filled our Module System using a Module Builder. So how do we put all these things together so that our code can run in a browser or be deployed to a server? That’s where Build Tools come in. Here’s a few things you might use a Build Tool to do:

  • Compile SCSS/Less to CSS
  • Watch for file changes and rebuild your app
  • Serve your files from localhost for development
  • Minify and concatenate your source files
  • Copy those minified files to a specific folder for distribution/deployment

Grunt

Grunt was the first JavaScript build tool (or Task Runner as it calls itself) to hit the scene. It includes a simple command line utility along with a straight forward way of specifying tasks in a Gruntfile.js file. Grunt’s strength came from the large number of plugins contributed by the community that allow you to do anything from compiling SCSS files to uploading files to S3.

Gulp

Gulp allows you to do essentially the same things as Grunt, but in a much more streamlined and easy to read format. A typical Gulpfile.js will often times be several times shorter than an identical Gruntfile.js. Whereas Grunt favors specifying tasks through large blocks of configuration, Gulp feels more like writing declarative code.


Meteor: Build Tools

Meteor handles these tasks for you behind the scenes. Again, this is great for new developers, but can sometimes be limiting for more experienced developers. Meteor 1.2 introduced a revamped build system that claims to be more flexible and provides better hooks to be extended by package authors. Personally, I haven’t researched the possibilities yet, but I’m excited to see how the Meteor community takes advantage of it.


Webpack: One tool to rule them all?

Webpack describes itself as a Module Bundler. So how’s that different than a Module Builder? Well here’s a short list of a few of the things Webpack can do:

  • Poly-fill the AMD and Common.js module system
  • Compile SCSS/Less to CSS
  • Watch for file changes and rebuild your app
  • Serve your files from localhost for development
  • Minify and concatenate your source files
  • Copy those minified files to a specific folder for distribution/deployment

Look familiar? Yep, Webpack is not just a Module Builder, but also includes several capabilities of a Build Tool as well!

Another interesting aspect of Webpack is that it isn’t just for loading JavaScript files, you can also require() images and CSS stylesheets. For React developers this lets you pull in everything you need into your components.

Webpack is still an early comer to the JavaScript ecosystem, but it seems to be gaining traction - especially amongst React developers - so it’s definitely one to keep your eye on.


Meteor + Webpack?

Again, Meteor makes most of Webpack’s features redundant. However if you are using React as your Meteor app’s front end, Webpack will allow you to take advantage of the large number of React packages on NPM, as well as some powerful tools like react-hot-loader. Check out the Meteor Webpack React repo on Github for an example of how you might integrate Meteor and Webpack.


Conclusion

It’s pretty impressive when you realize that Meteor abstracts away this entire complex ecosystem and packages it up nicely for you. On the flip side, by creating Meteor-specific alternatives rather than extending or contributing to existing solutions, I believe Meteor has in some ways ostracized itself from the larger JavaScript community which has potentially hindered its adoption. The following tweets by @tomdale from a year ago sum up the situation at the time nicely:

But with Meteor 1.2’s ES6/ES2015 support and React/Angular integration I think we’re seeing a more ecosystem-friendly Meteor evolve. As a Meteor developer I think it’s a great time to start exploring the larger JavaScript ecosystem and integrating some of these tools into your workflow.

Share Share on Twitter Share on Facebook Share on LinkedIn

How Can We Help?

Reaching out doesn’t mean you’re ready to start a project, but we’d love to learn more about the challenge you’re facing, answer any questions, and see if we might be a good fit for working together.

Contact Us