Hahahaha, taint
Posts by K.
I should really learn what durable objects are and why everyone likes them so much, will definitely check it out if you post it on here!
Wow just tried Tanstack table for the first time, the API is really clean!
Oi! New video is up, it's on a game that for all intents and purposes should exist, but does. And that's kind of rad. The game itself is pretty good too.
I'm talking about S.T.A.L.K.E.R. 2, by the way youtu.be/WjkFrF0VSho?...
Awesome!
Woke up looking for the broccoli
Mr get off dropppppeeeddddddd
Tested this from the cottage this weekend on spotty, slow internet and works well!
When I pick this up again I'm going to learn about CDNs and how they are so fast, and how to host my own for my toy rom manager app
Okay, so caching going kinda smoothly! Stats:
-server cache hits are ~90ms (this is also true of client cache misses hitting a server cache)
-client cache hits send no network request
-server cache misses are a bit expensive at ~600ms but my app uses no CDNs for images and sends base64 string 🤫
Oh! Also any custom or opinionated linting rules you like!
Thanks sensei
Naming recommendations (files, functions, variables), alignment, fn defs (const vs function), type X = SomeType vs Interfaces, how many components per file (after reading full stack components, this seems obvious but I think would be good to get into), any opinionated lint rules and why
Eyyyy its fuckin bobbo
Getting older is realizing useState was just an escape hatch all along
I think I may be allowed to use remix at work for a new project, yessssssssssss
This series is so good, I think I'll do the same!
Version I have now (with no stale-while-revalidate functionality)
I think this could be simplified a ton by allowing developers to modify the request that is made to your server with `serverLoader()` in the `clientLoader`. The browser could handle ETag validation!
Code sample illustrating a potential client side cache implementation in Remix. Code to follow: export async function withClientCache<T, S extends StoreKey>({ store, cacheKey, ttl, serverLoader, request, params, }: WithClientCacheOptions<T, S>) { try { let key = typeof cacheKey === "function" ? cacheKey(params) : cacheKey; let cached = await cacheManager[store].get(key); if (cached) { let age = Date.now() - cached.timestamp; let isExpired = age >= ttl; if (!isExpired) return cached.data; if (cached.eTag) { let versionCheck = await fetch(request.url, { method: "HEAD", headers: { "If-None-Match": cached.eTag, }, }); if (versionCheck.status === 304) { await cacheManager[store].set(key, { data: { ...cached } as any, timestamp: Date.now(), eTag: cached.eTag, }); return cached.data; } } } let freshData = await serverLoader(); await cacheManager[store].set(key, { data: { ...freshData }, timestamp: Date.now(), eTag: freshData.eTag, }); return freshData; } catch (error) { console.error("Cache error:", error); return serverLoader(); } }
client cache:
Protip: add a `DEPLOY_SECRET` or something to eTag generation or waste time wondering why deploys mess up the cache 😅
Where I've landed: the server cache is longer lived and invalidated on mutation, the client cache is 25% of the server cache and on expiry it sends a HEAD request to check the eTag, if it is different, await the server's full response
I think I've been overthinking caching, and should just go with something and measure the impact of the cache before optimizing everything. A 90ms (on my not-so-good internet connection to my server) round trip is good, but most requests not leaving the browser makes this feel so good
client loaders also strip headers, which I guess I get, but getting the eTag would have been awesome :(
Nice! I really like the pattern of abusing the URL for app state so I'm excited to give this a try
Current caching dilemma:
Implementing a HEAD request to check an ETag on the server in a Remix client Loader adds a 90ms round trip to navigation. When just relying on a TTL, you only paid the network cost once.
I wonder where the line is, no one told me this was just tradeoffs all the way down ðŸ˜
I think I'd like it more with one level of configuration, at first glance
searchTerm: {
urlKey: 'q',
parse: parseAsString,
default: ''
}
TIL about input.validity and input.setCustomValidity(), I wonder if I could use this as strong defaults wrt to assistive technologies over aria-described-by. AI is a little too wishy-washy with its answers to say if it's a good idea or not
html.spec.whatwg.org/multipage/fo...
(back to caching)
I find its also really good at giving you primers on topics you may not have encountered yet. I often ask it to walk me through topics, even advanced ones, and then I can look up the primary source later if I need to.
Super useful if you are newer in your career or at an intermediate level I think!