I have two pages which are pretty much the same pages, but one has some additional element to show, and another doesn't. Nothing fancy like some private user data or authentication: pages are purely static.
So what I want is to show one of those two pages under the same url, depending on a parameter stored on user device (most likely cookie).
I only see three solutions to that, each with their problems:
Stick to the static approach, and just make it two different pages, having two different urls. I don't like this approach, since those pages serve the same purpose, and I don't want users to share two different links of the same page.
Stop treating that as statics, and use
getServerSideProps
, and render different components depending on a cookie. Of course I don't like this approach either: the page is no more static, i.e. it loses its simplicity, getServerSideProps disables static optimization, so requests are handled slower.Stick to the static approach, and handle the logic on the client: render different components depending either on a cookie or localStorage. Though it doesn't have disadvantages of the first two approaches, I don't like this approach either, because since the initial render is different for client and server, so when DOM gets replaced, you experience "content jumping" (similar to this one but my case has more complex nature). Aside content jumping, you get a warning in console in development mode:
Warning: Did not expect server HTML to contain a ...
, - thanks toreact-dom
(otherwise it would be harder to track such problems).
The third option seems the best among else, but it's not ideal. I will temporarily use this approach for my things, but I'd like to open conversation to solving this problem at least, and in the end discover a solution to that.
UPD.
It seems you guys can't even imagine it's possible. First, let me explain the problems with some naive "immediate" approaches ("immediate" because it's first solutions appearing in mind, not because it's "fast"):
More complex styles to avoid content jumping. Though it's possible to set constant height (rather than default
height: auto
), so the overall page height won't change, but it's not only a too strict constraint, which is hard to deal with from design standpoint (sometimes you just can't give elements a constant height), but it also doesn't solve another problem: flickering.Custom server, which handles routing logic, and no more than that. It's even worse than option #2 (with getServerSideProps), - it disables static optimizations globally, not just for a certain page, but for whole application. Not to mention it's not deployable to Vercel. It's anti-NextJSy. Too bad.
I've spent whole day dealing with this problem, now let me describe one potential direction which might solve the problem: PWA cache. Shortly: it should be something similar to option #1 (with two different static pages), but the problem of different urls is solved by managing PWA cache.
So by default we show one page, and after certain user interactions, we run cache.put(request, response)
, - where the response is the second page, so I kinda swap one page with another, and then, upon visiting this url, it's INITIALLY shown with proper elements, while the url hasn't changed (under the hood cache is using another url, but in browser it's the same url). On MDN there's an example of how to do that when you try recovering failed requests, but it's possible to do on whatever event: user interactions too.
Helpful links
Recovering Failed Requests article
cache.put
documentationCacheFirst
strategy documentation (seems to be the most appropriate here)
TL;DR
Though I see a potential solution using PWA, I would not hurry celebrating the discovery, - I have no working example yet. I'm not sure when I'll have that, - quite a lot of things to do, etc. But hopefully I'll have more time for that and I'll figure this out, and consider this question solved. Probably not soon. Code samples/gists/repositories are welcomed.
If neither of the 3 options satisfy your needs, then I would consider a 4th option: