What Do the Popular JavaScript Tools Depend On?

My aim in writing this article is simple: I'm going to loosely describe what I am calling the "hard'ish dependencies" (I'll define what I mean by "hard'ish dependencies" momentarily) for the following JavaScript tools:

  • jQuery
  • Angular 2
  • Angular 1
  • React
  • Aurelia
  • Ember
  • Vue.js

Now, when I say "hard'ish dependencies," what I mean is anything third-party that is required for the most basic usage and grokking of the tool as a production solution. And, yes, I realize these are not the same types of tools and that comparing their dependencies isn't exactly comparing apples to apples. Still, one should be aware of these details when picking tools of this nature.

The Purpose of This Exercise

So why do this? Well, two reasons. First, believe it or not, gathering all of this information into one spot for quick consumption isn't trivial. I've found myself wanting to mentally compare these dependencies in the past and couldn't easily Google my way to an immediate answer. So, I am scratching my own itch here, to some degree, by writing all this down.

Second, I want to inform and educate developers about the hard'ish dependencies they'll have to learn when choosing a solution (some up-front, though others down the road). This will allow them to make an educated decision pertaining to the potential overhead of learning a tool in-depth. Yes, yes, I know not all these dependences will will have to be learned right away, but walk long with any solution and the dependences will more than likely require mastery.

I am not going to spend much time discussing commonly used "soft dependencies." While many soft dependencies, pragmatically, are hard dependencies, I'll refrain from clouding the issue with too much of a semantical debate about what might not be technically required but pragmatically required (e.g. Angular 2 and TypeScript or React and Babel).

Let's begin with jQuery, since it was the first mainstream JS tool. And, even today, remains the most used JS tool on the web.

Screenshot-2016-07-15-15.43.44

Screenshot-2016-07-15-15.41.44

jQuery

Depends on: Nothing

Poor jQuery. Today, it is slighted for not being what it never was: a tool to build complex applications. jQuery, by design, was a tool to script simple web pages and simple applications residing in simple web pages.

This is why I mention it in this article. Because, the truth is, a lot of simple apps (little or no state) could be built as simple web pages (rather than as a single page app aka SPA) and some light DOM scripting with something like Kendo UI (i.e. a jQuery plugin).

Include jQuery in a web page and boom, you're jQuery'ing.

<!doctype html>
<html>
  <head>
   <script src="https://code.jquery.com/jquery-3.1.0.js"   integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="   crossorigin="anonymous"></script>
  </head>
  <body>
    <script>jQuery.fn.jquery || $.fn.jquery</script>
  </body>
</html>

I can't seem to take my mind off of the simplicity of one script file, with a single purpose, in a simple HTML page.

Angular 1

Depends on: Nothing

Angular has no hard dependencies. Nope, not even on jQuery. Angular 1 implemented its own lite version of jQuery (aka jqLite) which removed the need for jQuery. However, a lot of developers still use jQuery, which Angular 1 will use over jqLite if jQuery is included before Angular 1.

So as it stands today, to use Angular 1, a developer must only include and minimally learn Angular 1.

<!doctype html>
<html ng-app>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
  </head>
  <body>
    <div>
      <label>Name:</label>
      <input type="text" ng-model="yourName" placeholder="Enter a name here">
      <hr>
      <h1>Hello {{yourName}}!</h1>
    </div>
  </body>
</html>

But, don't underestimate learning this one thing. Getting started with Angular 1 is trivial. Learning it is hard.

feelings_about_angularjs_over_time

Angular 2

Depends on: Zone.js, reflect-metadata, and RxJS

To make Angular 2 work you'll need three (maybe four, more on that in a sec) things. Allow me to describe each of these things because chances are these dependencies will be new to you.

  1. Zone.js – A Zone is an execution context that persists across async tasks. You can think of it as thread-local storage for JavaScript VMs. What? Watch a video. That might help.
  2. reflect-metadata – A polyfill for the Metadata Reflection API. Decorators make it possible to annotate and modify classes and properties at design time.
  3. RxJS – An API for asynchronous programming with observable streams i.e., "The ReactiveX Observable model allows you to treat streams of asynchronous events with the same sort of simple, composable operations that you use for collections of data items like arrays. It frees you from tangled webs of callbacks, and thereby makes your code more readable and less prone to bugs". If it helps, think of it as underscore or lodash, but for a collection of asynchronous values that change over time.

A potential fourth dependency, more than likely a hard dependency, will be core-js. Core-js polyfills ES5, ES6, and ES* features.

If you are going to reach for Angular 2, prepare yourself to not only learn Angular 2, but also some of the details around these dependencies.

Below is an example of an Angular 2 app that is not using a module loader or TypeScript (i.e. uses UMD versions of NG2 code).

<!DOCTYPE html>
<html>

<head>
    <title>Angular 2 QuickStart JS</title>
    <!-- 1.0 Load dependencies -->
    <script src="https://npmcdn.com/core-js/client/shim.min.js"></script>
    <script src="https://npmcdn.com/zone.js@0.6.12?main=browser"></script>
    <script src="https://npmcdn.com/reflect-metadata@0.1.3"></script>
    <script src="https://npmcdn.com/rxjs@5.0.0-beta.6/bundles/Rx.umd.js"></script>
    <!-- 1.1 Load NG2 dependencies -->
    <script src="https://npmcdn.com/@angular/core/bundles/core.umd.js"></script>
    <script src="https://npmcdn.com/@angular/common/bundles/common.umd.js"></script>
    <script src="https://npmcdn.com/@angular/compiler/bundles/compiler.umd.js"></script>
    <script src="https://npmcdn.com/@angular/platform-browser/bundles/platform-browser.umd.js"></script>
    <script src="https://npmcdn.com/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js"></script>

</head>

<!-- 3. Display the application -->

<body>
    <my-app>Loading...</my-app>
</body>

<!-- 2. Bootstrap and load NG2 component into app -->

<script>
    window.app || (window.app = {})

    app.AppComponent =
        ng.core.Component({
            selector: 'my-app',
            template: '<h1>My First Angular 2 App</h1>'
        })
        .Class({
            constructor: function() {}
        });
        
    document.addEventListener('DOMContentLoaded', function() {
        ng.platformBrowserDynamic.bootstrap(app.AppComponent);
    });
</script>
</html>

React

Depends on: Technically, nothing, but in practice a rendering adapter (e.g. ReactDOM)

It could be said that React doesn't technically have any hard dependencies. No, not even JSX or Babel are absolutely required. However, to render React code, one will have to choose where to render it and this will require an additional hard dependency (React calls it an adapter e.g. react-native, react-art, react-canvas, and react-three).

For example, to render React code to the DOM, potentially in a web browser, you'll have to include the react-dom-15.2.1.js file alongside React. This file provides the DOM-specific methods required to render React components to a DOM tree.

Below is an example of using React in a simple web page.

<!DOCTYPE html>
<html>
  <head>
    <script data-require="react@*" data-semver="15.2.0" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.0/react.min.js"></script>
    <script data-require="react@*" data-semver="15.2.0" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.0/react-dom.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <script>
        ReactDOM.render(React.createElement(
          'h1',
          null,
          'Hello World'
        ), document.getElementById('example'));
    </script>
  </body>
</html>

Note that most people use React with JSX and Babel. But neither of these tools should stop a developer from learning and using React. Simply include react-15.2.1.js and react-dom-15.2.1.js (i.e. an adaptor) in a web page and start writing React code.

Ember

Depends on: Node, npm, Bower, jQuery, and QUnit

As far as I can tell, Ember requires the use of the ember-cli Node package to build an Ember application. There's no choice, you have to learn it and use it. Other than Node and friends needed to build Ember applications, Ember also requires jQuery to run in a browser.

I have to say, if you are going to provide such an opinionated tool, I think its great that you go all the way and provide everything, as Ember does with the CLI tool. The ember-cli even doubles as a package installer (under the hood it uses npm and Bower).

Eventually I imagine the hard dependencies on jQuery will change.

Aurelia

Depends on: A module loader (supported options: SystemJS, RequireJS, Dojo, or Webpack), but it's safe to assume you'll also need some knowledge about Node, npm, gulp, and Babel/Typescript

Aurelia, technically, only requires one of the support module loaders to run an Aurelia application. However, a production-worthy solution will involve several JavaScript tools. Just consider the descriptions for the official production skeletons (an Aurelia skeleton is a basic starting point for the structure for you app):

  • skeleton-esnext-webpack – This project is configured to use the Babel transpiler so that you can write your application using either language. It should work well with any standard text editor. This skeleton uses npm for package management and Webpack for bundling.
  • skeleton-esnext – This project is configured to use the Babel transpiler so that you can write your application with ESNext code. It should work well with any standard text editor. This skeleton uses JSPM for package management and SystemJS for loading and bundling.
  • skeleton-esnext-aspnetcore – This is an ASP.NET Core web project pre-configured for building a .NET backend and an Aurelia front-end. It is configured for full ES Next support with Babel, similar to the standard skeleton-esnext option. This skeleton uses JSPM for package management and SystemJS for loading and bundling.
  • skeleton-typescript-webpack – This project is configured to use the TypeScript transpiler so that you can write your application using either language. It should work well with any standard text editor. This skeleton uses npm for package management and Webpack for bundling.
  • skeleton-typescript – This project is configured to use the TypeScript transpiler so that you can write your application using TypeScript. It should work well with any standard text editor, however it has been specially configured to work well with VSCode and Atom, including full TypeScript Intellisense for app, unit test and e2e test code. This skeleton uses JSPM for package management and SystemJS for loading and bundling.
  • skeleton-typescript-aspnetcore – This is an ASP.NET Core web project configured for building a .NET backend and an Aurelia front-end. It is configured for full TypeScript support, similar to the standard skeleton-typescript option. This skeleton uses JSPM for package management and SystemJS for loading and bundling.

I'm told that in the near future, a simpler script only version of Aurelia will be available. When this happens, Aurelia won't have any hard dependencies on third-party anything.

Vue.js

Depends on: Nothing

Include vue.js, learn Vue.js, and your off to the races. Similar to jQuery, Angular 1, and React, Vue.js offers a simplistic start. Below I show a simple webpage using Vue.js.

<!DOCTYPE html>
<html>
<head>
<script src="https://npmcdn.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
  <p>{{ message }}</p>
  <input v-model="message">
</div>
  <script>
    new Vue({
        el: '#app',
        data: {
            message: 'Hello Vue.js!'
        }
    })
  </script>
</body>
</html>

A very attractive feature of Vue.js is how it scales with the developer (e.g. Vue Components) with no additional dependencies. In other words, a lot can be done with Vue.js alone. Sprinkle it in existing web pages, or use front to back to compose the UI of a complex application from Vue components.

Two clear groupings

After considering the "hard'ish dependencies" for each tool, I hope it is obvious that tools like Ember, Angular 2, and Aurelia are in a class of their own when compared to tools like jQuery, Angular 1, React, and Vue.js. One group is simple (i.e. one script, no hard third-party dependencies to go to production) while the rest require a more advanced understanding of application development, app architecture, and task/build tools.

Some of these tools can be used interchangeably to solve similar problems. However, when you go to use Ember, Angular 2, or Aurelia be aware that these solutions initially require more cognitive overhead (Node, npm, module loaders, components, command line tools, compilers, builds, tests etc.). Of course, they also offer more. I'll let you decide if less is more or more is more.

For me, in my many years of playing the web development game, less has always been more until which point less just won't do. But instead of adding heaps of more, I just add a little more to the less.

Header image courtesy of INTVGene

Comments