# jQuery 4.0.0: four build variants, an exports map with three conditions, and a --exclude flag with a hidden dependency graph

> jQuery 4.0.0 is still one MIT licensed library for DOM operations, but the packaging has grown: four build variants, an ES module build in a separate directory, and an exports map that hands Node, bundlers and plain scripts three different files. The build script also lets you strip the library down to core, and the module list shows that removing one module quietly removes others.

**jquery/jquery** — GitHub describes it as jQuery JavaScript Library. The repository metadata lists JavaScript as its primary language. The metadata lists the MIT license. This article stays within the project description and details documented in the GitHub repository README.

- Repository: https://github.com/jquery/jquery
- Website: https://jquery.com
- Stars: 59,782 · Forks: 20,396
- Language: JavaScript
- License: MIT
- Published: 2026-08-13 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/jquery-jquery

## Four variants, and the ES module ones land in dist-module/ not dist/

A release is not one file. Building every variant with the build:all target produces jquery.js, jquery.slim.js, jquery.module.js and jquery.slim.module.js, each with a minified copy and a sourcemap. Three of them go into dist/. The two ECMAScript module builds are placed in dist-module/ instead, and they export jQuery and $ as named exports, which means the module build cannot hand you a global and you have to import what you use.

package.json decides which file a given import specifier resolves to, and the map has three conditions. Under node an import resolves to jquery.node-module-wrapper.js while the node default is dist/jquery.js. Under module an import resolves to dist-module/jquery.module.js while the module default is a bundler require wrapper. The top-level import condition points at the module build and the top-level default at dist/jquery.js. The same request, jquery, therefore lands on three different files depending on what is asking. The ./slim, ./factory and ./factory-slim entry points repeat the same pattern with their own wrapper files, and ./src/*.js is exported raw so a build tool can consume the sources.

## npm run build puts the artefact in dist/ with a minified copy

Building jQuery needs the latest Node.js/npm and git 1.7 or later; earlier versions may work but are not supported. On macOS the project sends you to Homebrew:

```bash
brew install git
brew install node
```

Windows users install git and Node.js from their own downloads, and Linux and BSD users use their package managers. Then clone the repository, enter the directory, install dependencies and run the build:

```bash
cd jquery
npm install
npm run build
```

The result lands in dist/ alongside a minified copy and the associated map file. To produce everything a release contains:

```bash
npm run build:all
```

That is the difference between a local build and a release build, and it matters when you are checking whether something is reproducible. The build script also has a help screen worth running before you pass anything unfamiliar:

```bash
npm run build -- --help
```

Version 4.0.0 is what package.json declares, and the 4.0.0 release was published on 2026-01-18.

## Any module can go except core, and selector leaves a querySelectorAll wrapper

The custom build is the interesting part of this project. Any module may be excluded except core, and paths are given relative to the src folder without the .js extension. The --include option is the opposite: the default includes are dropped and you get only what you named.

The exclusions are not independent, which is where a custom build turns into a debugging session. Excluding css removes everything that depends on it, including effects, dimensions and offset. Excluding deferred removes the Deferred object and, with it, ajax, effects and queue, while swapping core/ready for core/ready-no-deferred. Excluding ajax/jsonp breaks the JSONP transport, which depends on the ajax/script transport. Only one module has a documented substitute rather than a deletion: exclude selector and it is not removed but replaced with a small wrapper around native querySelectorAll.

Two more are about how the library attaches itself. Excluding exports/global removes the attachment of jQuery and $ to the window, and exports/amd removes the AMD definition. The dependency edges are written as prose in the module list rather than as a graph, so the only way to find the full cascade is to build and read the failure.

## Excluding core/ready changes when your callbacks run, not whether they exist

The core/ready module has the sharpest failure mode in the list, because the build still succeeds. Exclude it and any ready callbacks bound with jQuery() are simply called immediately, which is the behaviour you want when your scripts sit at the end of the body. What you lose is more than a convenience: jQuery(document).ready() will not be a function, and handlers bound with .on("ready", ...) will not be triggered. Code that takes the ready function as a value and calls it later fails at that call, not at build time.

A related trap sits in the ajax module. It carries $.ajax(), $.get(), $.post(), $.ajaxSetup(), the .load() method, the transports and the ajax event shorthands such as .ajaxStart(), so excluding it to save bytes removes an API surface that other libraries and your own helpers may call. The narrower options exist for that reason: ajax/xhr, ajax/script and ajax/jsonp are each a single transport, and excluding one of those leaves the rest of the module intact. If you are unsure, the same reasoning applies to event, which holds .on() and .off() along with all event functionality, and to effects, which holds .animate() and its shorthands.

## 4.x has full support, 3.x is critical-only, 2.x and 1.x are unsupported

The support table is four rows and it sets the tone for everything else. Version 4.x on the main branch has full support. Version 3.x on 3.x-stable receives critical updates only. Versions 2.x and 1.x, on their own stable branches, receive none at all. The project states plainly that the 3.x branch will now only receive critical updates, that 2.x and 1.x are no longer supported, and that all users should upgrade to the latest version for performance, security and features.

The release history shows how that transition went. 4.0.0 and 4.0.0-rc.2 were both published on 2026-01-18, minutes apart, and 4.0.0-rc.1 came earlier on 2025-08-11. The last push to the repository was on 2026-09-22, so the 4.x line is the one being worked on.

For anyone still on an old line, the project points at commercial backport support from HeroDevs and TuxCare. That is the honest shape of the answer: the 3.x line will not be receiving the module and packaging work that 4.x has, so a codebase on 3.x is choosing between upgrading and paying someone else to patch it.

## A script tag build and a bundled build give the page two copies

The exports map has a practical consequence that only shows up in a mixed project. A bundler that matches the module condition and a Node process that matches the node condition resolve the same specifier to different wrapper files, and a page that loads dist/jquery.js with a script tag also gets jQuery and $ attached to the window unless exports/global is excluded. Mix that with a bundled ES module import and the page holds two jQuery objects: one global, one imported. Plugins that reach for the global will not see the imported instance, and state held on one is invisible to the other.

Nothing in the build system prevents this, because the two builds are individually valid. The fix is a decision rather than a flag: pick either the global build or the module build for a given page and keep to it, and if a dependency needs the global, exclude exports/global nowhere and accept the global. The slim and factory entry points exist for the projects that want a smaller surface, but the choice of which copy wins has to be made deliberately.

The same reasoning extends outside a browser. The project states that jQuery also supports Node, browser extensions and other non-browser environments, and browser support has its own page on jquery.com. In an environment with no DOM, the modules that reach for elements are the ones to leave out, which is another argument for the custom build over a global script.

## gh-NUMBER and trac-NUMBER are two eras of the same bug history

jQuery's issue references follow two conventions, and reading the wrong one wastes an afternoon. Current issues and pull requests are cited as gh-NUMBER and live under the GitHub repository. Older reports live on a Trac based tracker at bugs.jquery.com, which is kept in read only mode so past discussions remain available, and are cited in the source as trac-NUMBER.

Contribution is guided by three documents the project asks you to read before writing code: Getting Involved, the Core Style Guide, and Writing Code for jQuery Projects. Project work happens on the matrix.org platform, and meeting minutes are published at meetings.jquery.org under the core category, which is where a design argument from years ago is still findable. The repository itself carries the release machinery: .release-it.cjs drives releases, AUTHORS.txt is checked and regenerated by the authors:check and authors:update scripts, eslint.config.js and .husky/ cover lint and hooks, and jtr-isolate.yml configures the test runner.

## Against the DOM API, the difference is a layer, not a capability

The alternative to jQuery is the DOM API the browser already ships, and the honest comparison is about ergonomics rather than reach. jQuery's own module list shows what it bundles: a selector engine, .on() and .off() for events, the ajax module with $.ajax() and its transports, the Deferred object that effects and queue sit on, offset for .offset() and .position(), dimensions for .width() and .height(), and wrap for .wrap() and its relatives. Modern browsers give you querySelectorAll, addEventListener, fetch, promises and CSS transitions, so none of that is unreachable without the library.

What the library still buys is one consistent surface across those pieces, plus the plugin ecosystem that expects a global jQuery object and the version support policy behind it. Note where the project itself has already conceded ground: a custom build can replace the selector engine with a thin wrapper around native querySelectorAll, and the default exports/global attachment can be excluded outright, which is the shape a project takes when it wants the library's conveniences without owning a global.

So the decision is not capability against capability. It is whether the codebase you are in benefits from a shared layer, and whether you are willing to own the upgrade path from 3.x to 4.x when the support table says 3.x is down to critical updates.

## Conclusion

Use jQuery when you are maintaining a codebase that already depends on it, when a plugin expects the global jQuery object, or when you want a custom build with the ajax and effects modules gone. Do not start a new project on it expecting a stable platform contract: 4.x on main is the only branch with full support, 3.x takes critical updates only, and 2.x and 1.x get nothing. Before you pin a version, check the --exclude list against the plugins you load, because excluding css, effects, deferred or core/ready removes calls that other modules depend on, and the failure appears at runtime rather than at build time.

## FAQ

### What is jQuery used for?

package.json describes it as a JavaScript library for DOM operations, and the module list shows the working surface: the ajax module with $.ajax(), $.get() and $.post(), effects with .animate() and its shorthands, offset for .offset() and .position(), and the event module with .on() and .off(). Everything is built from the sources in src/ into the files in dist/ and dist-module/.

### What is jQuery vs JavaScript?

jQuery is written in JavaScript and runs inside it, not instead of it. What it adds on top of the language is a selector and event layer, AJAX transports, a Deferred object, animation methods and a plugin-friendly global, all assembled from the modules in src/ by the build script.

### Is jQuery good in 2026?

The support table is the useful answer: 4.x on main has full support, 3.x on 3.x-stable receives critical updates only, and 2.x and 1.x receive none. jQuery 4.0.0 was released on 2026-01-18, the project recommends upgrading to the latest version, and commercial support for older lines is offered by HeroDevs and TuxCare.

### Is jQuery front-end or backend?

It is a DOM library, so front-end by nature, but the project states that jQuery also supports Node, browser extensions and other non-browser environments, with browser support documented on its own page. The package's exports map carries a node condition that resolves to a node module wrapper, so the file you get depends on the environment rather than the import path alone.

### how to install jquery

The current version is downloaded from jquery.com/download/. To build it yourself you need the latest Node.js/npm and git 1.7 or later, then run npm install and npm run build inside the jquery directory, which places the built file in dist/ along with a minified copy and a sourcemap.

### how to use jquery

Choose a variant. A full build produces jquery.js, jquery.slim.js, jquery.module.js and jquery.slim.module.js, with the two ECMAScript module builds placed in dist-module/ exporting jQuery and $ as named exports. To carry less than the whole library, pass module paths relative to src to the --exclude option, or name only what you want with --include.

## Sources

- [Official documentation](https://jquery.com)
- [Official README](https://github.com/jquery/jquery#readme)
- [Project repository](https://github.com/jquery/jquery)
- [Release notes](https://github.com/jquery/jquery/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jquery-jquery
