In general, Windows has always belonged on a VM snapshot backing image. =3
It followed the 8-17 monday-friday pattern.
Essentially it was people at their work machines (posts, banks, etc) running corporate computers where modern browsers were not installed.
We had a computer for manually testing every release on IE8 and 9.
If somebody is looking for our products from those computers, we aren't gonna lose them.
But as far as I know, that client dropped support for IE8 and IE9 in 2024 with IE11 planned to be dropped this year.
> We also dropped support for other very old browsers, including Edge Legacy, iOS versions earlier than the last 3, Firefox versions earlier than the last 2 (aside from Firefox ESR), and Android Browser.
Safari from iOS 16, released in 2022, is more modern in every conceivable way than MSIE 11. I'd also bet there are more people stuck with iOS 16- than those who can only use IE 11, except maybe at companies with horrid IT departments, in which case I kind of see this as enabling them to continue to suck.
I'd vote to rip the bandaid off. MSIE is dead tech, deader than some of the other browsers they're deprecating. Let it fade into ignomony as soon as possible.
There are likely millions if not tens of millions of computers still running MSIE11. There are likely to be no devices running iOS 16
Statcounter says there are about 4.6% of iOS users still on iOS 16.[1]
My gut instinct is that there are multiple times more people using iOS 16 today than MSIE of any version.
[0] https://radar.cloudflare.com/reports/browser-market-share-20...
[1] https://gs.statcounter.com/os-version-market-share/ios/mobil...
My iPhone X is stuck on iOS 16 with no way to upgrade.
However, the phone is still working well. Despite being in daily use for 8 years it still has 81% battery capacity, has never been dropped, has a great OLED screen, can record 4K@60 video. It is far more responsive than a brand new 2025 $200 Android phone from e.g. Xiaomi. It still gets security patches from Apple. The only real shortcoming compared to a modern iPhone is the low light camera performance. That and some app developers don't support iOS 16 anymore, so e.g. I can't use the ChatGPT app and have to use it via the browser, but the Gemini app works fine.
Those phones are still supported. The most recent iOS 16 update was in September 2025.
Crazy to think that software running inside IE11 should use the latest version of a library.
But maybe they will scope this one better: they were talking about getting 4.0 released in 2020 back in 2019!
[1]: https://github.com/jquery/jquery/pull/5077 [2]: https://github.com/jquery/jquery/issues/4299
It requires a strong design system and it probably makes it harder to use some web APIs but those can be reasonable tradeoffs
EDIT: Found one that's going v5 soon, looks nice. https://www.nativewind.dev/
It made it so much better to build apps vs. spaghetti jQuery.
I still have nightmares about jeeping track of jQuery callbacks
So the options are to 1. Code React all day and be happy with it. 2. Come up with reasons why it's bad.
There are many talented and intellectually curious people in the field which lean towards 2.
Nobody in their right mind is remembering to use `useDeferredValue` or `useEffectEvent` for their very niche uses.
These are a direct result of React's poor component lifecycle design. Compare to Vue's granular lifecycle hooks which give you all the control you need without workarounds, and they're named in a way that make sense. [1]
And don't get me started on React's sad excuse for global state management with Contexts. A performance nightmare full of entire tree rerenders on every state change, even if components aren't subscribing to that state. Want subscriptions? Gotta hand-roll everything or use a 3rd party state library which don't support initialization before your components render if your global state depends on other state/data in React-land.
> When they started adding new hooks just to work around their own broken component/rendering lifecycle, I knew React was doomed to become a bloated mess.
Hooks didn't fundamentally change anything. They are ways to escape the render loop, which class components already had.
> Nobody in their right mind is remembering to use `useDeferredValue` or `useEffectEvent` for their very niche uses.
Maybe because you don't necessarily need to. But for what it's worth, I'm on old versions of React when these weren't things, and I've built entire SPAs out without them at work. But reading their docs, they seem fine?
> And don't get me started on React's sad excuse for global state management with Contexts. A performance nightmare full of entire tree rerenders on every state change
I think it's good to give context on what a rerender is. It's not the same as repainting the DOM, or even in the same order of magnitude of CPU cycles. Your entire site could rerender from a text input, but you're unlikely to notice it even with 10x CPU slowdown in Devtools, unless you put something expensive in the render cycle for no reason. Indeed, I've seen people do a fetch request every time a text input changes. Meanwhile, if I do the same slowdown on Apple Music which is made in Svelte, it practically crashes.
But pretty much any other state management library will work the way you've described you want.
Even if you make a `createProvider` factory to initialize a `useMyContext` hook, it still requires what I mentioned above.
Compare this to Vue's Pinia library where you can simply create a global (setup) hook that allows you to bring in other hooks and dependencies, and return the final, global state. Then when you use it, it points to a global instance instead of creating unique instances for each hook used.
Example (React cannot do this, not without enormous boilerplate and TypeScript spaghetti -- good luck!):
export const useMyStore = defineStore("myStore", () => {
const numericState = ref(0);
const computedState = computed(() => reactiveState.value * 2);
const numberFromAnotherHook = useAnotherHook();
const { data, error, loading } = useFetch(...);
const derivedAsyncState = computed(() => {
return data.value + numericState.value + numberFromAnotherHook.value;
});
return {
numericState,
computedState,
numberFromAnotherHook,
derivedAsyncState,
}
});
This is remarkably easy, and the best part is: I don't have to wrap my components with another <Context.Provider> component. I can... just use the hook! I sorely wish React offered a better way to wire up global or shared state like this. React doesn't even have a plugin system that would allow someone to port Pinia over to React. It's baffling.Every other 3rd party state management library has to use React Context to initialize store data based on other React-based state/data. Without Context, you must wait for a full render cycle and assign the state using `useEffect`, causing your components to flash or delay rendering before the store's ready.
Your example would look like:
const id = useState(...);
const numericState = useState(0);
const q = useQuery({
queryFn: async (context) => {
const data = await fetch(..., {signal: context.signal});
const derivedState = numericState + data.something;
return `This is it ${derivedState}`;
},
queryKey: ["someState", id],
}, [id, numericState]);
...
if (q.isLoading) {
return <div>loading...</div>;
}
return <div>{q.data}</div>;
It'll handle cancellation if your state changes while the query is being evaluated, you can add deferred rendering, and so on. You can even hook it into Suspense and have "transparent" handling of in-progress queries.The downside is that mutations also need to be handled by these libraries, so it essentially becomes isomorphic to Solid's signals.
Here's how Zustand gets around this, and lo-and-behold: it requires React Context :( [1] (Look at how much boilerplate is required!)
React Query at least gives you an `initialData` option [2] to populate the cache before anything is done, and it works similarly to `useState`'s initializer. The key nuance with `const [state, setState] = useState(myInitialValue)` is the initial value is set on `state` before anything renders, so you don't need to wait while the component flashes `null` or a loading state. Whatever you need it to be is there immediately, helping UIs feel faster. It's a minor detail, but it makes a big difference when you're working with more complex dependencies.
1. https://zustand.docs.pmnd.rs/guides/initialize-state-with-pr...
2. https://tanstack.com/query/v5/docs/framework/react/guides/in...
---
I guess I could abuse React Query like this...
function useGlobalStore() {
const myHookState = useMyHook(); // not async
return useQuery({
initialData: {
optionA: true,
optionB: myHookState,
}
});
}
And you'd have to use `queryClient` to mutate the state locally since we aren't dealing with server data here.But here's what I really want from the React team...
// Hook uses global instance instead of creating a new one each time it's used. No React Context boilerplate or ceremony. No wrapping components with more messy JSX. I can set state using React's primitives instead of messing with a 3rd party store:
const useGlobalStore = createGlobalStore(() => {
const dataFromAnotherHook = useAnotherHook();
const [settings, setSettings] = useState({
optionA: true,
optionB: dataFromAnotherHook,
});
return {
settings,
setSettings,
}
});There is no real difference now between doing:
const [state, setState] = useState(42);
and: const [state, setState] = useState(undefined);
useEffect(() => setState(42));
They both will result in essentially the same amount of work. Same for calculations with useMemo(). It was a different situation before React 18, because rendering passes were essentially atomic.My major problem with React is the way it interacts with async processes, but that's because async processes are inherently tricky to model. Suspense helps, but I don't like it. I very much feel that the intermediate states should be explicit.
Their setup (component) functions are a staging ground for wiring up their primitives without you having to worry about how often each call is being made in your component function. Vue 3's composition pattern was inspired by React with hooks, with the exception that variables aren't computed on every render.
And I agree about Suspense, it's a confusing API because it's yet-another-way React forces you to nest your app / component structure even further, which creates indirection and makes it harder to tie things together logically so they're easier to reason about. The "oops, I forgot this was wrapped with X or Y" problem persists if a stray wrapper lives outside of the component you're working on.
I prefer using switch statements or internal component logic to assign the desired state to a variable, and then rendering it within the component's wrapper elements -- states like: loading, error, empty, and default -- all in the same component depending on my async status.
I understand that mixing declarative UI with the harsh imperative world is always problematic, but I think I prefer React's approach of "no spooky action at a distance".
As for speed, I didn't find any real difference between frameworks when they are used correctly. React can handle several thousand visible elements just fine, and if you have more, you probably should work on reducing that or providing optimized diffing.
For example, we're using React for 3D reactive scenes with tens of thousands of visible elements. We do that by hooking into low-level diffing (the design was inspired by ThreeJS), and it works acceptably well on React.Native that uses interpreted JS.
I find React perfectly acceptable, it's just global state management and a few flaws with its lifecycle that repeatedly haunt me from time to time. (see: https://news.ycombinator.com/item?id=46683809)
Vue's downside is not being able to store off template fragments in variables. Every template/component must be a separate component file (or a registered component somewhere in the tree), so the ease of passing around HTML/JSX conditionally with variables is impossible in Vue. You can use raw render functions, but who wants to write those?
JSX being a first-class citizen is where React really shines.
Problems are only truly solved by the folks who dedicate themselves to understanding the problem, that is: the folks working on web standards and the other folks implementing them.
It kills me to think of how amazing Web Components could be if those folks had started standardising them _now_ instead of in "competition" with userland component libraries of the time (while punting on many of the essential challenges of developing UI in the DOM those libraries were still evolving solutions for), and introduced more problems entirely of their own making.
I find it very intuitive, with the exception of useEffect.
```js
<div id="root"></div>
<script>
import React from 'https://esm.sh/react@19';
import ReactDOM from 'https://esm.sh/react-dom@19/client';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<h1>Hello, world!</h1>); </script>
```
---
HTML's hello world:
```html
<h1>Hello, world!</h1>
```
---
JS's hello world:
Nothing, it was already done in HTML
import { useState } from "react";
function Counter() { const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}---------- Svelte:
<script> let count = 0; </script>
<button on:click={() => count += 1}> Count: {count} </button> --------------- React: function Editor({ initialText }) { const [text, setText] = useState(initialText);
useEffect(() => {
setText(initialText);
}, [initialText]);
return (
<textarea
value={text}
onChange={e => setText(e.target.value)}
/>
);
}
---------------------
Svelte:<script> export let initialText; let text = initialText;
$: text = initialText;
</script><textarea bind:value={text} />
It's the ones that do some kind of server connection that introduce vulnerabilities and need active development.
But again, I don't think no support matters. How many DOM apis do you know of in the last 10 years that are essential? There are sites on JQuery 2 running fine.
Complex rendering model and hard to tame lifecycle since they ditched the class component. Very hard to get performant websites (but you're free to link me what you've produced with React and prove me wrong).
Also, biggest issue: severely misused for websites that are mostly static content and are nowhere near "app-like" nor have any particular reactivity need. 95%+ of react "applications" would've benefited from being written with a templating language instead.
E.g. Github was miles better under all aspects when it used ruby but of course somebody had to sell to upper management their promotion case.
[0]: https://github.blog/engineering/architecture-optimization/ho...
Which is entirely the issue. Supporting a browser for the 10 users who will update jQuery in 2025 is insane.
Is there some outlier place where people using virtual DOM frameworks don't also include 100-200kb of "ecosystem" in addition to the framework?
I suppose anything is possible, but I've never actually seen it. I have seen jQuery only sites. You get a lot for ~27kB.
I had started with a simple front-end that was using jQuery to quickly prototype the device controls, but quickly exceeded my goal of keeping the front-end at under 40KB total gzipped. The problem is needing more than just jQuery, we also needed jQueryUI to help with the front-end, or build out similar complex components ourselves. And as soon as the jQuery code became non-trivial, it was clear that Preact made much more sense to use. Our payload is quite a bit smaller yhan the jQuery prototype was.
Live on jQuery! Go forth and multiply!
Why hook up a virtual dom when you have a real one? Unless you're saying AI can't interact reliably with a real browser yet.
https://stackoverflow.com/questions/2826791/am-i-using-too-m...
https://css-tricks.com/reactive-jquery-for-spaghetti-fied-le...
I just try and get LLMs to do it for me because I'm lazy, and they like to use setInterval instead of mutationObservers and if it works, I just live with the inefficiency.
Oh the horrible things I do with Instagram...
function awaitElement(selector) {
return awaitPredicate(selector, _ => true);
}
function awaitPredicate(selector, predicate) {
return new Promise((resolve, _reject) => {
for (const el of document.querySelectorAll(selector)) {
if (predicate(el)) {
resolve(el);
return;
}
}
// Create a MutationObserver to listen for changes
const observer = new MutationObserver((_mutations, obs) => {
// You could search just inside _mutations instead of the entire DOM.
// Efficiency will depend primarily on how precise your selector is.
for (const el of document.querySelectorAll(selector)) {
if (predicate(el)) {
resolve(el);
obs.disconnect(); // Don't forget to disconnect the observer!
break;
}
}
});
// Start observing the document
observer.observe(document.documentElement, {
childList: true,
subtree: true,
attributes: false,
characterData: false,
});
});
}I kid you not, there were 30+ redux actions chaining in the most incomprehensible ways, the form literally had a textual input, a button to open the file explorer and a submit button.
It took few weeks one of their Romanian team to build it and apparently that team was reassigned and nobody could touch it without them.
I remember writing pages and pages of notes to understand how this all tied up in those extremely complex chains and claiming progress after few hours when I achieved to simplify the flow by removing a handful of these actions. Hooray.
Then it suddenly dawned on me that...I could just rewrite it from scratch.
Nuked the entirety of that nonsense and replaced it with a single useState in a matter of few hours also implemented the newly requested features.
The client could not believe my progress and the fact I also removed many of their previous issues.
Then I had a second realization: React was useless too and it got dropped for native HTML forms and a handful of JS callbacks.
I 100% believe this, as it describes all the redux codebases I've seen. The library seems to be an antipattern of indirection.
Even now I am not sure I could find a better tool to deal with real time data and synchronization. But for simple crud Redux is mostly overkill
For the anecdote, I remember my manager admitting we can't fix the legacy app, but we can put lipstick on the pig with React.
And in the same way faang is filled with leetcode blackbelt charlatans writing slop, so is Romania apparently.
I'm sure you'd 100% approve of such a statement of your country when based on one anecdotal recount (even if it true).
I was making a point that whether you graduate or not has little correlation with your capacity of handling higher abstractions and complexity, because neither bootcampers nor engineering graduates have the experience of building complex systems, let alone under time, tech leadership and management pressure.
It is likely that the original authors may have found themselves in a situation where they were tasked to build a trivial form with technologies they were not accustomed to at the request of some superior and they ended writing a soup.
Well structured redux (or mobx or zustand for that matter) can be highly maintainable & performant, in comparison to a codebase with poorly thought out useState calls littered everywhere and deep levels of prop drilling.
Redux Toolkit has been a nice batteries-included way to use redux for a while now https://redux-toolkit.js.org/
But the popularity of Redux especially in the earlier days of react means there are quite a lot of redux codebases around, and by now many of them are legacy.
Auto-generated actions from slices are a codified way to do what was once considered an antipattern: Tying an action directly to a single reducer, instead of actions being an action the user could do on a page (which multiple reducers could respond to).
To be fair, jQuery was a response to the the IE and JS variant mess of the early 2000s. jQuery made development possible without debugging across three browser varients.
If someone is still using jQuery for legacy reasons, BackboneJS might be a good intermediate step before going for a modern framework. Backbone is pretty light and pretty easy to grasp
Browser extension options pages are mostly a form mapped to what you have stored in the Storage API, so implementing them by handling the change event on a <form> wrapping all the options (no manual event listener boilerplate) then calling a render() function which applies classes to relevant elements (<body> classes are so good for conditionally showing/hiding things without manually touching the DOM), updates all form fields via named form.elements and re-generates any unique UI elements makes it so un-painful to change things without worrying you're missing a manual DOM update somewhere.
My options pages are Zen Garden-ing 5 different browser-specific UI themes from the same markup to match their host browsers, which is a brittle nightmare to maintain in an app which needs to change over time rather than static demo HTML, but once you've tamed the CSS, the state handling and re-rendering is so painless I'm sticking with it for a while yet, even though it would be long-term easier if I used Preact+htm for no-build option components which know what the active theme is and can generate specific UI for it.
My favourite dirty old-school knowledge is still the named global created for an element with an id, why bother selecting an element when it's right there (once you know you need to avoid global name collisions)?. I use those suckers all the time for quick fun stuff and one-off tool pages.
<h3 id="communityNoteHeading">
Readers added context they thought people might want to know
</h3>
<div>
<textarea id="communityNote" placeholder="Note" rows="5" style="width: 400px"></textarea>
</div>
<button id="communityNoteCopyButton" type="button">Copy</button>
<script>
communityNoteCopyButton.addEventListener('click', () => {
navigator.clipboard.writeText([
communityNoteHeading.innerText,
communityNote.value,
].join('\n\n'))
communityNoteCopyButton.innerText = 'Copied'
setTimeout(() => communityNoteCopyButton.innerText = 'Copy', 1000)
})
</script>Incredible it's still being maintained.
For extra flavor, const $$ = (selector) => document.querySelectorAll(selector) on top.
const $$ = (selector) => Array.from(document.querySelectorAll(selector))
is even nicer since then you can do things like $$('.myclass').map(e => stuff)Good times, I'm glad it is still around.
I can't believe how much public opinion has changed over the years. Love it, actually.
Anyway, jQuery always did the job, use it forever if it solves your problems.
While presumably jquery is slower than native selectors, maybe that could be pre-computed away.
If the verbosity bothers you, you can always define an utility function with a short name (although I'm not personally a fan of this kind of things).
https://developer.mozilla.org/docs/Web/API/Document/querySel...
https://developer.mozilla.org/docs/Web/API/Document/querySel...
https://developer.mozilla.org/docs/Web/API/Element/querySele...
https://developer.mozilla.org/docs/Web/API/Element/querySele...
But you might still break stuff in your own projects. Imagine you extend a native prototype with a method, and later the native prototype starts having a method with the same name.
Newer libraries start using that new standard method.
You upgrade the libraries your website depends on, or add a dependency, and this new code happens to depend on that native prototype. Only you replaced it with your custom method, and that method likely doesn't have the exact same behavior. You broke that new code and fixing this might not be trivial because uses of your custom method are sprinkled everywhere in your code.
It only works if you ever works on projects that have zero dependencies, or dependencies you never update.
Or you could spare yourself the troubles and define a method that takes the node in parameter.
It's also a question of forming good habits: you could be working on your projects now, forming a habit of extending prototypes, but will you remember not to do this the day you write a library?
By the way, how can you be sure you won't move some of your app code to a library because you like your utility functions and would like to reuse them in another project of yours? And why not open source that shared code, so you can just install it with NPM? Bam, that stuff is a library now.
He was suggesting adding a prototype method, not replacing one. Unless the library your using is also adding prototypes, I can't think of an issue with this. Sure, if a new version of JS ends up using these names then things could break, but I'd bet this won't cause him a problem in actuality.
For anyone that didn't know, IE8 implemented native JSON.(parse/stringify) methods, and the second parameter is a hydrator/dehydrator... however, if you added custom properties/methods to Array or Object prototypes, they would throw an error you couldn't catch in JS... so to work around, you'd have to load the JSON library and use it under a different name, in ALL your code, because the native implementation was locked/sealed and couldn't be masked out.
Second most annoying IE bug was 5.0.0 and the old/new api's for dealing with select elements. New worked, old broken, have fun.
(function (global) {
function $(selector, context = document) {
let elements = [];
if (typeof selector === "string") {
elements = Array.from(context.querySelectorAll(selector));
} else if (selector instanceof Element || selector === window || selector === document) {
elements = [selector];
} else if (selector instanceof NodeList || Array.isArray(selector)) {
elements = Array.from(selector);
} else if (typeof selector === "function") {
// DOM ready
if (document.readyState !== "loading") {
selector();
} else {
document.addEventListener("DOMContentLoaded", selector);
}
return;
}
return new Dollar(elements);
}
class Dollar {
constructor(elements) {
this.elements = elements;
}
// Iterate
each(callback) {
this.elements.forEach((el, i) => callback.call(el, el, i));
return this;
}
// Events
on(event, handler, options) {
return this.each(el => el.addEventListener(event, handler, options));
}
off(event, handler, options) {
return this.each(el => el.removeEventListener(event, handler, options));
}
// Classes
addClass(className) {
return this.each(el => el.classList.add(...className.split(" ")));
}
removeClass(className) {
return this.each(el => el.classList.remove(...className.split(" ")));
}
toggleClass(className) {
return this.each(el => el.classList.toggle(className));
}
hasClass(className) {
return this.elements[0]?.classList.contains(className) ?? false;
}
// Attributes
attr(name, value) {
if (value === undefined) {
return this.elements[0]?.getAttribute(name);
}
return this.each(el => el.setAttribute(name, value));
}
removeAttr(name) {
return this.each(el => el.removeAttribute(name));
}
// Content
html(value) {
if (value === undefined) {
return this.elements[0]?.innerHTML;
}
return this.each(el => (el.innerHTML = value));
}
text(value) {
if (value === undefined) {
return this.elements[0]?.textContent;
}
return this.each(el => (el.textContent = value));
}
// DOM manipulation
append(content) {
return this.each(el => {
if (content instanceof Element) {
el.appendChild(content.cloneNode(true));
} else {
el.insertAdjacentHTML("beforeend", content);
}
});
}
remove() {
return this.each(el => el.remove());
}
// Utilities
get(index = 0) {
return this.elements[index];
}
first() {
return new Dollar(this.elements.slice(0, 1));
}
last() {
return new Dollar(this.elements.slice(-1));
}
}
global.$ = $;
})(window);const $$ = document.querySelectorAll.bind(document);
const $ = (s, e = document) => e.querySelector(s)
and a similar one for $$.FWIW, also hated the old ASP.Net Webforms round trips (and omg massive event state on anything resembling dialup or less than a few mbps in the early 00's).
I just wish that React and other SPA devs kept some awareness of total payload sizes... I'm more tolerant than most, but you start crossing over/into MB of compressed JS, it's too much. Then that starts getting janky.
which I found while doing some performance work at one point. intercooler.js started as a custom function that hooked .load() in based on custom attributes (a trick I learned from angular 1.x)
deeply respect and love jquery
Is there still anything jquery does you cannot easily do with a couple lines of stdlib?
I mean, personally, I've mostly used React the past decade and any integration directly to the browser has been straight JS/TS... but I can still see how jQuery can be useful for its' conveniences.
Whats the current behemoth instead of JQ?
I perceive it as still being the de-facto standard?
There's probably some corner-case stuff it still makes easier if you're not using some framework, but I don't think there's a reason to go out of your way to use it just for the sake of using it.
maybe use Vue or something like mithril which doesn't require build. But jQuery is short and easy to grasp.
It was a nice ride, many thanks to the people that worked and still work on it. Not sure we'll ever see a jQuery 5, but that's life.
15+ years ago I wrote a tutorial for french people about using jQuery, it got a lot of views. I hope it helped spread jQuery.
Most of the changes are completely reasonable - a lot are internal cleanup that would require no code changes on the user side, dropping older browsers, etc.
But the fact that there are breaking API changes is the most surprising thing to me. Projects that still use jQuery are going to be mostly legacy projects (I myself have several lying around). Breaking changes means more of an upgrade hassle on something that's already not worth much of an upgrade hassle to begin with. Removing things like `jQuery.isArray` serve only to make the upgrade path harder - the internal jQuery function code could literally just be `Array.isArray`, but at least then you wouldn't be breaking jQuery users' existing code.
At some point in the life of projects like these, I feel like they should accept their place in history and stop themselves breaking compatibility with any of the countless thousands (millions!) of their users' projects. Just be a good clean library that one can keep using without having to think about it forever and ever.
I recently had to upgrade from jQuery 2 to the latest version, because an client demanded it (security issues), and just ran into compatibility issues with third party libs/plugins.
Looks like the core behavior doesn't change, something that people complain about, e.g. https://github.blog/engineering/engineering-principles/remov...
> This syntax is simple to write, but to our standards, doesn’t communicate intent really well. Did the author expect one or more js-widget elements on this page? Also, if we update our page markup and accidentally leave out the js-widget classname, will an exception in the browser inform us that something went wrong? By default, jQuery silently skips the whole expresion when nothing matched the initial selector; but to us, such behavior was a bug rather than a feature.
I completely agree with this, because I have been bitten so many times by this from subtle bugs. However I can see some other people not caring about any of it.
I already know that I am definitely not going to use jQuery in my personal projects, and there is no chance that my workspace does. (I much prefer letting a framework handle rendering for me based on data binding.) So none of that concerns me. But good luck to jQuery and anyone who sticks with it.
JQ is also used in frameworks like Bootstrap (although I think they’re trying to drop third-party dependencies like this since they tend to cause conflicts).
I have also used JQ in an Angular app where complex on-the-fly DOM manipulation just isn’t practical with standard tooling.
https://youmightnotneedjquery.com/
Yes, sometimes the vanilla JS analogs are not the most elegant, but the vast majority are not terribly complicated either.
IMHO, another advantage of vanilla JS (aside from saving ~30KB) is potentially easier debugging. For example, I could find / debug the event listeners using the dev tools more easily when they were implemented via vanilla JS, since for complicated event listeners I had to step through a lot of jQuery code.
Thanks guys!
Has anyone done any benchmarks yet to see how jQuery 4 compares to jQuery 3.7?
But then Google, Chrome, iPhone, PWA or JS for everything took over and took a completely different path to what I imagine webpage would be.
I’m glad JavaScript has evolved to the point we don’t need jQuery anymore.
For what it’s worth, if you’re looking for a more structured approach on top of jQuery, JsViews (https://jsviews.com) provides a reactive templating and data-binding system that’s been around and stable for many years.
It hasn’t seen the same level of adoption as newer frameworks, but it may still be of interest to people who prefer the jQuery ecosystem.
Regarding adoption levels, the JsViews website made me think I had accidentally toggled the "Desktop Site" option in my Iceweasel browser, I wonder if that scared people off. Or perhaps it's because, as others mentioned, most jQuery development these days is in legacy codebases where the devs are not allowed to add any new libraries, reducing the adoption rates of any new jQuery libraries even more than you'd expect based on the raw nrs of jQuery users.
(the website does work though, and it loads fast. Which is something I've always appreciated about jQuery based sites still alive today. The only thing I'm missing is any indication of how big it is when minified + gzipped. EDIT: jsrender.js is 33.74 kB, jsrender.min.js a mere 12.82 kB)
I also raised the jQuery dependency concern with Boris for exactly the reason you mentioned: many teams automatically rule out anything that requires jQuery, especially outside of legacy codebases. That’s a real barrier today.
For what it’s worth, a jQuery-free version may happen. Boris is actively exploring it, but he’s making no promises—it’s a non-trivial problem and would effectively require a full rewrite rather than a simple refactor.
My next question would be, is this something that OpenAI and Anthropic would train their data on? If I ask Claude Code to write an app and utilize jQuery, would it resolve to the previous version until it's retrained in a newer model?
they have legendary backwards compatibility.
most of the breaking changes are dropping support for ancient browsers.
so yes, LLMs are great with jQuery.
Thank you for everything you've done for us.
[1]: https://htmx.org/
Having said that, after JQuery 1.x, and in particular, the changing, the deprecating, and the dropping of things here and there, JQuery no longer made sense. Somewhat similar to the SDL situation in the C/C++ word. An important role of JQuery, similar to SDL, was a strong code contract before anything else, and if the developer now has to account for JQuery's version differences like having to account for browser differences, what is the point.
Are you talking about STL? But even there it makes no sense
However, and adding to other replies, by SDL I assume you mean the Simple Directmedia Layer?
SDL looks rather strong from my perspective and still my typical goto when having fun making a game. You could argue SDL lost some customers in favour of other libraries like RayLib - or moving away from making things from scratch to Unreal, Unity, etc.
SDL still seems popular - as SDL version 3 was officially released less than a year ago (or it feels like it) However, I guess it depends what you need to do.
Could you explain this please?
Before jQuery, I had vanilla JS code that factored in Safari, Firefox, Opera... and... IE6, IE7, and then IE8 which was (from memory) recent at the time.
Trying to design a visual drag n' drop editing interface on the web was a chore at the time especially with the differences in IE browsers! It was suprising how many customers were still using IE6!
A lot of this is purely by memory, now. I even have shivering memories reminding myself I was using VB.NET with ASP.NET Web forms. I really HATED it!
I remember ASP.NET provided dynamic web pages with things like Placeholder tag, etc. Again, It felt bloated even back then but I made it work. It was a balance of using what was recommended by other developers, and trying to ensure performance is good.
By around end of 2009, I tried jQuery as an experimental branch and very impressed with its capabilities. Despite being a decent Javascript developer at the time I was inexperienced with AJAX (Technically I was a Junior dev in ways) but jQuery shows me the way. It was not long before I ditched certain features of .NET Web Forms for jQuery.
At the time, there may have been a little overhead replacing various javascript code I am written with jQuery but the rewards were high. It was cleaner frontend and backend code, thanks to simple AJAX calls.
Since then I've always had huge respect for jQuery! While I don't consider myself a decent javascript as I don't use it much. However, when I do come back to web development, I cannot be asked with the modern ways. To me it's bloat. I just stick with htmx, now. If I have do some fancy things visually then I will use jQuery.