vuejs / vitepress

Vite & Vue powered static site generator.
https://vitepress.dev
MIT License
12.46k stars 2.03k forks source link

Redirection for `/index` leads to empty page #4058

Open swaldmann opened 1 month ago

swaldmann commented 1 month ago

Describe the bug

Accessing a page via suffixing /index redirects you to the correct page, but no content is displayed. This can be reproduced on vitepress.dev, too: https://vitepress.dev/guide/getting-started/index. A reload afterwards fixes the problem.

In our project we noticed by chance when one of our contributors put an /index suffix on a relative link. Our broken link checker noticed because the request still returns a 404 status code. It's a minor issue but could be handled nicer.

Caveat: this does not seem reproducible during local development.

Reproduction

Open https://vitepress.dev/guide/getting-started/index.

Expected behavior

Either page content is rendered correctly or a 404 is shown.

System Info

System:
  OS: macOS 14.5
  CPU: (12) arm64 Apple M2 Pro
  Memory: 2.68 GB / 32.00 GB
  Shell: 5.9 - /bin/zsh
Binaries:
  Node: 20.13.1 - /usr/local/bin/node
  npm: 10.5.2 - /usr/local/bin/npm
  pnpm: 8.15.6 - ~/Library/pnpm/pnpm
Browsers:
  Chrome: 126.0.6478.128
  Safari: 17.5

Additional context

No response

Validations

bugwelle commented 1 month ago

The issue is that the user is redirected to the correct page (without /index suffix), but the page is only partially if at all rendered. Reloading works, because we're now on the correct page. 😃

yushanfans2233 commented 1 month ago

When you access https://vitepress.dev/guide/getting-started/index, the server response is 404 and the content is

<!DOCTYPE html>
<html lang="en-US" dir="ltr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>404 | VitePress</title>
    <meta name="description" content="Not Found">
    <meta name="generator" content="VitePress v1.3.1">
    <link rel="preload stylesheet" href="/assets/style.DI9EelPt.css" as="style">
    <script type="module" src="/assets/chunks/metadata.34e32cf1.js"></script>
    <script type="module" src="/assets/app.DbyyJ-Ea.js"></script>
    <link rel="preload" href="/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
    <link rel="icon" type="image/svg+xml" href="/vitepress-logo-mini.svg">
    <link rel="icon" type="image/png" href="/vitepress-logo-mini.png">
    <meta name="theme-color" content="#5f67ee">
    <meta property="og:type" content="website">
    <meta property="og:locale" content="en">
    <meta property="og:title" content="VitePress | Vite &amp; Vue Powered Static Site Generator">
    <meta property="og:site_name" content="VitePress">
    <meta property="og:image" content="https://vitepress.dev/vitepress-og.jpg">
    <meta property="og:url" content="https://vitepress.dev/">
    <script src="https://cdn.usefathom.com/script.js" data-site="AZBRSFGG" data-spa="auto" defer></script>
    <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
    <script id="check-mac-os">document.documentElement.classList.toggle("mac",/Mac|iPhone|iPod|iPad/i.test(navigator.platform));</script>
  </head>
  <body>
    <div id="app"></div>

  </body>
</html>

It hands over the responsibility of render 404 page to the client. But the client will normalize the url from https://vitepress.dev/guide/getting-started/index to https://vitepress.dev/guide/getting-started/, it is a valid path, so the client won't do anything, then we get an empty page. https://github.com/vuejs/vitepress/blob/cccc231f2106b41c6c3298917e222ba34e015f46/src/client/app/router.ts#L327C3-L327C69

When you refresh the page, the brower will send a GET request to https://vitepress.dev/guide/getting-started, this is a valid request, so the server renders the content.