다중 페이지 앱에서 React 사용


122

나는 React를 가지고 놀았고 지금까지 정말 좋아합니다. NodeJS로 앱을 구축 중이며 애플리케이션 전체의 일부 대화 형 구성 요소에 React를 사용하고 싶습니다. 단일 페이지 앱으로 만들고 싶지 않습니다.

다음 질문에 대한 답을 웹에서 아직 찾지 못했습니다.

다중 페이지 앱에서 React 컴포넌트를 나누거나 번들링하려면 어떻게해야합니까?

현재 모든 구성 요소는 앱의 일부 섹션에서로드하지 않아도 하나의 파일에 있습니다.

지금까지 조건문을 사용하여 React가 렌더링 할 컨테이너의 ID를 검색하여 구성 요소를 렌더링하려고합니다. React의 모범 사례가 무엇인지 100 % 확신하지 못합니다. 이렇게 생겼습니다.

if(document.getElementById('a-compenent-in-page-1')) {
    React.render(
        <AnimalBox url="/api/birds" />,
        document.getElementById('a-compenent-in-page-1')
    );
}

if(document.getElementById('a-compenent-in-page-2')) {
    React.render(
        <AnimalBox url="/api/cats" />,
        document.getElementById('a-compenent-in-page-2')
    );
}

if(document.getElementById('a-compenent-in-page-3')) {
    React.render(
        <AnimalSearchBox url="/api/search/:term" />,
        document.getElementById('a-compenent-in-page-3')
    );
}

아직 문서를 읽고 있지만 아직 다중 페이지 앱에 필요한 것을 찾지 못했습니다.

미리 감사드립니다.


requirejs 플러그인을 사용해보십시오.
amit_183

2
ReactJs가 각 페이지에 대해 초기화해야하는 매우 큰 JS 라이브러리라는 점에 신경 쓰지 않는다면 (단일 페이지 앱을 빌드하지 않는다고 말했듯이), 그게 중요한지 모르겠습니다. 모든 구성 요소를 하나의 파일로 결합했습니다. 클라이언트에 캐시됩니다. 페이지가로드되면 블록에 render올바른 구성 요소 가 있어야합니다 script.
WiredPrairie 2015-08-12

동일한 문제가 있습니다. 다른 페이지에 다른 대형 라이브러리를로드하는 앱이 있으며, 만일을 대비하여 4 개의 대형 라이브러리가 아닌 방문자의 필요에 따라 반응 + 하나의 라이브러리 만로드하고 싶습니다.
AJFarkas

답변:


83

현재 나는 비슷한 일을하고 있습니다.

이 응용 프로그램은 완전한 React 앱이 아니며, 저는 autark 인 CommentBox와 같은 동적 Stuff에 React를 사용하고 있습니다. 그리고 특별한 매개 변수를 사용하여 모든 지점에 포함될 수 있습니다.

그러나 내 모든 하위 앱이로드되고 단일 파일 all.js에 포함되므로 브라우저에서 페이지간에 캐시 할 수 있습니다.

SSR 템플릿에 앱을 포함해야 할 때 "__react-root"클래스와 특수 ID (렌더링 할 React 앱의 이름)가있는 DIV 만 포함하면됩니다.

논리는 정말 간단합니다.

import CommentBox from './apps/CommentBox';
import OtherApp from './apps/OtherApp';

const APPS = {
  CommentBox,
  OtherApp
};

function renderAppInElement(el) {
  var App = APPS[el.id];
  if (!App) return;

  // get props from elements data attribute, like the post_id
  const props = Object.assign({}, el.dataset);

  ReactDOM.render(<App {...props} />, el);
}

document
  .querySelectorAll('.__react-root')
  .forEach(renderAppInElement)

<div>Some Article</div>
<div id="CommentBox" data-post_id="10" class="__react-root"></div>

<script src="/all.js"></script>

편집하다

webpack은 코드 분할 및 LazyLoading을 완벽하게 지원하기 때문에 하나의 번들에 모든 앱을로드 할 필요는 없지만 분할하여 필요에 따라로드하는 예제를 포함하는 것이 합리적이라고 생각했습니다.

import React from 'react';
import ReactDOM from 'react-dom';

const apps = {
  'One': () => import('./One'),
  'Two': () => import('./Two'),
}

const renderAppInElement = (el) => {
  if (apps[el.id])  {
    apps[el.id]().then((App) => {
      ReactDOM.render(<App {...el.dataset} />, el);
    });
  }
}

1
멋지군요. npm create-react-app을 사용할 때 실행중인 사람이 있습니까? 나는 이것이 나를 위해 작동하지 않을 것이라고 생각합니다 ... 방금 1 앱으로 실행 중이며 어떻게 작동하는지 볼 수 있지만 내 빌드는 올바르게 작동하는 프로덕션 빌드를 만들지 않습니다.
Sprose

@Sprose는 create-react-app에서도 작동해야합니다. 뭔가 빠졌나요? github에서 공유 할 수없는 작은 예를 공유 할 수 있습니다. 그 이유를 모르겠습니다
webdeb

1
@Sprose는 늦은 대답을 위해 sry하지만 완전히 다른 것을 시도하고 있다고 생각합니다.이 접근 방식은 해결하려고합니다. IMO create react app는 쉽게 만들 수있는 도구를 제공합니다 bundle.js. 따라서 내 대답의 목적은 동일한 것을 bundle.js사용하고 여러 SSR 사이트에서 사용하고 여러 가지 React 응용 프로그램을 단일 페이지에로드하는 것입니다. 죄송합니다. 제 답변이 귀하의 요구에 맞지 않으면 언제든지 새 게시물을 작성하고 귀하가하려는 작업을 설명해 주시면 도와 드리겠습니다.
webdeb

1
@SorcererApprentice cra는 webpack을 사용하므로 기본 webpack.js.org/guides/getting-started/#creating-a-bundle
webdeb

1
@SorcererApprentice는 기본적으로 누군가이 페이지에 webpack 구성을 게시했습니다. stackoverflow.com/a/41857199/5004923
webdeb

52

webpack.config.js 파일에서 애플리케이션에 대한 여러 진입 점을 제공 할 수 있습니다.

var config = {
  entry: {
    home: path.resolve(__dirname, './src/main'),
    page1: path.resolve(__dirname, './src/page1'),
    page2: path.resolve(__dirname, './src/page2'),
    vendors: ['react']
  },
 output: {
    path: path.join(__dirname, 'js'),
    filename: '[name].bundle.js',
    chunkFilename: '[id].chunk.js'
  },
}

그런 다음 src 폴더에 각각의 js 파일이있는 세 개의 다른 html 파일을 가질 수 있습니다 (페이지 1의 예).

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Page 1</title>
</head>
<body>
  <div id="app"></div>
  <script src="./vendors.js"></script>
  <script src="./page1.bundle.js"></script>
</body>
</html>

JavaScript 파일 :

import React from 'react'
import ReactDom from 'react-dom'
import App from './components/App'
import ComponentA from './components/ReactComponentA'
ReactDom.render(<div>
                  <App title='page1' />
                  <ReactComponentA/>
                 </div>, document.getElementById('app'))

그런 다음 각 단일 페이지에 대해 다른 React 구성 요소를로드 할 수 있습니다.


1
webex 페이지에서 아래 내용을 읽었습니다. webpack version < 4 it was common to add vendors as separate entrypoint to compile it as separate file (in combination with the CommonsChunkPlugin). This is discouraged in webpack 4. Instead the optimization.splitChunks option takes care of separating vendors and app modules and creating a separate file. Do not create a entry for vendors or other stuff which is not the starting point of execution.그렇다면이 샘플을 웹팩 4 이상으로 업데이트해야합니까?
Ramesh

32

나는 처음부터 응용 프로그램을 만들고 있고 배우면서 배우고 있지만 찾고있는 것은 React-Router 라고 생각합니다 . React-Router는 구성 요소를 특정 URL에 매핑합니다. 예를 들면 :

render((
    <Router>
        <Route path="/" component={App}>
            <Route path="api/animals" component={Animals}>
               <Route path="birds" component={Birds}/>
               <Route path="cats" component={Cats}/>
            </Route>
        </Route>
        <Route path="api/search:term" component={AnimalSearchBox}>
    </Router>
), document.body)

검색 사례에서 'term'은 AnimalSearchBox의 속성으로 액세스 할 수 있습니다.

componentDidMount() {
    // from the path `/api/search/:term`
    const term = this.props.params.term
}

시도해보십시오. 튜토리얼은 이것과 다른 관련 주제에 대한 나의 이해의 관점에서 저를 맨 위에 올려 놓은 것입니다.


원래 답변은 다음과 같습니다.

나는 여기에서 같은 답을 찾기 위해 길을 찾았습니다. 있는지 확인 게시물을 고무시킨다. 귀하의 응용 프로그램이 내 것과 같은 것이라면 거의 변하지 않고 본체에서만 변하는 영역이 있습니다. 응용 프로그램의 상태에 따라 다른 위젯을 렌더링하는 책임이있는 위젯을 만들 수 있습니다. 플럭스 아키텍처를 사용하면 본문 위젯이 전환되는 상태를 변경하는 탐색 작업을 전달하여 페이지 본문 만 효과적으로 업데이트 할 수 있습니다.

이것이 제가 지금 시도하고있는 접근 방식입니다.


8
내 백엔드 코드 (이 경우 nodejs)에 의해 URL 경로가 생성되면 어떻게됩니까? 의지 Router작업은 단일 페이지 응용 프로그램에서와 같은 방법으로?
Jose Carrillo 2015

1
@Scott 특별한 위젯이있는 관리 페이지 기능을 노출하지 않으려면 어떻게합니까? react를 사용하면 실제 인증 없이도 모양과 느낌을 재현 할 수 있습니다.
Kairat Kempirbaev 2011

11

CMS를 사용하고 있습니까? 그들은 당신의 응용 프로그램을 망칠 수있는 URL 변경을 좋아하는 경향이 있습니다.

또 다른 방법은 React Habitat 과 같은 것을 사용하는 것 입니다.

이를 통해 구성 요소를 등록 할 수 있으며 자동으로 dom에 노출됩니다.

구성 요소 등록 :

container.register('AnimalBox', AnimalBox);
container.register('AnimalSearchBox', AnimalSearchBox);

그런 다음 그들은 다음과 같이 당신의 돔에서 사용할 수 있습니다.

<div data-component="AnimalBox"></div>

<div data-component="AnimalSearchBox"></div>

위의 내용은 자동으로 반응 구성 요소로 대체됩니다.

그런 다음 속성 (또는 소품)을 구성 요소에도 자동으로 전달할 수 있습니다.

<div data-component="AnimalBox" data-prop-size="small"></div>

이것은 size컴포넌트에 소품으로 노출 됩니다. json, array 's, int, floats 등과 같은 다른 유형을 전달하기위한 추가 옵션 이 있습니다 .


2

이 질문을 한 지 오래되었지만 도움이되기를 바랍니다.

@Cocomico가 언급했듯이 webpack.config.js 파일에서 애플리케이션에 대한 여러 진입 점을 제공 할 수 있습니다. 정적 페이지에 React 구성 요소를 추가 할 수있는 간단한 Webpack 설정 (다중 진입 점 개념을 기반으로 함)을 찾고 있다면 https://github.com/przemek-nowicki/multi-page 사용을 고려할 수 있습니다. -반응이있는 앱


-1

InertiaJS를 살펴 보시기 바랍니다 : https://inertiajs.com/

Inertia를 사용하면 선택한 서버 측 웹 프레임 워크로 항상 해왔 던 것처럼 앱을 빌드 할 수 있습니다. 라우팅, 컨트롤러, 미들웨어, 인증, 권한 부여, 데이터 가져 오기 등에 프레임 워크의 기존 기능을 사용합니다.

유일한 차이점은 뷰 레이어입니다. 서버 측 렌더링 (예 : Blade 또는 ERB 템플릿)을 사용하는 대신보기는 JavaScript 페이지 구성 요소입니다. 이를 통해 React, Vue 또는 Svelte를 사용하여 전체 프런트 엔드를 구축 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.