새로 고치거나 수동으로 쓸 때 리액트 라우터 URL이 작동하지 않음

리액트 라우터를 사용하고 있는데 링크 버튼을 클릭해도 정상적으로 동작하지만 웹 페이지를 새로 고치면 원하는 내용이 로드되지 않습니다.

예를 들어, 저는localhost/joblist링크를 눌러서 도착했기 때문에 모든 것이 정상입니다.그러나 웹 페이지를 새로 고치면 다음과 같은 메시지가 나타납니다.

Cannot GET /joblist 

기본적으로는 이렇게 작동하지 않았습니다.처음에 제 URL은localhost/#/그리고.localhost/#/joblist완벽하게 잘 작동했어요근데 이런 URL이 마음에 안 들어서 지우려고 하는데#, 나는 다음과 같이 썼다.

Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler/>, document.body); }); 

이 문제는, 에서는 발생하지 않습니다.localhost/이건 항상 내가 원하는 걸 돌려줘.

이 앱은 한 페이지이기 때문에/joblist서버에는 아무것도 묻지 않아도 됩니다.

내 라우터 전체

var routes = (
<Route name="app" path="/" handler={App}>
<Route name="joblist" path="/joblist" handler={JobList}/>
<DefaultRoute handler={Dashboard}/>
<NotFoundRoute handler={NotFound}/>
</Route> );
Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler/>, document.body); }); 


질문에 대한 답변



서버측과 클라이언트측

여기서 가장 먼저 알 수 있는 것은 예전에는 URL이 1개였던 것이 지금은 2개라는 것입니다.과거에 삶이 단순할 때, 몇몇 사용자는 다음을 위한 요청을 보냈습니다.http://example.com/about는, URL 의 패스 부분을 검사하고, 유저가 About 페이지를 요구하고 있는 것을 판단하고, 그 페이지를 반송했습니다.

React Router가 제공하는 클라이언트 측 라우팅에서는 모든 것이 간단하지 않습니다.처음에 클라이언트는 아직 JavaScript 코드를 로드하지 않았습니다.따라서 첫 번째 요청은 항상 서버에 대한 것입니다.그러면 React 및 React 라우터 등을 로드하는 데 필요한 스크립트태그가 포함된 페이지가 반환됩니다.이러한 스크립트가 로드된 경우에만 단계2가 시작됩니다.단계 2에서 사용자가 ‘About us’ 탐색 링크를 클릭하면 URL은 로컬에서만 변경됩니다.http://example.com/about(History API에 의해 가능)하지만 서버에 대한 요청은 이루어지지 않습니다.대신 React Router는 클라이언트 측에서 작업을 수행하고 렌더링할 React 뷰를 결정하고 렌더링합니다.REST 호출을 필요가 없다고 가정하면 이미 완료되어 있습니다.서버 요청을 실행하지 않고 에서 정보 서비스로 전환했습니다.

따라서 기본적으로 링크를 클릭하면 페이지 새로 고침 없이 주소 표시줄의 URL을 조작하는 JavaScript가 실행되어 React Router가 클라이언트 측에서 페이지 전환을 수행합니다.

그러나 이제 주소 표시줄에 URL을 복사하여 붙여넣고 친구에게 이메일로 보내면 어떻게 되는지 생각해 보십시오.친구가 아직 웹 사이트를 로드하지 않았습니다.다시 말해, 그녀는 아직 1단계에 있다.시스템에서 아직 실행 중인 리액트 라우터가 없습니다.그래서 그녀의 브라우저는 서버 요청을 할 것이다.http://example.com/about.

그리고 여기서부터 문제가 시작되죠지금까지는 서버의 웹 루트에 정적 HTML을 배치하는 것만으로 문제를 해결할 수 있었습니다.그러나 서버에서 요청하면 다른 모든 URL에 대해 404개의 오류가 발생합니다.이러한 URL은 클라이언트 측에서는 정상적으로 동작합니다.Resact Router가 라우팅을 하기 때문입니다만, 서버에 인식시키지 않는 한 서버 측에서는 실패합니다.

서버측 라우팅과 클라이언트측 라우팅의 조합

필요한 경우http://example.com/about서버측과 클라이언트측 모두에서 동작하는 URL.서버측과 클라이언트측 모두에서, URL 의 루트를 설정할 필요가 있습니다.말이 되죠?

여기서부터 선택이 시작됩니다.해결책은 부트스트랩 HTML을 반환하는 catch-all 루트를 통해 문제를 완전히 우회하는 것부터 서버와 클라이언트가 모두 동일한 JavaScript 코드를 실행하는 풀온 동형 접근까지 다양합니다.

문제를 완전히 우회하는 방법:해시 이력

Hash History를 사용하면 브라우저 히스토리 대신 About 페이지의 URL은 다음과 같습니다.http://example.com/#/about

해시 뒤의 부분(#) 기호는 서버로 전송되지 않습니다.따라서 서버는 다음 명령어만 표시됩니다.http://example.com/인덱스 페이지를 올바르게 송신합니다.리액트 라우터에 의해#/about올바른 페이지를 표시합니다.

단점:

  • ugly URL
  • 이 방법에서는 서버 측 렌더링을 수행할 수 없습니다.검색 엔진 최적화(SEO)에 관한 한 웹 사이트는 거의 내용이 없는 단일 페이지로 구성됩니다.

캐치올

이 접근방식에서는 브라우저 기록을 사용하지만,가 송신하는 서버에 catch-all을 설정하기만 하면 됩니다./*로.index.html이는 해시 히스토리와 거의 동일한 상황을 제공합니다.단, 깨끗한 URL을 가지고 있기 때문에 나중에 사용자의 즐겨찾기를 모두 무효화하지 않고 이 방식을 개선할 수 있습니다.

단점:

  • 셋업이 복잡함
  • 아직 좋은 SEO는 없다.

하이브리드

하이브리드 방식에서는 특정 루트에 특정 스크립트를 추가하여 catch-all 시나리오를 확장합니다.간단한 PHP 스크립트를 만들어 콘텐츠가 포함된 사이트의 가장 중요한 페이지를 반환할 수 있으므로 Googlebot은 최소한 페이지에 있는 내용을 볼 수 있습니다.

단점:

  • 셋업이 더욱 복잡함
  • 특별한 취급을 하는 루트는 SEO만 유효합니다.
  • 서버 및 클라이언트의 콘텐츠를 렌더링하기 위한 코드 복제

동형

양쪽에서 동일한 JavaScript 코드를 실행할 수 있도록 Node.js를 서버로 사용하면 어떨까요?이제 모든 경로가 단일 리액트 라우터 구성으로 정의되어 렌더링 코드를 복제할 필요가 없습니다.말하자면 이것은 ‘성배’입니다.서버는 클라이언트에서 페이지 전환이 일어났을 때와 동일한 마크업을 송신합니다.이 솔루션은 SEO 측면에서 최적입니다.

단점:

  • 서버는 JavaScript를 실행할 수 있어야 합니다.Nashorn과 함께 Java를 실험해 봤지만 잘 되지 않습니다.실제로는 대부분 Node.js 기반 서버를 사용해야 합니다.
  • 많은 까다로운 환경 문제(사용 방법)window서버측 등)
  • 가파른 학습 곡선

어떤 걸로 할까요?

피할 수 있는 것을 고르세요.개인적으로 캐치올은 셋업하기에 충분히 간단하다고 생각하기 때문에 최소한으로 하겠습니다.이 설정을 사용하면 시간이 지남에 따라 상황을 개선할 수 있습니다.이미 서버 플랫폼으로 Node.js를 사용하고 있다면 동형 앱을 실행하는 것을 반드시 검토해 보겠습니다.네, 처음에는 어렵지만, 일단 요령을 터득하면 그 문제에 대한 매우 우아한 해결책입니다.

그러니까 기본적으로는 그게 결정적 요인이 되는 거죠.서버가 Node.js 상에서 동작하고 있는 경우는 동형이 됩니다.그렇지 않은 경우는 Catch-all 솔루션을 선택하고 시간이 경과하고 SEO의 요건에 따라 확장(하이브리드 솔루션)합니다.

React를 사용한 동형(‘범용’이라고도 함) 렌더링에 대해 자세히 알고 싶다면 해당 주제에 대한 몇 가지 유용한 튜토리얼이 있습니다.

또한, 시작을 위해 스타터 키트를 살펴보는 것이 좋습니다.테크놀로지 스택에 적합한 것을 선택합니다(Resact는 MVC의 V일 뿐이므로 완전한 앱을 구축하려면 더 많은 것이 필요합니다).Facebook 자체에서 발행한 것부터 살펴보자.

아니면 지역사회의 많은 것 중 하나를 고르세요.이 모든 것을 인덱스화하려고 하는 좋은 사이트가 있습니다.

처음에는 다음과 같이 했습니다.

현재 위의 2개의 스타터 키트에서 영감을 얻은 홈브루드 버전의 유니버설 렌더링을 사용하고 있습니다만, 현재는 구식입니다.

행운을 빌어요!




Apache를 웹 서버로 사용하고 있는 경우, 이 파일을 웹 서버에 삽입할 수 있습니다..htaccess파일:

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

사용하고 있다react: "^16.12.0"그리고.react-router: "^5.1.2"이 방법은 만능이며 시작하기 위한 가장 쉬운 방법입니다.




여기 있는 답변들은 모두 매우 도움이 됩니다. 팩 서버가 루트를 예상하도록 설정했습니다.

devServer: {
historyApiFallback: true,
contentBase: './',
hot: true }, 

historyApiFallback을 통해 이 문제를 해결할 수 있었습니다.이것으로 라우팅이 올바르게 동작해, 페이지를 갱신하거나 URL 를 직접 입력할 수 있습니다.Node.js 서버에서의 회피책은 걱정할 필요가 없습니다.이 답변은 웹 팩을 사용하는 경우에만 사용할 수 있습니다.

React-router 2.0 browserHistory에 대한 답변을 참조하십시오.이것이 필요한 이유에 대한 자세한 내용은 새로고침 시 이력이 작동하지 않습니다.




React Router V4 사용자의 경우:

다른 답변에서 언급된 해시 이력 기술로 이 문제를 해결하려고 할 경우 다음 점에 유의하십시오.

<Router history={hashHistory} > 

V4에서는 동작하지 않습니다.사용하세요HashRouter대신:

import { HashRouter } from 'react-router-dom'
<HashRouter>
<App/> </HashRouter> 

레퍼런스:해시 라우터




방금 Create React App을 사용하여 웹 사이트를 만들었는데, 여기에 같은 문제가 나와 있습니다.

사용하고 있다BrowserRouting에서react-router-dom패키지.Nginx 서버에서 실행하고 있으며 다음 항목을 추가합니다./etc/nginx/yourconfig.conf해결해주신 것 같아요.

location / {
if (!-e $request_filename){
rewrite ^(.*)$ /index.html break;
} } 

이는 다음 사항을 에 추가하는 것에 해당합니다..htaccessApache를 실행하고 있는 경우:

Options -MultiViews RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.html [QSA,L] 

이것은 Facebook이 제안하는 해결책이기도 하고, 여기에서 찾을 수 있습니다.