| name | wsh-jquery-removal |
| description | Replacing jQuery with native fetch API in WSH 2026. Covers async:false sync XHR replacement, fetchBinary, fetchJSON, sendFile, sendJSON, and ProvidePlugin removal. |
WSH: jQuery Removal
jQuery's async: false option is the single biggest TBT contributor in the client. It performs synchronous XMLHttpRequests that block the main thread completely during every API call.
Use this skill when replacing jQuery with native fetch API.
Techniques
1. Replace fetchers.ts
import $ from "jquery";
export async function fetchBinary(url: string): Promise<ArrayBuffer> {
const result = await $.ajax({ async: false, dataType: "binary", responseType: "arraybuffer", url });
return result;
}
export async function fetchJSON<T>(url: string): Promise<T> {
const result = await $.ajax({ async: false, dataType: "json", method: "GET", url });
return result;
}
export async function fetchBinary(url: string): Promise<ArrayBuffer> {
const response = await fetch(url);
return response.arrayBuffer();
}
export async function fetchJSON<T>(url: string): Promise<T> {
const response = await fetch(url);
return response.json() as Promise<T>;
}
export async function sendJSON<T>(url: string, body: unknown): Promise<T> {
const response = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
return response.json() as Promise<T>;
}
export async function sendFile(url: string, file: ArrayBuffer, mime: string): Promise<void> {
await fetch(url, {
method: "PUT",
headers: { "Content-Type": mime },
body: file,
});
}
2. Remove jQuery from Webpack
entry: {
main: [
"./src/index.css",
"./src/tsconfig.build.json",
"./src/index.tsx",
],
},
plugins: [
],
3. Uninstall jQuery Packages
cd application/client && pnpm remove jquery jquery-binarytransport
Pitfalls
| Pitfall | Symptom | Fix |
|---|
| Components depending on sync behavior | Race conditions, data not ready | Ensure useFetch hooks handle async properly |
| sendJSON needs credentials | Session cookies not sent | Add credentials: "same-origin" to fetch options |
| Binary response handling | Data format mismatch | Use response.arrayBuffer() |
| ProvidePlugin still in config | Build error: $ is not defined | Remove ProvidePlugin entry |
VRT Risks
| Change | Visual Impact | Mitigation |
|---|
| Async fetch | Data may load in different order | Usually not visible, same end state |
| Removed jQuery globals | None if all usages replaced | grep for $ and jQuery in codebase |
Project-Specific Notes
fetchers.ts at application/client/src/utils/fetchers.ts
- 4 functions: fetchBinary, fetchJSON, sendFile, sendJSON
- fetchBinary is used by CoveredImage, PausableMovie (heavy usage)
- fetchJSON is used by useFetch hook (all data loading)
- sendJSON is used for auth (signin, signout, signup) and post creation
- sendFile is used for image upload in post creation
- The
async: false causes ~500ms-2000ms main thread blocks per request
- Session cookies are needed for authenticated requests — include credentials