在多页应用中使用 React

2022-08-30 04:17:12

我一直在玩 React,到目前为止,我真的很喜欢它。我正在用 NodeJS 构建一个应用程序,并希望将 React 用于应用程序中的一些交互式组件。我不想让它成为单页应用程序。

我还没有在网上找到任何回答以下问题的东西:

如何在多页应用中拆分或捆绑我的 React 组件?

目前,我的所有组件都在一个文件中,即使我可能永远不会在应用程序的某些部分中加载它们。

到目前为止,我正在尝试使用条件语句来渲染组件,方法是搜索 React 将呈现的容器的 ID。我不是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')
    );
}

我仍在阅读文档,但尚未找到多页应用程序所需的内容。

提前致谢。


答案 1

目前,我正在做类似的事情。

该应用程序不是一个完整的React应用程序,我正在使用React进行动态的东西,比如NotemarkBox,这是自给自足的。并且可以在任何点包含特殊参数。

但是,我的所有子应用程序都已加载并包含在单个文件中,因此浏览器可以跨页面缓存它。all.js

当我需要将应用程序包含在SSR模板中时,我只需要包含一个带有类“__react根”和特殊ID的DIV(要呈现的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);
    });
  }
}

答案 2

您可以在 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 组件。