jQuery
The first commit of jQuery contains Perl, a 748-line monolithic core, and a commit message with a typo in the word 'Initial'.
8a4a1edf04Before we get to the commit, I need you to look very carefully at the commit message.
"Inital Import."
Read it again. Inital. Not "Initial." The initial commit of jQuery (the library that single-handedly defined frontend web development for the better part of a decade, that at its peak was included on somewhere north of 75% of the top websites on the internet) contains a typo in its commit message. And the typo is in the word initial.
The typo has never been fixed. It cannot be fixed: you cannot edit commit messages in the git history of a published repo without rewriting every subsequent SHA, which for jquery/jquery would be catastrophic. The misspelling is permanent, load-bearing, and visible to anyone who runs git log --reverse.
This is my favorite kind of detail. Some of the most influential software on earth has a spelling error right at its origin.
1. What's in the commit
12 files, 2,074 lines. The commit is modest in size but dense in weirdness. The file list is not what you would expect for a "JavaScript library":
ajax/ajax.js 88 lines
browse/.htaccess 5 lines
browse/Pack.pm 467 lines (!)
browse/ParseMaster.pm 207 lines (!)
browse/browse-new.cgi 85 lines
browse/browse.cgi 51 lines
browse/copyright.txt 17 lines
core/core.js 748 lines
event/event.js 73 lines
fx/fx.js 170 lines
sort/sort.js 57 lines
tmpl/tmpl.js 106 lines
Two things jump out.
First: the first commit of jQuery contains Perl. browse/Pack.pm and browse/ParseMaster.pm are two Perl modules, totaling 674 lines. browse.cgi and browse-new.cgi are Perl CGI scripts. A .htaccess file configures Apache to serve them. Before jQuery had a build system, a test runner, or a minifier, it had a Perl-based source code browser for jquery.com. The repository was serving the jquery website as well as the library itself. They lived in the same git repo, side by side, without apology.
The Pack.pm and ParseMaster.pm files are themselves a port of Dean Edwards' famous "JavaScript Packer" into Perl. Dean Edwards' packer was the go-to tool for minifying JavaScript in the mid-2000s, before UglifyJS or Terser existed, back when "minified JavaScript" meant running a regex-based tool that tried very hard not to break your code. jQuery was using it from day one. In Perl.
Second: the folder structure is organized by concept, not by build artifact:
ajax/ → networking
core/ → the library core
event/ → event binding
fx/ → animations and effects
sort/ → (!)
tmpl/ → (!)
sort/ and tmpl/ are the surprising ones. jQuery, in its first commit, shipped with a built-in sorting module and a built-in templating module. Neither of these would survive to jQuery 1.0. Both would be cut from the core library, banished to plugins, and eventually forgotten. But on March 22, 2006, they were considered as fundamental as ajax/ and event/. John Resig was imagining a jQuery that would do more than manipulate the DOM. It would also help you render lists and reorder tables. That jQuery never shipped.
2. The 748-line core
The file that would become the entire identity of jQuery ($(...), .each(), .find(), .parents(), chainable DOM manipulation) was in this commit as core/core.js, 748 lines long. One file. The entire library, minus the modules, in 748 lines of JavaScript.
It is worth pausing on that number. A modern frontend framework is measured in tens or hundreds of thousands of lines of TypeScript spread across hundreds of files, because the problem the framework is solving is complex and the tools have gotten rich. In 2006, John Resig looked at the state of DOM scripting in browsers, where you had to use document.getElementsByTagName and document.createElement and suffer through subtly-incompatible addEventListener implementations, and he thought: we can fix this with one file.
The thing he fixed was enormous. The fix was 748 lines. Ratio of value delivered to bytes shipped, this is one of the most efficient pieces of software ever written.
3. The design idea, in a sentence
jQuery was built around a single idea that is very easy to state and was very hard to arrive at: turn the DOM into a set, and give the set a nice API.
In vanilla JavaScript of 2006, document.getElementsByTagName('a') returned a NodeList, which was almost an array but not quite, and iterating it required writing a for loop. jQuery said: what if that thing were wrapped in a chainable object with methods? What if $('a') returned something where .addClass('visited') would apply to every matched element at once? What if selectors were just CSS? What if events, effects, AJAX, and DOM walking were all methods on the same chainable object?
Every frontend library written after jQuery (Prototype, Mootools, Zepto, Underscore, Lodash, the entire "fluent interface" school of JavaScript) is in conversation with that one idea. You can see it being born in core/core.js in this commit.
4. What happened to the 12 files
ajax/ajax.js→ merged into the core, eventually became$.ajax(), which is still the API that most Stack Overflow answers from 2010-2014 recommend you use.core/core.js→ becamesrc/core.js, grew, was split into submodules, refactored multiple times, and is still the heart of jQuery today.event/event.js→ became the events module, which gave jQuery its famous.on(),.off(), and.trigger()methods.fx/fx.js→ became.animate()and friends. The 170 lines offx.jsin the first commit contain a surprisingly complete animation engine built entirely onsetTimeout.sort/sort.js→ cut. Gone. Not in jQuery 1.0. Not in jQuery today.tmpl/tmpl.js→ cut. Templating would eventually return to the jQuery ecosystem as a separate plugin calledjquery-tmpl, which itself was deprecated in 2012.browse/→ the Perl website browser was removed from the library repo when the website moved to its own codebase. The Perl files no longer exist anywhere in the jQuery source tree.
If you git blame jQuery today, you can trace the surviving code back to 8a4a1edf through many layers of refactoring, but most of the original 2,074 lines have been rewritten. The one thing that has genuinely persisted is the shape: the $(selector).method() pattern that was already there in the 748-line core file on day one.
5. The era this commit belongs to
It is easy, now, to be dismissive of jQuery. The browser standards it was compensating for have mostly been fixed. document.querySelectorAll exists. Element.classList exists. fetch exists. The things jQuery made possible are now in the browser, which means the library's reason for existing has shrunk.
But the dismissal ignores what jQuery actually did during its decade of dominance, which is that it taught an entire generation of developers how to think about the DOM as something programmable. If you learned JavaScript between 2007 and 2014, you almost certainly learned it through jQuery. The mental model of "select stuff, then do things to it" came from this library, and it turned out to be the right model; so right that the browser eventually absorbed it.
And it all starts with a 748-line file, a set of Perl CGI scripts, and a commit message that says "Inital Import."
6. Footnotes from the commit log
- John Resig presented jQuery publicly for the first time at BarCampNYC in January 2006, two months before this commit. The library existed before this commit (in his personal repo, and in the talk demos), but this is the beginning of the version-controlled lineage that became jquery/jquery.
- The
.htaccessfile in the commit enablesmod_rewritefor the Perl CGI scripts. In 2006, Apache mod_rewrite was the closest thing the web had to modern request routing. - John Resig went on to become the Dean of Computer Science at Khan Academy, where he applied the same "make the complex feel simple" instinct to teaching programming to children.
- The jQuery repository migrated to GitHub in 2008. Like Rails, the pre-git history was preserved during migration, which is why the "Inital Import." typo is still visible in the current git log.