배경

저는 웹사이트를 배포할때 gh-pages를 자주 사용해요. 그런데 gh-pages는 정적 웹사이트이기 때문에 url에 해당하는 경로에 index.html 파일이 없으면 404 에러가 나면서 페이지가 없다고 표시돼요.
그래서 페이지 라우팅이 필요한 경우 약간의 설정을 해줘야해요.

해결

이를 해결하기 위해서는 /public/404.html 파일을 추가하고 /index.html 파일에 스크립트를 추가해줘야해요.

출처: https://github.com/rafgraph/spa-github-pages/blob/gh-pages/404.html

아래 코드는 출처에서 가져온 404.html과 리다이렉팅 스크립트에요. 해당 스크립트를 추가한 후 배포하면 라우팅 이슈가 해결돼요~

해결 원리는 url 경로에 index.html 파일이 없으면 public/404.html 파일이 실행돼요. 404.html 파일에서는 현재 url을 파싱해서 searchParams에 담아서 /index.html 경로로 이동해요.
그러면 /index.html 에서는 해당 searchParams를 다시 파싱해서 state에 담은 후 처음 경로로 이동시켜요. 그러면 SPA이지만 gh-pages에서도 해당 페이지를 볼 수 있어요.

좋은 하루 되세요~ 😙

/public/404.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Single Page Apps for GitHub Pages</title>
    <script type="text/javascript">
      // Single Page Apps for GitHub Pages
      // MIT License
      // https://github.com/rafgraph/spa-github-pages
      // This script takes the current url and converts the path and query
      // string into just a query string, and then redirects the browser
      // to the new url with only a query string and hash fragment,
      // e.g. https://www.foo.tld/one/two?a=b&c=d#qwe, becomes
      // https://www.foo.tld/?/one/two&a=b~and~c=d#qwe
      // Note: this 404.html file must be at least 512 bytes for it to work
      // with Internet Explorer (it is currently > 512 bytes)

      // If you're creating a Project Pages site and NOT using a custom domain,
      // then set pathSegmentsToKeep to 1 (enterprise users may need to set it to > 1).
      // This way the code will only replace the route part of the path, and not
      // the real directory in which the app resides, for example:
      // https://username.github.io/repo-name/one/two?a=b&c=d#qwe becomes
      // https://username.github.io/repo-name/?/one/two&a=b~and~c=d#qwe
      // Otherwise, leave pathSegmentsToKeep as 0.
      console.log('404')
      var pathSegmentsToKeep = 1

      var l = window.location
      l.replace(
        l.protocol +
          '//' +
          l.hostname +
          (l.port ? ':' + l.port : '') +
          l.pathname
            .split('/')
            .slice(0, 1 + pathSegmentsToKeep)
            .join('/') +
          '/?/' +
          l.pathname
            .slice(1)
            .split('/')
            .slice(pathSegmentsToKeep)
            .join('/')
            .replace(/&/g, '~and~') +
          (l.search ? '&' + l.search.slice(1).replace(/&/g, '~and~') : '') +
          l.hash
      )
    </script>
  </head>
  <body></body>
</html>

/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My app</title>
    <link rel="stylesheet" href="/index.css" />
    <!-- Start Single Page Apps for GitHub Pages -->
    <script type="text/javascript">
      // Single Page Apps for GitHub Pages
      // MIT License
      // https://github.com/rafgraph/spa-github-pages
      // This script checks to see if a redirect is present in the query string,
      // converts it back into the correct url and adds it to the
      // browser's history using window.history.replaceState(...),
      // which won't cause the browser to attempt to load the new url.
      // When the single page app is loaded further down in this file,
      // the correct url will be waiting in the browser's history for
      // the single page app to route accordingly.
      ;(function (l) {
        if (l.search[1] === '/') {
          var decoded = l.search
            .slice(1)
            .split('&')
            .map(function (s) {
              return s.replace(/~and~/g, '&')
            })
            .join('?')
          window.history.replaceState(
            null,
            null,
            l.pathname.slice(0, -1) + decoded + l.hash
          )
        }
      })(window.location)
    </script>
    <!-- End Single Page Apps for GitHub Pages -->
  </head>

  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>
profile
프론트엔드 엔지니어로 일하고 있어요. 제품, 동료, 성장을 중요시해요. 겸손, 존중, 신뢰를 갖춘 동료가 되기 위해 노력해요. 😄

0개의 댓글