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

SSR generating an emtpy body on next.js #1265

Closed
gpessa opened this issue Jun 30, 2022 · 20 comments
Closed

SSR generating an emtpy body on next.js #1265

gpessa opened this issue Jun 30, 2022 · 20 comments

Comments

@gpessa
Copy link

gpessa commented Jun 30, 2022

Describe the bug
Using the lingui / next.js example seems that the page is not generated server side.
If I inspect the source code of a generated page the body is empty.
An example can be found here:
https://stackblitz.com/github/akellbl4/next.js/tree/examples/with-lingui-update/examples/with-lingui?file=pages%2F_app.js

To Reproduce

  1. Build the project
  2. Start it
  3. Inspect the source code

Expected behavior
I should have the generated HTML

@Barik85
Copy link

Barik85 commented Sep 5, 2022

Same issue

1 similar comment
@brucexu-eth
Copy link

Same issue

@semoal
Copy link
Contributor

semoal commented Nov 7, 2022

This is something we should improve asap, a @lingui/ssr package, that compiles the t`` macros on server side.

@thekip
Copy link
Collaborator

thekip commented Dec 13, 2022

There are no issue with lingui itself, the problem in the example code. It activates a language in useEffect hook which is called only in client-side code.

The example should be updated, no other changes needed.

@thekip
Copy link
Collaborator

thekip commented Dec 13, 2022

https://stackblitz.com/edit/github-jvqjsi?file=pages%2Findex.js,i18n%2FloadCatalog.js,pages%2F_app.js,pages%2Ftwo.js

Here is an updated example where SSR is working.

What I've changed:

  • I've added loadCatalog function which is called in getServerSideProps on each page. It can also be getStaticProps or other nextjs methods which called on the server and allow to load data before component render.

@thekip
Copy link
Collaborator

thekip commented Dec 13, 2022

BTW is still some work should be done to update example in this repo to avoid confusing people.

@gpessa
Copy link
Author

gpessa commented Dec 14, 2022

BTW is still some work should be done to update example in this repo to avoid confusing people.

is it really necessary to load the catalog on each page?
Is a bit annoying

@thekip
Copy link
Collaborator

thekip commented Dec 15, 2022

You need to call i18n activate with locale data in server code BEFORE component will start render. It's not required to be on the each page, but should be in the place where this call could be awaited.

Unfortunately, nextjs doesn't provide us with an obvious way how to do that. Each different method has advantages and disadvantages.

You may try to implement gitInitialProps on the custom app component or document.
You also may try to benefit from new nextjs app folder and put initialization in layout, but beware app folder doesn't support i18n out of the box as pages folder do.

@Martin005
Copy link
Contributor

@gpessa @Barik85 @brucexu-eth Could you please post what version of Next.js you used?

I used the lingui/next.js example, updated the React version to 18.2.0 and I was able to reproduce the bug only when I updated Next.js to version 13.0.7 (or any higher).

@thekip
Copy link
Collaborator

thekip commented Jan 8, 2023

@Martin005 that's very strange, it should not work on any version of react + nextjs. Because i18n.activate() call is happened inside a useEffect hook, but this hook is never called in SSR. According to lingui docs I18nProvider should not renders until activate would be called. That's why an empty body in SSR appears.

What is really needs is create another, working example in the repo, that users may start from it. Current example is outdated. It also would be great to create an example of usage with nextjs 13 app folder.

@shouze
Copy link

shouze commented Jan 19, 2023

https://stackblitz.com/edit/github-jvqjsi?file=pages%2Findex.js,i18n%2FloadCatalog.js,pages%2F_app.js,pages%2Ftwo.js

Here is an updated example where SSR is working.

What I've changed:

* I've added `loadCatalog` function which is called in `getServerSideProps` on each page. It can also be `getStaticProps` or other nextjs methods which called on the server and allow to load data before component render.

@thekip so you have a custom webpack config into next.js.config. Can we avoid it and only use something like const { messages } = await import('@lingui/loader!./messages/en.po'); instead?

Seems to work in nextjs app, but failing when running server side loading tests with jest, producing such an error:
Cannot find module '@lingui/loader!./messages/en.po' from 'src/translations/messagesLoader.ts'

Also, when using Next with SWC & lingui swc plugin, whenever catalog loading method I use (dynamic-ish import or webpack custom config), in Storybook I have such an error related to lingui/macro (triggered by lingui/loader):
Cannot find module 'fs'

And hen I add such webpackFinal configuration into Storybook, then I get an error about cannot find module os:

webpackFinal: async (config, { isServer }) => {
  if (!isServer) {
    config.resolve ||= {};
    config.resolve.fallback ||= {};
    config.resolve.fallback.fs = false;
  }

  config.module.rules.push({
    test: /\.po/,
    use: ["@lingui/loader"],
  });

  return config;
},

image

So far, if I follow the white rabbit 🐇 and update webpack lingui preset like that I still get such an error:

module.exports = {
  webpackFinal: async (config, { isServer }) => {
    if (!isServer) {
      config.resolve ||= {};
      config.resolve.fallback ||= {};
      config.resolve.fallback.fs = false;
      // see https://webpack.js.org/configuration/resolve/#resolvefallback
      config.resolve.fallback.os = require.resolve("os-browserify/browser");
    }

    config.module.rules.push({
      test: /\.po/,
      use: ["@lingui/loader"],
    });

    return config;
  },
};

image

node version: 16.19.0
storybook version: indifferently latest 6.x or 7.0 latest beta
nextjs version: 13.0.6
lingui swc plugin version: 0.2.0
lingui version:
webpack version: 5

In definitive, I'm kinda stuck because of storybook not behaving the same way witch webpack 5 depending I use babel or swc. Any idea on how to fix that?

@thekip
Copy link
Collaborator

thekip commented Jan 19, 2023

You reporting bunch of different issues here.
Jest will not work with '@lingui/loader!./messages/en.po' syntaxes because it's webpack specific. You should write a mock for them.

Issues from storybook pointing to the fact you don't get a babel macro plugin and storybook trying to bundle code which is not designed to be in runtime. You need to check sb configuration and make sure all required babel plugins provided.

@shouze
Copy link

shouze commented Jan 19, 2023

Jest will not work with '@lingui/loader!./messages/en.po' syntaxes because it's webpack specific. You should write a mock for them.

Thank you. I'm not familiar at all with this notation, could you point me to some ressource that explains how to mock it?

Issues from storybook pointing to the fact you don't get a babel macro plugin and storybook trying to bundle code which is not designed to be in runtime. You need to check sb configuration and make sure all required babel plugins provided.

Was exactly that, thanks! FTR, I had .storybook/babel.config.json with all necessary plugins (mainly macros here for lingui) AND... I delete root babel config to enable swc into next. I was believing that storybook would read .storybook/babel.config.json but in fact.. no. So I found out a solution by loading babel configuration directly through storybook main.js.

@thekip
Copy link
Collaborator

thekip commented Jan 19, 2023

I writing from the smartphone, so it's hard to provide you with a real code snippet. But as starting point you can read here https://stackoverflow.com/questions/46898638/importing-images-breaks-jest-test

You need to tell Jest to use some js mock instead of *.po files, similarly as images in the SO answer.

This mock could be as simple as

exports = {messages: {}}

Then lingui would render with default messages (usually english)

@gpessa
Copy link
Author

gpessa commented Jan 19, 2023

@shouze @shouze the issue you are talking about is unrelated to the main one. Would be nice if we maybe stay focussed and remove the messages :(

@shouze
Copy link

shouze commented Jan 19, 2023

@gpessa removing the message, not sure this is a good idea as anyway it's indexed and maybe useful for someone. But I'm ok to end this thread here 💯

@gpessa
Copy link
Author

gpessa commented Feb 6, 2023

Can we reopen this bug, is not solved and the example is still wrong @andrii-bodnar .

@thekip
Copy link
Collaborator

thekip commented Feb 7, 2023

@gpessa we have separate tasks for example. #1393

@gpessa
Copy link
Author

gpessa commented Feb 7, 2023

thank you!

@thekip
Copy link
Collaborator

thekip commented Mar 23, 2023

new examples were added #1550

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

No branches or pull requests

8 participants