javascript - Dynamic routes not working when app is exported to static files - Stack Overflow

I have a site that is statically exported, and has dynamic routes.This site works fine in dev mode. Ho

I have a site that is statically exported, and has dynamic routes.

This site works fine in dev mode. However if I build & export it, and then serve the static files, it has an issue.

You can go to the site root and click on a link, which will take you to a dynamic post page like http://localhost:3000/post/1 and will work, but if you refresh the page (or visit directly) it 404s.

Why is this? Do dynamic routes, that need to access the router query object, not work when statically exported?

The dynamic route docs don't mention any caveats to dynamic routes when used with static export.

The code:

Taking the next.js static example to start with, I edited it’s pages/post/[id].tsx by removing the getStaticPaths and getStaticProps (as I don’t require build time static generation) and added clientside fetching on mount. I’m grabbing the router.query.id value and using it to fetch data:

⚡ Codesandbox here (which works fine as its running in dev, not exported served files)

import Head from 'next/head'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { GetPost } from '../../lib/postdata_api'
import { PostData } from '../../types/postdata'

const Post = () => {
  const [postData, setPostData] = useState<null | PostData>(null)
  const router = useRouter()
  const id = router.query.id as string
  const fetchData = async () => setPostData(await GetPost(id))

  useEffect(() => {
    if (!router.isReady) return
    fetchData()
  }, [router, router.isReady])

  if (!postData) return 'Loading...'

  return (
    <main>
      <Head>
        <title>{postData.title}</title>
      </Head>

      <h1>{postData.title}</h1>

      <p>{postData.body}</p>

      <Link href="/">
        <a>Go back to home</a>
      </Link>
    </main>
  )
}

export default Post

Expected Behavior

I expected it to behave the as it does it dev. Meaning a user can:

  • click a link on the root page
  • view the dynamic post page eg /post/1
  • refresh / directly visit this post (without it 404ing)

To Reproduce

  • Download the code sandbox or github repo
  • run npm run export && serve out
  • visit http://localhost:3000
  • click a link to a post
  • press refresh to see the 404

I have a site that is statically exported, and has dynamic routes.

This site works fine in dev mode. However if I build & export it, and then serve the static files, it has an issue.

You can go to the site root and click on a link, which will take you to a dynamic post page like http://localhost:3000/post/1 and will work, but if you refresh the page (or visit directly) it 404s.

Why is this? Do dynamic routes, that need to access the router query object, not work when statically exported?

The dynamic route docs don't mention any caveats to dynamic routes when used with static export.

The code:

Taking the next.js static example to start with, I edited it’s pages/post/[id].tsx by removing the getStaticPaths and getStaticProps (as I don’t require build time static generation) and added clientside fetching on mount. I’m grabbing the router.query.id value and using it to fetch data:

⚡ Codesandbox here (which works fine as its running in dev, not exported served files)

import Head from 'next/head'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { GetPost } from '../../lib/postdata_api'
import { PostData } from '../../types/postdata'

const Post = () => {
  const [postData, setPostData] = useState<null | PostData>(null)
  const router = useRouter()
  const id = router.query.id as string
  const fetchData = async () => setPostData(await GetPost(id))

  useEffect(() => {
    if (!router.isReady) return
    fetchData()
  }, [router, router.isReady])

  if (!postData) return 'Loading...'

  return (
    <main>
      <Head>
        <title>{postData.title}</title>
      </Head>

      <h1>{postData.title}</h1>

      <p>{postData.body}</p>

      <Link href="/">
        <a>Go back to home</a>
      </Link>
    </main>
  )
}

export default Post

Expected Behavior

I expected it to behave the as it does it dev. Meaning a user can:

  • click a link on the root page
  • view the dynamic post page eg /post/1
  • refresh / directly visit this post (without it 404ing)

To Reproduce

  • Download the code sandbox or github repo
  • run npm run export && serve out
  • visit http://localhost:3000
  • click a link to a post
  • press refresh to see the 404
Share Improve this question edited Aug 17, 2022 at 18:21 Ash asked Aug 17, 2022 at 16:20 AshAsh 2587 silver badges21 bronze badges 2
  • Could you plz try accessing the page with a trailing slash? – Irfanullah Jan Commented Aug 17, 2022 at 16:42
  • @IrfanullahJan Good idea! but sadly that didn't change anything. – Ash Commented Aug 17, 2022 at 18:23
Add a ment  | 

3 Answers 3

Reset to default 3

TL;DR

Add the following configuration to next.config.js and then make the export again:

// next.config.js
module.exports = {
    trailingSlash: true,
}

Explanation

It's possible to fix this behavior changing manually all routes produced by the export process to folders and renaming each *.html file to index.html, as follows:

Produced route by next export:

/posts/1.html

"Fixed" route:

/posts/1/index.html

So, if the page is refreshed when the browser has /posts/1 as url, the route will acquire a trailing slash and will bee /posts/1/, the HTTP petition will be done correctly because the HTTP server picks up the file index.html under any directory by default, and the static page will be shown.

Apparently, this behavior was the default prior Next.js v9 when export, and can be enabled again adding the following configuration to the file next.config.js (in order to avoid doing the change per route manually):

// next.config.js
module.exports = {
    trailingSlash: true,
}

I know it's a little late, but I found out this solution when I faced the same problem yesterday.

Source: official documentation

I see that you use 'serve' from Vercel. To have pretty URLs, you need to config rewrite for the server.

According to this instruction https://github./vercel/serve-handler#rewrites-array. You need to add this config to make it work with pretty URLs.

// public/serve.json
{
  "rewrites": [
    { "source": "/post/*", "destination": "/post/[id].html" }
  ]
}
// next.config.js
const nextConfig = {
  exportPathMap: () => {
   return {
     '/newpassword/index': { page: '/newpassword/[uuid]' }
   };
 },
}

run yarn build, then the return in out/ will be: newpassword/[uuid]/index.html to newpassword/index.html

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745110766a4611836.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信