Saturday, February 13, 2016

You Might Not Need Babel

Babel is great, and by all means use it if it makes it easier to develop your application.

If you're developing a library on the other hand, please take a moment to consider whether you actually need Babel. Maybe you can write a few more lines of utility code and forego the need to pre-process. If you're only targeting some platforms, you may not need anything more than plain old ES6.

At the very least, make sure you know what Babel is doing for you, and what it's not. Some developers believe that Babel is protecting us from a great demon of code complexity when, in truth, browsers and node are pretty easy to deal with on their own. Let's take a look at some of the strategies for not needing Babel.

ES5 is pretty okay: In the days when we used tables for layout and the debugger was named alert(), we would have been so grateful if JavaScript had the features that ES5 has today. If you truly need Babel you are not only a weak programmer, but also an ingrate. Face it, you don't yet understand why ({}+[])[2] === 'b' and you're already moving on to ES6.

Supported environments: With Babel you can mindlessly use any ES6 feature and run on any browser or version of node. To avoid Babel, track the progress of ES6 in all platforms and just use the features they all support. So, Node 4.x doesn't support modules, proxies, unicode regexp extensions, and destructuring. As ES6 support improves in each environment, simply return to all your older code and rewrite it to use the newly enabled features.

Shareable code: ES5 is the common denominator that lets developers share their work. It gives code a greater "reach" and makes JavaScript easy to consume via CDNs or package repositories such as npm. All that is overrated. If you can keep track of your supported environments, people who want to use your code can do it too. If ES6 features in their supported environments are not the same as yours, they can run Babel on it.

Performance: JavaScript engines have gotten really good at optimizing ES5 code. But hey, it's still ES5 and looks like something your mom or dad would have written. As Douglas Crockford probably said once, "It is much better to look good than to run good." Sure, ES6 can be a lot slower than equivalent ES5 but that doesn't make Babel an optimizing compiler. At least not on purpose.

New language features: Did I say ES6 above? I meant ES7. Yeah, ES7, the one with the new exponentiation operator that will cause a syntax error in your ES6 if it's not supported. Just avoid that. Oh, also avoid sweet new syntax like the proposed function-bind (::) operator since that doesn't work yet.

So in summary, You Might Not Need Babel in any of these cases:
  • You respect your elders and want to honor our shared ES5 heritage.
  • Your code just needs to run on Microsoft Edge, Chrome Canary, and Firefox Nightly.
  • Other developers don't ever want to use your code via npm.
  • The low native performance of ES6 features is worth the pretty code.
  • JavaScript features beyond ES6 don't interest you.

Monday, November 30, 2015

How I got involved in Open Source

Uh oh, its almost the end of 2015 so I'd better put at least one blog post here for posterity!

About ten years ago, I was at a startup I co-owned and searching for a way to easily create a nice-looking UI for a Windows-based utility. Since this was a Windows app, most people at the time would have chosen C or C++ as the language or used C# and a framework like .NET. Or perhaps they would have gone old-school with something like MFC. Instead, we hosted the Windows HTML rendering engine in our own executable and built 80 percent of the app (including 99 percent of the user interface) in JavaScript and HTML. Basically, this would be a Cordova app today, but we coded it uphill both ways back then.

A short time into development, it was becoming clear that there had to be a better way to organize all the DOM manipulation that had to be done. I looked around and tried a few libraries available at the time, but they seemed a bit ugly and weren't helping that much. Then, almost ten years ago, I found this thing called jQuery. I can't even recall how I stumbled upon it, probably Slashdot. (Yeah, that long ago.)

jQuery was just what I was looking for. I didn't even need any of its cross-browser goodness, our app would only ever run on the IE6-like HTML engine inside Windows. The expressiveness of jQuery was its attraction to me, because it greatly simplified the way our app was written. Later on we started using it on our web site as well, where the cross-browser benefits were definitely appreciated.

But this story is mainly about how I made my first contribution to open source. It's hard to remember the days before we had excellent project collaboration via GitHub. All I had was a copy of jQuery and John Resig's email address. So when I found some problems I sent him an email with suggestions. John replied, thanking me for the contributions and offering to put me on a newly-formed mailing list of people who were interested in jQuery. You can still find some of those early posts scattered around the Internet.

If you want a course on how to build a successful open source project, take a look at what John Resig did during those early years of jQuery. It's not always about the codebase. You need an enthusiastic group of volunteers to help with all the organizational things that will allow others to use the project. Sure that includes code, but it also takes good documentation, devops, and user support. John was great at getting others to help, and listening to what they said. If you look at those old posts from nearly a decade ago, you'll see a lot of people who are still very active in open source.

Thursday, February 06, 2014

A year with Modern.IE

For a little over a year I've been working with Microsoft on the modern.IE site. This week the site is celebrating having saved developers one million hours in browser testing. Some of the savings come from the free pre-configured VMs with real copies of the different IE browser versions. Just about all the popular VM software is supported on several different platforms. There is no substitute for using the real browser when it comes to compatibility testing, and these VMs are one way to do just that with minimal hassle.

Further time saving comes from Browserstack. It provides convenient in-browser testing of just about any type of browser or device. Modern.IE offers a free three-month membership to Browserstack for IE versions. There are Chrome and Firefox plugins that make it really easy to quickly try out your latest designs on any version of IE, even if they're served off your local computer. Very slick.

Most of my work on the project was done for the online compatibility scan, available directly off the home page but also downloadable for local use. It scans the HTML, CSS, and JavaScript of the site to see if there are things that may work in one browser but not in another. This includes things like outdated JavaScript libraries, missing CSS prefixes, browser sniffing, missing doctype, or use of ActiveX controls. It also suggests features that might improve the experience for Windows 8 users, such as high-quality favicons.

The scanner project is open source, written in node.js, and hosted on GitHub. This tool is meant to be useful to your web development diagnosis and debugging, so open an issue in the repo if you find problems or have suggestions.

For even more information, you can run your site through Compat Inspector via Sauce Labs to find code specific to older versions of IE that might cause things to break with modern IE versions. To use this feature, just click the "Scan for code no longer supported in modern IE" tab once the initial scan is done. On that same results page you can also get screen shots of how the page appears in various browsers, as another quick check that the layout is functioning properly.

Quite often I'll hear developers say, "All these versions of IE are a pain and make my job harder! Why are there so many versions and why can't I just run this on a Mac where I do my development?" There are so many versions of browsers, not just IE, and yes that is the burden of the web developer. The Android 2.3 browser is just as much of a pain to today's web developers as older versions of IE, and that will get worse before it gets better. New phones are still shipping with that ancient Android browser, but at least the market share of older IE is shrinking.

As for why you can't run IE on your Mac, let's turn that around and ask why Windows-based web developers can't run Safari to do testing. Apple doesn't make VMs available to do that the way Microsoft does here. Fortunately, Browserstack does support many versions of Safari. Perhaps Apple will make free Browserstack testing available for Safari. No matter what, though, responsible web developers should test on every browser they expect the audience to use. Microsoft has done what they can to make that easy.

Wednesday, January 22, 2014

Haters Gonna Hate

@jeresig on Twitter: Whenever I come across people who really hate me and my work it takes every ounce of energy to try and ignore them and move on. So hard.
I was saddened to come across this tweet by John Resig a few days ago. I know at least one of the people who has made--and continues to make--the attacks he speaks about. This person seems to have held deep hatred for John and jQuery for years. It's really unfortunate, because the attacker seems to be a smart and technically astute person. But he's also a bully.

This bully's attacks tend to focus on two things: the quality of jQuery's code, and the quality of jQuery users. On the first point, it's telling that early in the project's life this bully created some tests that showed problems with jQuery. John asked whether we could use that code in jQuery's unit tests, and the answer was NO WAY. He leaves his own vitriolic form of jQuery "code reviews" around the Internet, but never makes constructive comments that might actually help jQuery improve. Helping people get productive things done does not seem to be his goal at all.

Anyone can find problems with jQuery and things that could be improved. The jQuery team has lists of issues in our GitHub repositories if you are short of them. Since the jQuery Foundation is powered primarily by volunteers, we'd love to have more people who are willing to help fix things and improve the documentation, for example. That would be a productive and constructive way to make jQuery better for everyone.

When the bully turns to jQuery's users, it's all about what horrible programmers they are and how bad their code is. He'd probably be happier if jQuery was an obtuse library that was unusable without a four-year degree in programming. Instead, jQuery is easy enough to use that many non-programmers can get something going after a short time. That's a bad thing? Everyone has to start somewhere. Don't blame jQuery if some people decide that their amateur efforts are good enough--and perhaps they are. If not, they can learn and get better over time.

From the very start, jQuery's design and philosophy was pragmatic. It made hard things easy. It fixed browser bugs. It provided a plugin architecture for people to share their code. It coexisted with the libraries that already existed, so people could try jQuery without having to abandon what they'd already done. It continues to do all of those things that John Resig envisioned eight years ago, and more. The bullies who attack John and jQuery are just harvesting a bumper crop of sour grapes.

So John, let me tell you this: There's no reason to let anyone make you feel like your work on jQuery was bad. Take a look at the Internet today. jQuery is everywhere, people choose it of their own free will as the best thing out there. The lessons jQuery taught are helping to drive the next generation of web standards, and it's a foundation component for many higher-level frameworks. Many of the people who you recruited to join that little jQuery mailing list in 2006, me included, are still working to ensure that jQuery keeps serving developer needs for years to come. You did good.

Sunday, December 29, 2013

Please Stop the Abuse!

According to many of the tests on, jQuery is slow. Really slow. The jQuery team gets bug reports from web citizens who've discovered these egregious flaws via jsperf and want them fixed. Now, can be a great tool when used knowledgeably, but its results can also be misinterpreted and abused. For example:

Why doesn't jQuery use DOM classList for methods like .addClass()?

There are at least three good reasons.
  1. It doesn't make any practical performance difference given its frequency of use.
  2. It complicates code paths, since classList isn't supported everywhere.
  3. It makes jQuery bigger, which makes it load slower for everyone, every time.
But this jsperf shows classList is much faster! How can you say that?

Well it's possible that test is running afoul of microbenchmark issues, and not measuring what it is supposed to measure due to the increased sophistication of today's JavaScript compilers. This is a big problem with a lot of the jsperf tests out there, they are just not measuring anything useful, or at least not measuring what their creator thought they measured.

But let's assume that in this case, the JavaScript is actually doing just what the test case creator intended to do, and none of those microbenchmark oddities are occuring. The two test cases are not quite the same because the API behaviors are different:
  • The jQuery case works correctly for zero, one, or more elements in its collection. The classList case only works with one element selected, and will throw an error if no elements are selected.
  • The jQuery case can add or remove multiple classes at once. The pure DOM case will not, since classList does not support it.
  • The jQuery case runs on browsers that don't support classList. This includes the Android 2.3 browser (about 25 percent of all Android) and Internet Explorer before version 10 (about 36 percent of all IE).
Since jQuery provides wide browser support and a richer API for class operations, any attempt to use classList inside jQuery would still need supporting code around it to deal with older browsers plus the cases of multiple elements and multiple classes. That's more code to be downloaded and parsed each time any browser (including those without classList) loads a page with jQuery. That starts our space-vs-speed performance tradeoff in a hole that we may never dig out of.

As for the speed, let's look at how long it takes to do this block of operations, ignoring that they consist of things you'd never do all at once such as adding and then immediately removing the same class. Looking at the per-block execution times on Chrome, the jQuery API takes only about 16 microseconds (just 1/1000 of our 16 millisecond frame length) to do those class operations. Sure, the native methods do it roughly four times faster, but are these 12 additional microseconds too much considering the extra features jQuery offers?

Now the classList advocate might say, "What if I call this code 1,000 times? Now it's taking 12 milliseconds and eating up most of my frame budget!" Typical real-life code would only manipulate the class property a few times a second at most, usually in response to user interaction. If you're really manipulating 1,000 of any DOM element in JavaScript and expecting that to fit into a 16-millisecond chunk of work, you're likely running into all sorts of performance issues anyway. That's a problem with algorithms and design, unlikely to be magically solved by shaving a few microseconds off jQuery's class manipulation methods.

After just about any class change, the browser needs to recalculate styles and redraw at least part of the page. The cost of those operations will usually outweigh the cost of manipulating the class property, but they're not reflected in jsperf because the rendering engine runs on the same thread as the benchmark. The browser doesn't get a chance to re-render the page until after the timed block of code is complete. But even if it did, the trivial size of this document (just one test element) isn't typical of the workload the browser faces in recalculating styles and layouts.

In fringe cases where jQuery is too slow, you're in luck! jQuery doesn't place "Do Not Enter" signs around DOM methods. You can freely mix many DOM methods with jQuery. That's why event handlers have the target DOM element, not a jQuery collection, as their this keyword. In your checkbox event handler, you're free to use this.checked instead of $(this).prop("checked") -- and you should, it's shorter! Go ahead and use this.classList.add() directly if you don't care about old Android or old IE and have strong emotions about wasting microseconds.

Knuth said, "We should forget about small efficiencies, say about 97 percent of the time: premature optimization is the root of all evil." The classList case is one of those small efficiencies that makes little difference to the performance of real code. There is no good reason for jQuery to blindly optimize exclusively for the CPU performance dimension that jsperf measures, particularly when it has a cost in code size and complexity. But the programmer's mentality often won't let go of these issues because, darn it, jQuery should use the native API regardless.

Bottom Line: Don't obsess on speeding up code that isn't slow. As tempting as it seems, is usually not the right tool for identifying browser bottlenecks in application code. Ultimately, the best way to make web pages and apps fast is to use tools like WebPageTest, followed by a profiling session in your favorite browser tools to pinpoint slow JavaScript. Don't waste your development time on the 97 percent.