[{"data":1,"prerenderedAt":30},["ShallowReactive",2],{"case-wechat-h5-storage-debug-en":3,"blog-list-en":13},{"slug":4,"title":5,"summary":6,"date":7,"featured":8,"seoDescription":9,"series":10,"seriesOrder":11,"html":12},"wechat-h5-storage-debug","H5 Debug in Practice (1): WeChat H5 Local Cache—Debug It on Desktop","After switching test accounts in a WeChat official-account H5, the avatar still showed the old user—capture had the new token, stale data stayed in localStorage. This post walks through a real joint-debug case and how to view and edit localStorage, sessionStorage, and IndexedDB in WeChat WebView from your PC.","2026-07-11",true,"DevPeek H5 debug: locate localStorage, sessionStorage, and IndexedDB cache issues in WeChat H5—compared with vConsole and remote debug, with real WebView debugging workflow.","h5-debug",1,"\u003Ch2>Case: avatar stuck after account switch\u003C\u002Fh2>\n\u003Cp>During joint debug on an official-account H5, QA reported in the group chat:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>“The H5 in the official-account menu—I logged in with a new test account, but the avatar is still the previous user. Clearing WeChat cache and re-entering from the menu didn’t help.”\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>The first suspects are usually:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Login didn’t actually succeed?\u003C\u002Fli>\n\u003Cli>Backend cache?\u003C\u002Fli>\n\u003Cli>WeChat cached the API response?\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>So I captured traffic in DevPeek first.\u003C\u002Fp>\n\u003Cp>\u003Ccode>GET \u002Fapi\u002Fuser\u002Fprofile\u003C\u002Fcode>\u003C\u002Fp>\n\u003Cp>The \u003Ccode>Authorization\u003C\u002Fcode> header already carried the \u003Cstrong>new\u003C\u002Fstrong> account’s token.\u003C\u002Fp>\n\u003Cp>The response body had the new user’s id and nickname too.\u003C\u002Fp>\n\u003Cp>From the server’s view, everything looked fine.\u003C\u002Fp>\n\u003Cp>On the page, the avatar and nickname were still the previous test account.\u003C\u002Fp>\n\u003Cp>That pattern usually means:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>The API is fine, but the page isn’t using what the API returned.\u003C\u002Fstrong>\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>The real problem is probably no longer HTTP—it’s the page’s own local cache.\u003C\u002Fp>\n\u003Ch2>Capture OK doesn’t mean the page reads the right data\u003C\u002Fh2>\n\u003Cp>Many H5 login flows write user info to:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>localStorage\u003C\u002Fli>\n\u003Cli>sessionStorage\u003C\u002Fli>\n\u003Cli>IndexedDB\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Then rendering reads from cache instead of re-fetching every time.\u003C\u002Fp>\n\u003Cp>If on account switch:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>the token updates\u003C\u002Fli>\n\u003Cli>cookies clear\u003C\u002Fli>\n\u003Cli>but storage doesn’t\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>you can get:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>new user on the wire, old user on screen.\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>One easy-to-miss point:\u003C\u002Fp>\n\u003Cp>\u003Cstrong>After an HTTP request finishes, how the page writes the response into localStorage or IndexedDB is browser JavaScript runtime behavior—not something capture tools are built to show.\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>\u003Ca href=\"\u002Fen\u002Fdocs\u002Fcapture\u002F\">Capture\u003C\u002Fa> is good at URL, headers, and body; \u003Ca href=\"\u002Fen\u002Fdocs\u002Fparam-transform\u002F\">param transform\u003C\u002Fa> can decrypt encrypted bodies too. But \u003Cstrong>\u003Ccode>localStorage.getItem(&#39;auth_token&#39;)\u003C\u002Fcode> never appears as a column.\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>So for many cases where:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>APIs look fine\u003C\u002Fli>\n\u003Cli>the page looks wrong\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Network alone is hard to debug.\u003C\u002Fp>\n\u003Cp>What’s missing is:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>what the page JavaScript is actually reading from storage right now.\u003C\u002Fstrong>\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Ch2>Desktop DevTools works—but WeChat WebView is different\u003C\u002Fh2>\n\u003Cp>Open the same URL in Chrome and you can go to:\u003C\u002Fp>\n\u003Cp>Application → Storage\u003C\u002Fp>\n\u003Cp>and inspect localStorage.\u003C\u002Fp>\n\u003Cp>But QA needed reproduction in:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>the official-account menu\u003C\u002Fli>\n\u003Cli>WeChat QR scan\u003C\u002Fli>\n\u003Cli>WeChat share links\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>—real environments, not desktop.\u003C\u002Fp>\n\u003Cp>Desktop Chrome and WeChat’s in-app WebView are often not the same runtime.\u003C\u002Fp>\n\u003Cp>Editing storage on desktop doesn’t prove the WeChat issue is fixed.\u003C\u002Fp>\n\u003Cp>At the time:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>capture confirmed the new token in headers;\u003C\u002Fli>\n\u003Cli>the WeChat page still showed the old avatar.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>The two sides never lined up.\u003C\u002Fp>\n\u003Ch2>vConsole-style tools: fine for logs, awkward for storage\u003C\u002Fh2>\n\u003Cp>The team had used \u003Cstrong>vConsole\u003C\u002Fstrong> on H5; some colleagues used \u003Cstrong>eruda\u003C\u002Fstrong> or similar in-page panels.\u003C\u002Fp>\n\u003Cp>For:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Console\u003C\u002Fli>\n\u003Cli>Network\u003C\u002Fli>\n\u003Cli>JS errors\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>they work great.\u003C\u002Fp>\n\u003Cp>Once you start digging into storage, it’s a different phase.\u003C\u002Fp>\n\u003Cp>For example:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>localStorage is often view-only; edits usually mean switching to Console and hand-written scripts;\u003C\u002Fli>\n\u003Cli>IndexedDB plugins can list stores, but deep object stores are slow to browse on a phone screen;\u003C\u002Fli>\n\u003Cli>deleting a row or editing JSON often means calling \u003Ccode>indexedDB.open(...)\u003C\u002Fcode> yourself;\u003C\u002Fli>\n\u003Cli>the phone screen is small—capture, specs, and Storage sit on different devices, so cross-checking is slow;\u003C\u002Fli>\n\u003Cli>many teams bake debug tools into H5 ahead of time; ad-hoc joint debug doesn’t always have time for a new build.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>WeChat WebView \u003Cstrong>remote debug\u003C\u002Fstrong> (\u003Ccode>chrome:\u002F\u002Finspect\u003C\u002Fcode>, Safari Web Inspector) can work, but WeChat version, OS version, and USB connection make it unreliable in practice.\u003C\u002Fp>\n\u003Cp>Comparison from our joint-debug work (“vConsole-style” covers vConsole, eruda, and common Storage plugins; exact features vary by version):\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Capability\u003C\u002Fth>\n\u003Cth>vConsole \u002F eruda\u003C\u002Fth>\n\u003Cth>DevPeek · Session\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>View localStorage\u003C\u002Ftd>\n\u003Ctd>Generally supported\u003C\u002Ftd>\n\u003Ctd>Desktop table view\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Edit localStorage\u003C\u002Ftd>\n\u003Ctd>Console scripts\u003C\u002Ftd>\n\u003Ctd>GUI edit, push to device\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>sessionStorage\u003C\u002Ftd>\n\u003Ctd>Plugin-dependent\u003C\u002Ftd>\n\u003Ctd>Dedicated sub-tab, view and edit\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>document.cookie\u003C\u002Ftd>\n\u003Ctd>Partial support\u003C\u002Ftd>\n\u003Ctd>View and edit (HttpOnly hidden)\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>View IndexedDB\u003C\u002Ftd>\n\u003Ctd>Supported\u003C\u002Ftd>\n\u003Ctd>Tree browser\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Edit IndexedDB\u003C\u002Ftd>\n\u003Ctd>Mostly scripts\u003C\u002Ftd>\n\u003Ctd>JSON edit, push to device\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Same chain as capture\u003C\u002Ftd>\n\u003Ctd>No\u003C\u002Ftd>\n\u003Ctd>Network and Session on one page\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Rollout\u003C\u002Ftd>\n\u003Ctd>Usually baked into H5\u003C\u002Ftd>\n\u003Ctd>Proxy inject—see \u003Ca href=\"\u002Fen\u002Fdocs\u002Fdebug-replay\u002F\">mobile web debugging\u003C\u002Fa>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>vConsole isn’t useless.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Logs and JS errors\u003C\u002Fstrong>—still a good fit.\u003C\u002Fp>\n\u003Cp>What actually blocked us this time:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>repeat edit, delete, and verify of storage and IndexedDB inside real WeChat.\u003C\u002Fstrong>\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>On a small screen, that’s clearly slower than on a desktop.\u003C\u002Fp>\n\u003Ch2>Locating stale data with Session: old token in localStorage\u003C\u002Fh2>\n\u003Cp>Point the phone’s Wi‑Fi proxy at DevPeek, trust the root CA, and put business hosts in \u003Ca href=\"\u002Fen\u002Fdocs\u002Fproxy-ssl\u002F\">SSL decrypt scope\u003C\u002Fa>. Full checklist: \u003Ca href=\"\u002Fen\u002Fdocs\u002Fdebug-replay\u002F\">mobile web debugging\u003C\u002Fa>; if the preview stays on “Waiting for device connection”, see \u003Ca href=\"\u002Fen\u002Fdocs\u002Ffaq\u002F\">FAQ\u003C\u002Fa> for inject and WebSocket troubleshooting.\u003C\u002Fp>\n\u003Cp>Once connected, the \u003Cstrong>Debug\u003C\u002Fstrong> tab mirrors the WeChat H5 page; switch the built-in panel to \u003Cstrong>Session\u003C\u002Fstrong>:\u003C\u002Fp>\n\u003Col>\n\u003Cli>On \u003Cstrong>Capture\u003C\u002Fstrong>, confirm decrypted HTML traffic for that phone.\u003C\u002Fli>\n\u003Cli>On \u003Cstrong>Debug\u003C\u002Fstrong>, pick the \u003Cstrong>client tab\u003C\u002Fstrong>; have QA \u003Cstrong>re-enter from the official-account menu\u003C\u002Fstrong> (stale tabs may miss inject).\u003C\u002Fli>\n\u003Cli>Session → \u003Cstrong>localStorage\u003C\u002Fstrong>—check token first, then user cache.\u003C\u002Fli>\n\u003Cli>\u003Ccode>auth_token\u003C\u002Fcode> still held the \u003Cstrong>previous\u003C\u002Fstrong> test account’s JWT.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>Capture headers already showed the new token because requests sometimes read a fresh in-memory value; avatar rendering still read localStorage—two sources out of sync.\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fdocs\u002Ffigures\u002Fdebug_local_storage.png\" alt=\"DevPeek Debug Session: localStorage list and edit\">\u003C\u002Fp>\n\u003Cp>\u003Cem>Edit key values on desktop and push to the real device—no \u003Ccode>localStorage.setItem\u003C\u002Fcode> in Console.\u003C\u002Fem>\u003C\u002Fp>\n\u003Cp>After editing \u003Ccode>auth_token\u003C\u002Fcode> to the new account and confirming push, delete:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>user_profile_cache\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Refresh the page—the avatar fixed immediately.\u003C\u002Fp>\n\u003Cp>That pretty much confirmed where the bug lived.\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>DevPeek Session shows data the current page JavaScript can access—not every browser-level store. HttpOnly cookies, WeChat JSBridge, and mini-program native storage are out of scope; visible cookies can be checked in the Cookies sub-tab.\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Ch2>Second issue: draft order wouldn’t leave the list\u003C\u002Fh2>\n\u003Cp>After the avatar was fixed, QA raised another:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>“After I delete a draft order and reopen the list, it comes back.”\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>That didn’t smell like localStorage.\u003C\u002Fp>\n\u003Cp>Switch to \u003Cstrong>IndexedDB\u003C\u002Fstrong> and expand:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>orders\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>The row was still in the database; the status field hadn’t updated either.\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fdocs\u002Ffigures\u002Fdebug_indexeddb.png\" alt=\"DevPeek Debug Session: IndexedDB store and record detail\">\u003C\u002Fp>\n\u003Cp>\u003Cem>Expand the object store, edit JSON in the detail pane, and push—easier than hand-written \u003Ccode>indexedDB\u003C\u002Fcode> APIs on a phone.\u003C\u002Fem>\u003C\u002Fp>\n\u003Cp>Confirm the fields, edit JSON, push to the device; refresh—the draft order finally disappeared.\u003C\u002Fp>\n\u003Cp>Many “delete failed,” “stale list,” or “offline data” issues are IndexedDB not syncing—not just a bad API response.\u003C\u002Fp>\n\u003Ch2>How I cross-check after fixing storage\u003C\u002Fh2>\n\u003Cp>After locating a storage issue, I usually confirm two more things:\u003C\u002Fp>\n\u003Col>\n\u003Cli>Back to \u003Cstrong>Network\u003C\u002Fstrong> in the debug panel—check whether later request headers match what I changed in Session;\u003C\u002Fli>\n\u003Cli>If I need different parameters, switch to \u003Cstrong>Capture\u003C\u002Fstrong> and open \u003Cstrong>Debug API\u003C\u002Fstrong> on the same row to resend—no Postman.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>That keeps \u003Cstrong>Session → Network → page\u003C\u002Fstrong> on one debug chain; for bulk key clears or heavier scripts, \u003Cstrong>Console\u003C\u002Fstrong> remote eval works in the same context—confirm key names before wiping.\u003C\u002Fp>\n\u003Ch2>Limits and caveats\u003C\u002Fh2>\n\u003Cp>Not every cache issue is fixed by editing Storage. Full boundaries: \u003Ca href=\"\u002Fen\u002Fdocs\u002Fdebug-replay\u002F\">mobile web debugging\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>For example:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>localStorage updated but APIs still 401—the token may live in HttpOnly cookies or another login path; compare Network and Session;\u003C\u002Fli>\n\u003Cli>WeChat may cache old HTML—re-enter from the menu or add a cache-busting query;\u003C\u002Fli>\n\u003Cli>iframe pages are another origin—open that URL separately to debug.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>Next\u003C\u002Fh2>\n\u003Cp>\u003Cstrong>H5 Debug in Practice (2): TBD\u003C\u002Fstrong>—more real joint-debug cases (Console remote scripts, Network and Mock on the same chain), not just tool tours.\u003C\u002Fp>\n\u003Chr>\n\u003Cp>If you keep editing localStorage and IndexedDB in WeChat H5 joint debug, \u003Ca href=\"\u002F\">try DevPeek\u003C\u002Fa> or discuss on \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FGYPengDev\u002Fdevpeek\u002Fdiscussions\">GitHub Discussions\u003C\u002Fa>. Setup: \u003Ca href=\"\u002Fen\u002Fdocs\u002Fdebug-replay\u002F\">mobile web debugging\u003C\u002Fa>; proxy and certs: \u003Ca href=\"\u002Fen\u002Fdocs\u002Fproxy-ssl\u002F\">proxy &amp; SSL\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2>Related docs\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"\u002Fen\u002Fdocs\u002Fdebug-replay\u002F\">Mobile web debugging\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fen\u002Fdocs\u002Fcapture\u002F\">Capture and request details\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fen\u002Fdocs\u002Fproxy-ssl\u002F\">Proxy &amp; SSL certificates\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fen\u002Fdocs\u002Ffaq\u002F\">FAQ\u003C\u002Fa>\u003C\u002Fli>\n\u003C\u002Ful>\n",{"items":14},[15,16,24],{"slug":4,"title":5,"summary":6,"date":7,"featured":8,"seoDescription":9,"series":10,"seriesOrder":11},{"slug":17,"title":18,"summary":19,"date":20,"featured":8,"seoDescription":21,"series":22,"seriesOrder":23},"why-we-built-devpeek-h5-debug","Why We Built DevPeek (2): That H5 Page in the App—Debug It on Your PC","Param transform fixed login, but the activity H5 only broke inside the App WebView. Remote debug and capture lived in different windows—so we folded mirroring and our own debug panels into DevPeek.","2026-07-10","DevPeek origin series, part 2: in-app H5 bugs that only show on real devices, the split between remote debug and capture, and how the Debug tab mirrors pages with built-in DOM, Console, and Network panels.","origin",2,{"slug":25,"title":26,"summary":27,"date":28,"featured":8,"seoDescription":29,"series":22,"seriesOrder":11},"why-we-built-devpeek","Why We Built DevPeek (1): HTTPS Decrypted, Body Still Gibberish","The night before a release, TLS was already open—but changing one request field still meant digging up encrypt\u002Fdecrypt scripts. That pushed us toward a proxy tool with business-layer crypto built in—and DevPeek started there.","2026-07-09","DevPeek origin series, part 1: the manual request-body encrypt\u002Fdecrypt grind—and why we set out to build a proxy tool that owns business-layer crypto.",1783708286244]