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

generateStaticParams breaks build when i18n is defined in next.config.js #55331

Open
1 task done
nickderobertis-ch opened this issue Sep 13, 2023 · 7 comments
Open
1 task done
Labels
bug Issue was opened via the bug report template. Navigation Related to Next.js linking (e.g., <Link>) and navigation.

Comments

@nickderobertis-ch
Copy link

Link to the code that reproduces this issue or a replay of the bug

https://github.com/nickderobertis-ch/app-ssg-i18n-issue

To Reproduce

  1. Run next build, observe error.

Current vs. Expected behavior

I expected the build to complete successfully with statically generated pages for each of the values returned in generateStaticParams.

Instead, the build fails with the following output:

$ next build
- info Creating an optimized production build  
- info Compiled successfully
- info Linting and checking validity of types  
- info Collecting page data  
[    ] - info Generating static pages (0/10)
Error occurred prerendering page "/en". Read more: https://nextjs.org/docs/messages/prerender-error
Error: The provided export path '/' doesn't match the '/[lang]/page' page.
Read more: https://nextjs.org/docs/messages/export-path-mismatch
    at /Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/export/worker.js:156:27
    at Span.traceAsyncFn (/Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/trace/trace.js:103:26)
    at Object.exportPage (/Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/export/worker.js:96:27)
    at execFunction (/Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/compiled/jest-worker/processChild.js:1:2828)
    at execHelper (/Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/compiled/jest-worker/processChild.js:1:2486)
    at execMethod (/Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/compiled/jest-worker/processChild.js:1:2574)
    at process.messageListener (/Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/compiled/jest-worker/processChild.js:1:1284)
    at process.emit (node:events:513:28)
    at emit (node:internal/child_process:937:14)
    at process.processTicksAndRejections (node:internal/process/task_queues:83:21)

Error occurred prerendering page "/es". Read more: https://nextjs.org/docs/messages/prerender-error
Error: The provided export path '/' doesn't match the '/[lang]/page' page.
Read more: https://nextjs.org/docs/messages/export-path-mismatch
    at /Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/export/worker.js:156:27
    at Span.traceAsyncFn (/Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/trace/trace.js:103:26)
    at Object.exportPage (/Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/export/worker.js:96:27)
    at execFunction (/Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/compiled/jest-worker/processChild.js:1:2828)
    at execHelper (/Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/compiled/jest-worker/processChild.js:1:2486)
    at execMethod (/Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/compiled/jest-worker/processChild.js:1:2574)
    at process.messageListener (/Users/nderobertis/repos/app-ssg-i18n-issue/node_modules/next/dist/compiled/jest-worker/processChild.js:1:1284)
    at process.emit (node:events:513:28)
    at emit (node:internal/child_process:937:14)
    at process.processTicksAndRejections (node:internal/process/task_queues:83:21)
- info Generating static pages (10/10)

> Export encountered errors on following paths:
        /[lang]/page: /en
        /[lang]/page: /es
error Command failed with exit code 1.

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 22.5.0: Thu Jun  8 22:22:20 PDT 2023; root:xnu-8796.121.3~7/RELEASE_ARM64_T6000
    Binaries:
      Node: 18.7.0
      npm: 8.15.0
      Yarn: 1.22.19
      pnpm: N/A
    Relevant Packages:
      next: 13.4.20-canary.26
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 5.2.2
    Next.js Config:
      output: N/A

Which area(s) are affected? (Select all that apply)

App Router, Routing (next/router, next/navigation, next/link)

Additional context

I tested my reproduction against different NextJS versions, from 13.0.0 to latest canary 13.4.20-canary.26 (had to remove metadata and make generateStaticParams async to go back all the way, that reproduction is on this branch). It seems this bug has existed since the app directory was introduced.

This is somewhat related to #53724, at least in that both bugs seem to be related to dynamic routes when i18n is defined in next.config.js. But while that bug was introduced in 13.4.13 and so we can downgrade to avoid it, there is no way to downgrade to avoid this bug.

In our case we have an existing NextJS app on the pages directory using i18n and we want to incrementally migrate to the app directory and SSG the language pages. This blocks our migration, as we still need to use the i18n config for the pages directory.

@nickderobertis-ch nickderobertis-ch added the bug Issue was opened via the bug report template. label Sep 13, 2023
@github-actions github-actions bot added the Navigation Related to Next.js linking (e.g., <Link>) and navigation. label Sep 13, 2023
@moonman239
Copy link

I suspect your function was written incorrectly.

It should look more like this:

export function generateStaticParams() {
  const paths = ["en", "es"].map((lang) => {params: { slug: lang }});
return {paths: paths, fallback: false}
}

@moonman239
Copy link

See:
#16881

@nickderobertis-ch
Copy link
Author

Hey thanks for your response @moonman239, but I think you are confusing getStaticPaths from the pages directory with generateStaticParams from the app directory. If you look at those two docs, you'll see the response you're describing is the structure for getStaticPaths and not generateStaticParams.

Anyway, just to be sure I tried your suggestion. There is actually a syntax error: the right hand side of the arrow function needs to be wrapped in parentheses to return an object rather than interpret that as a function body. So the final code I tried was:

export function generateStaticParams() {
  const paths = ["en", "es"].map((lang) => ({
    params: {
      slug: lang,
    },
  }));
  return { paths: paths, fallback: false };
}

Which then fails to compile with:

Type error: Page "app/[lang]/page.tsx" has an invalid export:
  "{ paths: { params: { slug: string; }; }[]; fallback: boolean; }" is not a valid generateStaticParams return type:
    Expected "any[] | Promise<any[]>", got "{ paths: { params: { slug: string; }; }[]; fallback: boolean; }".

As you can see from the error, it expects an array as the response, not an object.

So I do think this is a real bug and not a usage error, but let me know if you have other suggestions.

@nickderobertis-ch
Copy link
Author

Also the SSG works fine when I comment out the i18n section in next.config.js.

@ewah
Copy link

ewah commented Sep 14, 2023

i18n and /app directory are no longer compatible

i had to make a middleware.ts that detects accept lang header to forward them the to the right /[lang]/... directory
and then make my own next/link proxy that rewrites hrefs so users will navigate properly

@nickderobertis-ch
Copy link
Author

Thank you for the suggestion, yes I am aware that the i18n is not intended to be supported in app directory. That's fine, it's that using it at all breaks the build.

In our case we have an existing app on pages directory using i18n, and we want to incrementally migrate to app directory. This is not possible due to this bug without removing i18n and re-implementing it ourselves with middleware, context, etc. That is the approach I'm headed down now, but it's quite complex to get all the pieces working in both directories.

Ultimately I have found that I need different routing behavior for app versus pages in the middleware, and I have not been able to find a good way to detect which directory the page is served from. Currently I have a proof of concept working by having a hard-coded list of routes that are in the app directory, but it will be easy for that to get out of sync.

@prkagrawal

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template. Navigation Related to Next.js linking (e.g., <Link>) and navigation.
Projects
None yet
Development

No branches or pull requests

4 participants