-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hydration errors when enabling JavaScript #83
Comments
The issue seems to be that the server formats slightly differently than the client does. Specifically spaces are NARROW NO-BREAK SPACE instead of normal spaces This is the best I could find on the issue: nodejs/node#45171. However, that concerns node 19 and says it's a bug 🤷♂️ Solutions I see:
|
Good catch! I was confused why the strings looked exactly alike, but figured the fix would be the same anyway. And agreed, formatting on the server seems like the best route. |
From what i can tell, there is a change with ICU. take the following code const SPACE_CHAR_CODE = 32;
const NARROW_NO_BREAK_CHAR_CODE = 8239;
console.log("versions", { node: process.versions.node, icu: process.versions.icu });
const date = new Date("2023-03-01T12:00:00.000Z");
const formatter = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "2-digit"
});
const formattedString = formatter.format(date);
function countCharCode(string, charCode) {
let count = 0;
for (let i = 0; i < string.length; i++) {
if (string.charCodeAt(i) === charCode) {
count++;
}
}
return count;
}
const spaceCount = countCharCode(formattedString, SPACE_CHAR_CODE);
const narrowNoBreakCount = countCharCode(formattedString, NARROW_NO_BREAK_CHAR_CODE);
console.log(formattedString, { spaceCount, narrowNoBreakCount }); Running that with node 18 returns
Running that with node 16 returns
this project was moved to node v18 via #73 and thus inherently moved to ICU 72. I think the relevant change in ICU 72 is
it seems like this thin space is only used before the PM/AM. my other tweaks say that "real" spaces are used everywhere else i could see. it's not clear to me how to figure out what icu most browsers are using, but i suspect the issue here is they're not using ICU 72. options for moving forward and my two cents on each:
if you use a 24-hour clock and format it as
this is a more direct solution. the problem is we opted in for thin spaces unknowingly. lets opt out. i'm not sure if there was a reason for node 18 (other than it's the latest and greatest) tho. was there a specific node 18 feature that was needed?
this seems like what's being attempted on #84 but i would challenge that this kind of defeats the point of hydration. so it feels a bit odd to me, but not the end of the world. i would also push to move the convo to a broader framing: how do you handle dates when doing SSR/hydration? i'm not sure the best practice is "just don't hydrate dates at all". maybe it is. not sure. seems extreme to say that i can never do a
in theory browser's will move to ICU 72. and this all goes away. this do nothing approach should probably be coupled with some research on how browser's handle ICU to confirm this is a good strategy. (i don't know enough about how the browser is handling ICU versions) another argument for do nothing is that this isn't a problem today. it's only a problem if you turn on js, which leads me to ...
you posit that this is a problem b/c "At some point we'll likely need js 🤷♂️". i'm not sure that's true. you discovered this b/c of some sentry-related work i gather? i've kind of had a question about whether or not sentry is needed for a project like this. it's not really a remix concept. skimming #1 again, the goals that stick out are SEO and facilitating things around the group that meetup.com doesn't do (content, sign up for talks). it's not clear to me what sentry adds to that. i wouldn't expect what amounts to a largely static blog to have something as sophisticated as sentry. and largely static blog likely doesn't need js. i would vote to do nothing until it becomes a real problem and at that point see if the ICU thing has gone away by then. and if not finished by that time, either drop the am/pm or use luxon. |
this shows firefox moving to 71, and i couldn't find a similar entry about it moving to 72. |
Super helpful writeup, thank you Colby! Appreciate all the suggestions and thoughts. Yeah, disallowing As for using node 18, I'd prefer for us to be using whatever node LTS is, which right now is 18. This doesn't seem like a big enough issue for us to drop node versions |
Thank you for the deep dive, @colbywhite! TIL a lot!
I just don't want to paint ourselves into a corner where we can't easily turn on js when we need it. re: Sentry ... Since it's a community project where others can deploy code to production, having some error monitoring in place will help us know if/when we break something, even if our site is super simple at the moment. Plus, I got us a free license as an OSS project, and it can also give us performance data and web vitals, which is a bonus 😎 |
for what it's worth, we use Luxon and like it a lot (and I'm pro javascript) |
Alright, finally sat down and read through this textbook @colbywhite produced (sincerest thanks, this was super helpful! 🙏) I want to address each of the options:
I'd rather not move to a 24 hour clock just to solve this issue. I think PM is still helpful (even though I assume most people wouldn't expect the even to be in the morning).
I'd prefer to stay on node 18, since it's LTS and it's better to keep up to date. Going backwards just for a single node/browser mismatch like this just seems like tackling the wrong problem
Alternatively, we could use Luxon in the server only, but then we basically have to do what's mentioned in the next point, which Colby listed some good reasons against doing.
I totally agree with Colby's analysis. I think I was taking the wrong approach -- if we're shipping JS we should expect hydration to work. Having arbitrary tribal-knowledge rule like this is not ideal, it would be better if date formatting worked the same on the server as it does on the client
Totally valid. I do think eventually we'll want JS, so I'm okay solving this for now. Mostly because I think I've come up with a solution I'm much happier with. Will post the PR in just a bit. |
See #87 for latest solution. Basically I think we should just replace the problem-character |
@colbywhite You might have insight on this ...
When enabling JS in
root.tsx
:... in
NextEventInfo.tsx
, the<time />
is different on the server vs client. Is this a simple "wrap it in auseEffect()
" fix and set a default for both server + client?Browser console error:
We don't currently have JavaScript enabled since it's all server rendered. But while I was testing integrating Sentry for error reporting, I noticed the error when forcing js to be enabled. (At some point we'll likely need js 🤷♂️)
The text was updated successfully, but these errors were encountered: