jQuery Plugin ~5 KB No Build Step

reQuery

A jQuery plugin that adds reactive state and declarative DOM binding — without a build step, a virtual DOM, or a component model.

The Problem

Most jQuery projects hit the same wall: a piece of UI depends on more than a couple of values, and keeping the DOM manually in sync starts getting messy fast. You end up with code like this:

// Vanilla jQuery — imperative, brittle
$('#inc').on('click', function() {
  count++;
  $('.counter-display').text(count);
  $('.step-tracker').text(`Step ${count} of 10`);
  if (count >= 10) $('.done-msg').show();
  updateProgressBar(count);
});

Every time count changes you have to remember every element that depends on it. Add a new display element and you're back editing every event handler. Miss one and you have a stale-display bug.

reQuery inverts that relationship. State is the source of truth. HTML declares what depends on it:

<!-- HTML: declare what depends on state -->
<span data-rq-text="count"></span>
<span data-rq-text="count" id="step-tracker"></span>
<div data-rq-show="isDone">All done!</div>
$('#app').rqState({ count: 0, isDone: false });

$('#inc').on('click', () =>
  $('#app').rqMutate('count', n => {
    const next = n + 1;
    $('#app').rqSet('isDone', next >= 10);
    return next;
  })
);

Adding a new element that displays count? One HTML attribute. No event handler edits. The handlers only change state — they no longer care about the DOM.

Who It's For

  • jQuery developers who want reactive binding without abandoning the jQuery mental model.
  • Legacy codebases — WordPress themes, Laravel Blade views, admin panels — needing reactive sections without a full rewrite.
  • CMS-driven or server-rendered HTML where a full SPA framework would be overkill.
  • Transparency seekers — no compiler, no magic, just readable source.

reQuery is not for greenfield SPA development. For that, use Vue, React, or Svelte.

Core Design Decisions

State is scoped to a DOM element

State lives in a WeakMap keyed to the root element — not a global store. Two widgets on the same page have fully independent state.

No virtual DOM — direct writes

When state changes, reQuery walks the subtree, finds data-rq-* bindings for the changed key, and updates those nodes directly. No diffing, no reconciler.

API follows jQuery conventions

All methods on $.fn, selector-first, read methods return values, write methods return this for chaining.

DOM Bindings

Add these attributes to any element inside your root and reQuery keeps them in sync automatically.

Attribute Effect
data-rq-text="key" Sets textContent
data-rq-html="key" Sets innerHTML
data-rq-val="key" Sets input value; also wires input/change for two-way binding
data-rq-show="key" Toggles visibility via display based on truthiness
data-rq-attr-[name]="key" Sets an HTML attribute; passes null to remove it
data-rq-class-[name]="key" Adds or removes a CSS class based on truthiness
data-rq-each="key" Clones a <template> child for each item in an array
data-rq-on-[event]="action" Wires an event to a named handler from opts.actions

API Reference

All methods are registered on $.fn and follow standard jQuery chaining patterns.

Method Returns Description
rqState(obj, opts?) this Initialize state on an element; runs initial binding pass
rqGet(key) value Read a state value
rqSet(key, value) this Write a state value; triggers watchers and DOM update
rqMutate(key, fn) this Update state via callback — receives current value, returns next
rqWatch(key, fn) this Register a callback that fires after state is written
rqComputed(key, fn) this Register a derived value; re-runs whenever dependencies change

How It Compares

reQuery fills a specific gap. It's not trying to be React.

reQuery Vanilla jQuery Vue / React / Svelte
Requires a build step No No Yes
Requires rewriting existing code No Yes
Reactive data binding Yes No Yes
Virtual DOM / diffing No No Yes (React, Vue)
Works inside CMS-rendered HTML Yes Yes Difficult
Full SPA capability No No Yes
Bundle size (approx.) ~5 KB ~30 KB 30–100+ KB

Get Started

Drop it in via script tag — no bundler required.

Script tag

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script src="dist/requery.umd.js"></script>

ESM / npm

import $ from 'jquery';
import 'requery';

Minimal example

<div id="app">
  <p>Count: <strong data-rq-text="count"></strong></p>
  <button id="inc">+</button>
</div>

<script>
  $('#app').rqState({ count: 0 });
  $('#inc').on('click', () => $('#app').rqMutate('count', n => n + 1));
</script>

No compilation. No configuration. No framework to learn.