HTML5 히스토리 모드

vue-router의 기본 모드는 hash mode 입니다. URL 해시를 사용하여 전체 URL을 시뮬레이트하므로 URL이 변경될 때 페이지가 다시 로드 되지 않습니다.

해시를 제거하기 위해 라우터의 history 모드 를 사용할 수 있습니다. history.pushState API를 활용하여 페이지를 다시 로드하지 않고도 URL 탐색을 할 수 있습니다.

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

히스토리 모드를 사용하면 URL이 "정상"으로 보입니다. http://oursite.com/user/id. 멋집니다!

그러나 문제는 다음과 같습니다. 우리의 앱이 적절한 서버 설정이 없는 단일 페이지 클라이언트 앱이기 때문에 사용자가 직접 http://oursite.com/user/id 에 접속하면 404 오류가 발생합니다.

걱정하지 않아도됩니다. 문제를 해결하려면 서버에 간단하게 포괄적인 대체 경로를 추가하기만 하면됩니다. URL이 정적 에셋과 일치하지 않으면 앱이 있는 동일한 index.html페이지를 제공해야 합니다.

서버 설정 예제

Apache

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

nginx

location / {
  try_files $uri $uri/ /index.html;
}

Native Node.js

const http = require("http")
const fs = require("fs")
const httpPort = 80

http.createServer((req, res) => {
  fs.readFile("index.htm", "utf-8", (err, content) => {
    if (err) {
      console.log('We cannot open "index.htm" file.')
    }

    res.writeHead(200, {
      "Content-Type": "text/html; charset=utf-8"
    })

    res.end(content)
  })
}).listen(httpPort, () => {
  console.log("Server listening on: http://localhost:%s", httpPort)
})

Express와 Node.js

Node.js/Express의 경우 connect-history-api-fallback 미들웨어를 고려해보세요.

Internet Information Services (IIS)

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 <system.webServer>
   <rewrite>
     <rules>
       <rule name="Handle History Mode and custom 404/500" stopProcessing="true">
         <match url="(.*)" />
         <conditions logicalGrouping="MatchAll">
           <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
           <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
         </conditions>
         <action type="Rewrite" url="index.html" />
       </rule>
     </rules>
   </rewrite>
     <httpErrors>     
         <remove statusCode="404" subStatusCode="-1" />                
         <remove statusCode="500" subStatusCode="-1" />
         <error statusCode="404" path="/survey/notfound" responseMode="ExecuteURL" />                
         <error statusCode="500" path="/survey/error" responseMode="ExecuteURL" />
     </httpErrors>
     <modules runAllManagedModulesForAllRequests="true"/>
 </system.webServer>
</configuration>

주의 사항

주의 사항이 있습니다. 여러분의 서버는 404 에러를 보고하지 않을 것입니다. 왜냐하면 모든 발견되지 않은 경로가 이제 index.html 파일을 제공하기 때문입니다. 이 문제를 해결하려면 Vue 앱에서 catch-all 라우트를 구현하여 404 페이지를 표시해야합니다.

const router = new VueRouter({
  mode: 'history',
  routes: [
    { path: '*', component: NotFoundComponent }
  ]
})

또는 Node.js 서버를 사용하는 경우 서버 측의 라우터를 사용하여 들어오는 URL을 일치시키고 라우트가 일치하지 않으면 404로 응답하여 폴백을 구현할 수 있습니다. 더 자세한 설명은 Vue 서버사이드 렌더링 문서을 읽어보세요