Skip to content
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

Dynamic content in locale file is loaded in SSR then reloaded on the client during hydration #663

Closed
Soviut opened this issue Apr 12, 2020 · 10 comments · Fixed by #823
Closed
Assignees

Comments

@Soviut
Copy link

Soviut commented Apr 12, 2020

Version

v6.8.1

Reproduction link

https://none

Steps to reproduce

  • Enable lazy: true in nuxt.config.js.
  • Create an /locales/en.js
  • In the en.js file, add a message: Math.random() translation
  • In a template, display {{ $t('message') }}
  • Reload the browser
  • Observe the page loads with the translations already applied in SSR, showing a random number
  • Observe that a few moments later, hydration happens and the random number is replaced with a new number

What is expected ?

Only the SSR version of the translations would be applied and hydration would not actually update the translations.

What is actually happening?

Hydration is updating the translations, changing the content from what SSR generates.

Additional comments?

The reason this came up is we're using a lorem ipsum module to quickly mock up fake content in our translations. Having the content change suddenly after first load is jarring.

This bug report is available on Nuxt community (#c436)
@rchl
Copy link
Collaborator

rchl commented Apr 13, 2020

It sounds like a good idea and might be a good base for fixing some other issues.

There is something that makes it non-trivial though - language files can export function in which case we have to pass context object to them and we can't do that if we are gonna process those when Nuxt module's code runs (which we would have to do to fix this).

We could potentially treat those two cases differently but not sure...

Are you exporting plain object or function from your language files?

@Soviut
Copy link
Author

Soviut commented Apr 13, 2020

I am exporting a plain object but I populate some of it using function calls. For example

      description: lorem.generateSentences(2),

The issue is/was that the lorem-ipsum module generates new random text each time it is called. My work around was to write a custom randomization function and pass that to the lorem object when it's constructed so the text is always generated on the same seed.

But this just solves the visual problem of the text changing, it doesn't alter the fact that the hydration step still re-runs the translation file. I could see more elaborate translation setups being rather costly to re-run.

@rchl
Copy link
Collaborator

rchl commented Apr 13, 2020

The fix would work for that (object) case, but for functions, we would need to handle them as we do now - processing them separately for client/server.

I think I'm fine with that. Just might be difficult to explain that difference in the docs for people to understand it really.

@rchl rchl self-assigned this Apr 13, 2020
@Soviut
Copy link
Author

Soviut commented Apr 13, 2020

Couldn't a flag in the store be set indicating that the function had already been called server-side and not to call it again client-side?

@rchl
Copy link
Collaborator

rchl commented Apr 13, 2020

Current functionality passes Nuxt context and that one is different for server and client. We can't really make any assumptions on how people are using that functionality so running it only once (on the server) would potentially break someone's use case (unlikely but still possible).

Also, your suggestion to have a store state for that:
a) doesn't solve the issue above
b) is not gonna work when store is disabled and this module doesn't rely on store for core functionality

@xfyre

This comment has been minimized.

@rchl

This comment has been minimized.

@xfyre

This comment has been minimized.

rchl added a commit that referenced this issue Aug 3, 2020
Instead of client importing and processing messages (translations)
itself on load pass already loaded messages from the server through
nuxtState. This will in most cases allow avoiding triggering an extra
network request to fetch lang file for given locale.

Slight behavior change: The client will no longer import the lang file
itself for the initially used locale. That means that if the lang file
has exported a function, it will only be called on the server and not
the client. This matches behavior of "asyncData" and I think it makes
more sense in general.

Resolves #486
Resolves #663
@rchl
Copy link
Collaborator

rchl commented Aug 3, 2020

With #823 we'll load translations on the server and pass that to the client so extra network requests (combined with #820) will be completely avoided.

Contrary to what I've said before, this will also work for lang files that export a function. I've decided to change behavior of those a bit so that if those were processed on the server, we'll not process them again on the client. That matches asyncData so I think it makes sense.

@rchl rchl closed this as completed in #823 Aug 3, 2020
rchl added a commit that referenced this issue Aug 3, 2020
Instead of client importing and processing messages (translations)
itself on load, pass already loaded messages from the server through
"nuxtState". This will in most cases allow avoiding triggering an extra
network request to fetch lang file for the given locale.

Slight behavior change: The client will no longer import the lang file
itself for the initially used locale. That means that if the lang file
has exported a function, it will only be called on the server and not on
the client. This matches behavior of "asyncData" and I think it makes
more sense in general.

Resolves #486
Resolves #663
@rchl
Copy link
Collaborator

rchl commented Aug 4, 2020

Released in v6.13.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants