Використання React у багатосторінковому додатку


122

Я грала з React, і поки мені це дуже подобається. Я будую додаток з NodeJS і хотів би використовувати React для деяких інтерактивних компонентів у додатку. Я не хочу робити це додатком для однієї сторінки.

Я ще не знайшов у Інтернеті нічого, що відповіло б на такі запитання:

Як я розбиваю або зв'язую свої компоненти React у додатку на кілька сторінок?

Наразі всі мої компоненти знаходяться в одному файлі, хоча я ніколи не можу завантажити їх у деяких розділах програми.

Поки я намагаюся використовувати умовні оператори для візуалізації компонентів, шукаючи ідентифікатор контейнера, де React буде надавати. Я не на 100% впевнений у тому, які найкращі практики стосуються React. Це виглядає приблизно так.

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

Я все ще читаю документацію і не знайшов, що мені потрібно для багатосторінкового додатка.

Заздалегідь спасибі.


спробуйте використовувати плагін Requjs.
amit_183

2
Якщо ви не заперечуєте, що ReactJs - це дуже велика бібліотека JS, яку потрібно буде ініціалізувати для кожної сторінки (як ви сказали, що ви не створюєте додаток для однієї сторінки), то я не впевнений, що це важливо для вас " ve об'єднав усі компоненти в один файл. Він буде кешований клієнтом. Коли сторінка завантажується, поставте їй renderправильний компонент у scriptблоці.
WiredPrairie

У мене те саме питання: у мене є додаток, який завантажує інші великі бібліотеки на різні сторінки, і я краще просто завантажую реакцію + одну бібліотеку залежно від потреб відвідувача, а не чотири великі бібліотеки на всякий випадок.
AJFarkas

Відповіді:


83

В даний час я роблю щось подібне.

Додаток не є повноцінним додатком React, я використовую React для динамічних речей, як CommentBox, який є Autark. І можуть бути включені в будь-яку точку зі спеціальними парамами.

Однак усі мої додатки завантажуються та включаються в один файл all.js , тому браузер може кешувати його на різних сторінках.

Коли мені потрібно включити додаток до шаблонів SSR, я просто мушу включити DIV з класом "__react-root" та спеціальним ідентифікатором (назва програми React, яку потрібно надавати)

Логіка дійсно проста:

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 також повинен працювати з додатком create-react, я щось пропускаю? Можливо, ви можете поділитися невеликим прикладом на Github, коли цього немає, я не бачу причини, чому цього не слід
webdeb

1
@Sprose, пізно відповідь, але я думаю, що ви намагаєтеся щось зовсім інше, що цей підхід намагається вирішити. IMO create react appдає вам кілька простих інструментів для створення bundle.js. Отже, мета моєї відповіді полягає в тому, щоб використовувати одне bundle.jsі те ж і використовувати його на неоднозначних сайтах SSR та завантажувати безліч різних програм React на одну сторінку. Вибачте, якщо моя відповідь не відповідає вашим потребам, сміливо створіть нову публікацію та опишіть те, що ви намагаєтесь зробити, я б спробував вам допомогти.
webdeb

1
@SorcererApprentice cra використовує webpack, потрібно вийняти та перевірити
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 три різні html-файли з відповідними js-файлами (приклад для page1):

<!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.Отже, чи слід оновлювати цей зразок для webpack 4+?
Рамеш

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)

У випадку пошуку "термін" доступний як властивість у AnimalSearchBox:

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

Спробуй. Цей підручник - це той, хто ставить мене на перше місце з точки зору мого розуміння цієї та інших суміжних тем.


Оригінальна відповідь наступна:

Я знайшов свій спосіб шукати ту саму відповідь. Подивіться, чи це надихає вас пост. Якщо у вашій заяві щось схоже на моє, у ній з’являться ділянки, які змінюються дуже мало і змінюються лише в основному корпусі. Ви можете створити віджет, відповідальність за який полягає у наданні іншого віджета залежно від стану програми. Використовуючи архітектуру потоку, ви можете відправити навігаційну дію, яка змінює стан переключення віджета тіла, ефективно оновлюючи лише тіло сторінки.

Ось такий підхід я намагаюся зараз.


8
Що робити, якщо URL-адреса створена моїм резервним кодом (у цьому випадку nodejs)? Чи буде Routerпрацювати так, як це робиться в одній сторінці програми?
Хосе Каррільо

1
@Scott Що робити, якщо я не хочу відкривати функціональну сторінку адміністратора, яка має спеціальні віджети? Використовуючи реакцію, можна відтворити зовнішній вигляд без справжньої автентичності.
Кайрат Кемпірбаєв

11

Ви використовуєте CMS? Вони, як правило, люблять змінювати URL-адреси, які можуть порушити вашу програму.

Інший спосіб - це використовувати щось на кшталт React Habitat .

З його допомогою ви можете реєструвати компоненти, і вони автоматично піддаються впливу дому.

Приклад

Реєстрація компонентів (и):

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, масив, ints, floats і т.д.


2

Я знаю, що минуло певний час, як це питання було задано, але, сподіваємось, це комусь допомагає.

Як згадував @Cocomico, ви можете вказати кілька вхідних точок для програми у файлі webpack.config.js. Якщо ви шукаєте просту настройку Webpack (заснована на ідеї декількох точок входу), яка дозволяє додавати компоненти React на статичні сторінки, які ви можете розглянути: https://github.com/przemek-nowicki/multi-page -app-з-реагувати


-1

Я пропоную вам поглянути на InertiaJS: https://inertiajs.com/

Завдяки Inertia ви створюєте додатки так, як ви завжди робили з веб-рамкою на стороні сервера. Ви використовуєте наявну функціональність своєї бази для маршрутизації, контролерів, проміжного програмного забезпечення, аутентифікації, авторизації, отримання даних тощо.

Єдине, що відрізняється - це ваш шар перегляду. Замість того, щоб використовувати візуалізацію на стороні сервера (наприклад, шаблони Blade або ERB), представлення - це компоненти сторінки JavaScript. Це дозволяє будувати весь передній край за допомогою React, Vue або Svelte.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.