Using getStaticPaths in combination with trailingSlash: true leads to invalid json prefetching. For a link to a dynamic route, the json file that is prefetched includes an invalid slash in the path, causing a 404 to be returned. However, when clicking the link and landing on the dynamic page the correct json file is fetched.
// next.config.js
module.exports = {
trailingSlash: true,
};
// pages/[name].js
export default function Hello({ name }) {
return <div>Hello {name}</div>
}
export function getStaticProps(context) {
return {
props: {
name: context.params.name
}
};
}
export function getStaticPaths() {
return {
paths: [
{ params: { name: 'world' } }
],
fallback: false
};
}
// pages/index.js
import Link from 'next/link'
export default function Home() {
return (
<div>
<Link as="/world" href="/[name]">
<a>Hello world</a>
</Link>
</div>
)
}
next build && next exporthttps://example.com/_next/data/some-hash/world/.json returning a 404The correct https://example.com/_next/data/some-hash/world.json is (pre)fetched
I've had a little look at this (it's also breaking the prefetching in the app I'm currently working on), I have pushed a little demo app here to reproduce the issue.
That app is now versioned to 9.5.4-canary.4, the earliest version where I see it happening, 9.5.3-canary.3 or earlier it seems fine, so I'm guessing it's related to this commit 489cad36bcc95f93ce012712369a83809e91956d that was introduced between those two versions.
Adding a little debugging, before this commit, the function _resolveHref was returning
{
href: "/[name]/"
pathname: "/[name]"
...
}
but after it returns:
{
href: "/[name]/"
pathname: "/[name]/"
}
and further along gets translated to '/world/' and then has the extension appended to it, creating '/world/.json'.
Just as a test, I've tried sanitising the URL just before calling prefetchData, it seems to resolve this issue, but not so confident it doesn't introduce others
git diff
diff --git a/packages/next/next-server/lib/router/router.ts b/packages/next/next-server/lib/router/router.ts
index 85921f4d6..268b86920 100644
--- a/packages/next/next-server/lib/router/router.ts
+++ b/packages/next/next-server/lib/router/router.ts
@@ -1146,6 +1146,8 @@ export default class Router implements BaseRouter {
}
const route = removePathTrailingSlash(pathname)
+ url = removePathTrailingSlash(url)
+
await Promise.all([
this.pageLoader.prefetchData(
url,
I have exactly the same issue, any updates?
Following on this. It is a really serious issue for our project, as not being able to fetch the pages .json breaks prefetching of links, causing the entire app to re-render when you click on a link and subsequent loss of data in React contexts.
As a temporary workaround, maybe just turn it off with prefetch={false} on the affected Links.
What worked for me is disabling prefetch in my Links and prefetching with router.prefetch in a Hook instead:
function LinkWrapper({ slug, text }) {
const router = useRouter();
useEffect(() => {
router.prefetch(`/posts/${encodeURIComponent(slug)}`);
}, []);
return (
<Link href={`/posts/${encodeURIComponent(slug)}/`} prefetch={false}>
<a>{text}</a>
</Link>
);
}
+1 I am also running into issues with this.
Most helpful comment
I have exactly the same issue, any updates?