vercel / next.js

The React Framework
https://nextjs.org
MIT License
125.63k stars 26.82k forks source link

app\[lang] breaks next/link with prefetch: false. Loading.tsx doesn't works with ISR #49799

Open Marsony opened 1 year ago

Marsony commented 1 year ago

Verify canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: x64
    Binaries:
      Node: 18.15.0
      npm: 9.5.0
      Yarn: 3.5.4
      pnpm: 7.24.3
    Relevant packages:
      next: 13.4.3-canary.0
      eslint-config-next: 13.2.5-canary.4
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 5.0.4

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true), Internationalization (i18n), Routing (next/router, next/navigation, next/link)

Link to the code that reproduces this issue

https://github.com/vercel/next.js/tree/canary/examples/app-dir-i18n-routing

To Reproduce

1) use template from repro link, then create app\[lang]\publication\[...slugs]\page.tsx

Page.tsx

export const revalidate = 60;
export const dynamicParams = true;

export async function generateStaticParams() {
  return [];
}
export default async function Page() {
  return (
    <div>
      <h1>control</h1>
    </div>
  )
}

then in app\[lang]\page.tsx just use next/link with prefetch: false and href: "/en/publication/car/in/berlin". after click on the link you will see window.reload (like php way).

2) create app\[lang]\publication\[...slugs]\loading.tsx it doesn't works with ISR and prefetch: false

Describe the Bug

Navigation breaks when wrapping app in [dynamicParam]

Expected Behavior

nextjs navigation, but now like php

Which browser are you using? (if relevant)

chrome

How are you deploying your application? (if relevant)

localhost

holicreact commented 1 year ago

I'm having the same problem. Occasionally, app navigation fails and multiple requests are attempted

astateful commented 1 year ago

Create a root layout.js file that simply returns the children, like so:

export default function RootLayout({ children }) { return children; }

Marsony commented 1 year ago

I think wrapping the app in a [lang] breaks Conditions for Soft Navigation (that conditions described here). So, application navigation switching from soft to the hard mode.

Is it possible to do something with this? We got hard transitions between all of the routes with prefetch: false (if the app wrapped in [lang]).

If we understood correctly, wrapping app in [locale] is the single way to make an i18n routing. But that strategy disable soft navigation with links which have prefetch: false.

OmgDef commented 1 year ago

Having the same issue. I use wrapping app in dynamicParam to show different content based on client's region. After enabling ISR and disabling prefetch, loading.tsx does not render anymore.

Marsony commented 1 year ago

Having the same issue. I use wrapping app in dynamicParam to show different content based on client's region. After enabling ISR and disabling prefetch, loading.tsx does not render anymore.

And you also have a hard navigation? In this case

zartinn commented 1 year ago

Having the same issue. I use wrapping app in dynamicParam to show different content based on client's region. After enabling ISR and disabling prefetch, loading.tsx does not render anymore.

Do you use generateStaticParams in your dynamic pages?

I commented something about loading UI here: https://github.com/vercel/next.js/issues/45317#issuecomment-1555870967

Marsony commented 1 year ago

Having the same issue. I use wrapping app in dynamicParam to show different content based on client's region. After enabling ISR and disabling prefetch, loading.tsx does not render anymore.

Do you use generateStaticParams in your dynamic pages?

I commented something about loading UI here: #45317 (comment)

Sure

export function generateStaticParams() {
  return ['en', 'en-DE', 'en-AT'].map((locale) => ({ lang: locale }));
}
zartinn commented 1 year ago

I am not sure how your example works out with your params that you set with revalidate and dynamicParams But without these parameters you'll have static pages that are created on build time and therefore you'll not see the loading UI.

Marsony commented 1 year ago

I am not sure how your example works out with your params that you set with revalidate and dynamicParams But without these parameters you'll have static pages that are created on build time and therefore you'll not see the loading UI.

app\\[lang]\\layout.tsx

export function generateStaticParams() {
  return ['en', 'en-DE', 'en-AT'].map((locale) => ({ lang: locale }));
}

app\\[lang]\\publication\\[...slugs]\\page.tsx <- thats fallback: 'blocking', I dont create this pages at build time, I creating them on demand

export const revalidate = 60;
export const dynamicParams = true;

export async function generateStaticParams() {
  return [];
}

While nextjs generating fallback: 'blocking' aka on demand page, I think will be good to see Loading.tsx. But it's not a biggest nuance I think. Wrap your app in [lang], then disable prefetch for all of the next/link and you will see php-like application.

lightrow commented 11 months ago

this affects the latest next 14 and app router as well. Disabliing prefetch on <Link>s while the app is wrapped with [lang] makes every <Link> act as a dumb <a>, forcing full page reload on every navigation