[javascript] 수동으로 새로 고치거나 쓸 때 반응 라우터 URL이 작동하지 않습니다

React-router를 사용하고 있으며 링크 버튼을 클릭하는 동안 제대로 작동하지만 웹 페이지를 새로 고칠 때 원하는 것을로드하지 않습니다.

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

Cannot GET /joblist

기본적으로 이와 같이 작동하지 않았습니다. 처음에 나는 같은 내 URL을했다 localhost/#/그리고 localhost/#/joblist그들은 완벽하게 정상적으로 작동했다. 그러나 나는 이런 종류의 URL을 좋아하지 않기 때문에 그것을 지우려고 노력했다 #.

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

이 문제는에서 발생하지 않으며 localhost/항상 원하는 것을 반환합니다.

편집 : 이 응용 프로그램은 단일 페이지이므로 /joblist서버에 아무것도 요구하지 않습니다.

EDIT2 : 내 전체 라우터.

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);
});



답변

허용되는 답변에 대한 의견과이 질문의 일반적인 특성 ( ‘작동하지 않음’)을 살펴보면 여기에 관련된 문제에 대한 일반적인 설명을하기에 좋은 장소라고 생각했습니다. 따라서이 답변은 OP의 특정 사용 사례에 대한 배경 정보 / 정교화로 의도되었습니다. 저를 참아주세요.

서버 측과 클라이언트 측

이것에 대해 가장 먼저 이해해야 할 것은 이제 URL이 해석되는 곳이 2 곳이고 ‘이전 날’에는 1 곳만 존재했다는 것입니다. 과거에는 수명이 단순했을 때 일부 사용자 http://example.com/about가 서버에 요청을 보냈는데 , URL의 경로 부분을 검사하여 사용자가 정보 페이지를 요청한 후 해당 페이지를 다시 보냈습니다.

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

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

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

그리고 이것이 당신의 문제가 시작되는 곳입니다. 지금까지는 서버의 웹 루트에 정적 HTML을 배치하는 것만으로도 벗어날 수 있습니다. 그러나 서버에서 요청하면404 다른 모든 URL에 오류가 발생 합니다 . React Router가 라우팅을 수행하기 때문에 동일한 URL 이 클라이언트 측 에서 잘 작동 하지만 서버 에서 URL을 이해하지 않으면 서버 측에서 실패 합니다.

서버 및 클라이언트 측 라우팅 결합

http://example.com/aboutURL이 서버 측과 클라이언트 측 모두에서 작동하게하려면 서버 측과 클라이언트 측 모두 에서 URL에 대한 경로를 설정해야합니다. 말이 되나요?

그리고 이것은 당신의 선택이 시작되는 곳입니다. 솔루션은 부트 스트랩 HTML을 반환하는 모든 경로를 통해 문제를 우회하는 것부터 서버와 클라이언트가 동일한 JS 코드를 실행하는 완전 동형 접근 방식까지 다양합니다.

.

문제를 모두 우회 : 해시 기록

함께 해시 역사 대신에 브라우저 역사 , 이런 걸 보이는 것에 대한 페이지에 대한 URL :
http://example.com/#/about
해시 (후 일부 #) 기호를 서버에 전송되지 않습니다. 따라서 서버는 http://example.com/예상대로 색인 페이지 만보 고 보냅니다. React-Router가 #/about부품 을 픽업 하고 올바른 페이지를 표시합니다.

단점 :

  • ‘못생긴’URL
  • 이 방법으로는 서버 측 렌더링이 불가능합니다. 검색 엔진 최적화 (SEO)에 관한 한 귀하의 웹 사이트는 내용이 거의없는 단일 페이지로 구성됩니다.

.

포괄

이 방법을 사용하면 사용 브라우저 기록을 할 수 있지만, 단지 포괄 전송 서버의 설정 /*에를 index.html효과적으로 당신에게 해시 역사와 많은 같은 상황을 제공합니다. 그러나 깨끗한 URL이 있으며 나중에 모든 사용자의 즐겨 찾기를 무효화하지 않고도이 체계를 개선 할 수 있습니다.

단점 :

  • 더 복잡한 설정
  • 여전히 좋은 SEO

.

잡종

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

단점 :

  • 훨씬 더 복잡한 설정
  • 당신이 특별한 대우를 제공하는 노선에 대해서만 좋은 SEO
  • 서버 및 클라이언트에서 컨텐츠를 렌더링하기위한 코드 복제

.

동형

Node JS를 서버로 사용 하여 양쪽 에서 동일한 JS 코드를 실행할 수 있다면 어떨까요? 이제 모든 라우트를 단일 반응 라우터 구성에 정의했으며 렌더링 코드를 복제 할 필요가 없습니다. 이것은 말하자면 ‘성배’입니다. 서버는 클라이언트에서 페이지 전환이 발생한 경우와 똑같은 마크 업을 보냅니다. 이 솔루션은 SEO 측면에서 최적입니다.

단점 :

  • 서버 는 반드시 JS를 실행할 수 있어야합니다 . Java icw Nashorn을 실험했지만 작동하지 않습니다. 실제로 이는 대부분 노드 JS 기반 서버를 사용해야 함을 의미합니다.
  • 많은 까다로운 환경 문제 ( window서버 측 등에서 사용)
  • 가파른 학습 곡선

.

어느 것을 사용해야합니까?

멀리 갈 수있는 것을 선택하십시오. 개인적으로 포괄은 설정하기에 충분히 간단하다고 생각합니다. 이 설정을 통해 시간이 지남에 따라 개선 할 수 있습니다. Node JS를 서버 플랫폼으로 이미 사용하고 있다면 동형 응용 프로그램을 수행하는 것이 확실합니다. 예, 처음에는 힘들지만 일단 중단되면 실제로는 문제에 대한 매우 우아한 해결책입니다.

기본적으로 저에게는 이것이 결정적인 요소입니다. 내 서버가 노드 JS에서 실행되면 동형이됩니다. 그렇지 않으면 Catch-all 솔루션을 선택하고 시간이 지남에 따라 SEO 요구 사항에 따라 솔루션을 확장합니다 (하이브리드 솔루션).

React를 사용하여 동형 ( ‘유니버설’이라고도 함) 렌더링에 대해 더 배우려면이 주제에 대한 유용한 자습서가 있습니다.

또한 시작을 위해 스타터 키트를 살펴 보는 것이 좋습니다. 기술 스택에 대한 선택과 일치하는 것을 선택하십시오 (React는 MVC의 V 일 뿐이므로 전체 앱을 빌드하려면 더 많은 것이 필요함을 기억하십시오). Facebook 자체에서 출판 한 것을 살펴보십시오.

또는 지역 사회에서 많은 사람 중 하나를 선택하십시오. 이제 모든 사이트를 색인 생성하는 멋진 사이트가 있습니다.

나는 이것들로 시작했다.

현재 위의 두 스타터 키트에서 영감을 얻은 자체 제작 버전의 범용 렌더링을 사용하고 있지만 현재는 구식입니다.

당신의 탐구에 행운을 빕니다!


답변

여기에 대한 답변은 모두 매우 도움이되며 경로를 기대하도록 Webpack 서버를 구성하는 것이 효과적이었습니다.

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

historyApiFallback 은이 문제를 해결했습니다. 이제 라우팅이 올바르게 작동하고 페이지를 새로 고치거나 URL을 직접 입력 할 수 있습니다. 노드 서버의 해결 방법에 대해 걱정할 필요가 없습니다. 이 답변은 분명히 웹팩을 사용하는 경우에만 작동합니다.

편집 : 이것이 필요한 이유에 대한 더 자세한 이유는 여기에 내 대답을 참조하십시오 :
https://stackoverflow.com/a/37622953/5217568


답변

.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"
있으며이 방법은 모두 포괄적이며 아마도 가장 쉬운 방법입니다.


답변

들어 라우터 V4의 반작용 사용자 :

다른 답변에서 언급 한 해시 기록 기술 로이 문제를 해결하려고하면

<Router history={hashHistory} >

V4에서는 작동하지 않습니다 HashRouter. 대신 사용하십시오 .

import { HashRouter } from 'react-router-dom'

<HashRouter>
  <App/>
</HashRouter>

참조 : HashRouter


답변

내비게이션이 클라이언트에서 발생하는지 아니면 서버에서 발생하는지에 따라 두 가지 다른 방식으로 라우터를 호출 할 수 있습니다. 클라이언트 측 작업을 위해 구성했습니다. key 매개 변수는 두 번째로 run 메소드 인 위치입니다.

React Router Link 컴포넌트를 사용하면 브라우저 탐색을 차단하고 transitionTo를 호출하여 클라이언트 측 탐색을 수행합니다. HistoryLocation을 사용하고 있으므로 HTML5 히스토리 API를 사용하여 주소 표시 줄에서 새 URL을 시뮬레이션하여 탐색의 환상을 완성합니다. 구형 브라우저를 사용하는 경우 작동하지 않습니다. HashLocation 구성 요소를 사용해야합니다.

새로 고침을 누르면 모든 React 및 React Router 코드가 무시됩니다. 서버가 요청을 /joblist받고 무언가를 반환해야합니다. 서버 run에서 올바른보기를 렌더링하려면 메소드에 요청 된 경로를 전달해야합니다 . 동일한 경로지도를 사용할 수 있지만 다른 전화 번호가 필요할 수 있습니다.Router.run 있습니다. Charles가 지적했듯이 URL 재 작성을 사용하여이를 처리 할 수 ​​있습니다. 다른 옵션은 node.js 서버를 사용하여 모든 요청을 처리하고 경로 값을 위치 인수로 전달하는 것입니다.

예를 들어, 다음과 같이 보일 수 있습니다.

var app = express();

app.get('*', function (req, res) { // This wildcard method handles all requests

    Router.run(routes, req.path, function (Handler, state) {
        var element = React.createElement(Handler);
        var html = React.renderToString(element);
        res.render('main', { content: html });
    });
});

요청 경로가 (으)로 전달되고 run있습니다. 이렇게하려면 렌더링 된 HTML을 전달할 수있는 서버 측 뷰 엔진이 있어야합니다. renderToString서버에서 React를 사용 하고 실행할 때 고려해야 할 사항이 몇 가지 있습니다 . 페이지가 서버에서 렌더링되고 나면 앱이 클라이언트에로드되면 다시 렌더링되어 필요에 따라 서버 측 렌더링 된 HTML이 업데이트됩니다.


답변

index.html head에서 다음을 추가하십시오.

<base href="/">
<!-- This must come before the css and javascripts -->

그런 다음 webpack dev 서버로 실행할 때이 명령을 사용하십시오.

webpack-dev-server --mode development --hot --inline --content-base=dist --history-api-fallback

--history-api-fallback 중요한 부분입니다


답변

방금 create-react-app를 사용하여 웹 사이트를 만들었고 여기에 동일한 문제가 표시되었습니다. 패키지 BrowserRouting에서 사용 react-router-dom합니다. Nginx 서버에서 실행 중이며 나를 해결 한 것은 다음을 추가하는 것입니다./etc/nginx/yourconfig.conf

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

.htaccessAppache를 실행하는 경우에 다음을 추가 하는 것과 일치합니다.

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

이것은 또한 Facebook 자체에서 제안한 솔루션 인 것처럼 보이고 여기 에서 찾을 수 있습니다