【问题标题】:Using React in a multi-page app在多页面应用程序中使用 React
【发布时间】:2015-11-03 04:22:19
【问题描述】:

我一直在玩 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')
    );
}

我仍在阅读文档,但还没有找到我需要的多页应用程序。

提前致谢。

【问题讨论】:

  • 尝试使用requirejs插件。
  • 如果您不介意 ReactJs 是一个非常大的 JS 库,需要为每个页面进行初始化(正如您所说,您不是在构建单页应用程序),那么我不确定将所有组件合并到一个文件中是否重要。它将被缓存在客户端上。当页面加载时,将其 render 放入 script 块中的正确组件。
  • 我遇到了同样的问题:我有一个应用程序可以在不同的页面上加载其他大型库,我宁愿根据访问者的需要加载 react + 一个库,而不是四个大型库图书馆以防万一。

标签: javascript node.js reactjs


【解决方案1】:

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

该应用程序不是一个完整的 React 应用程序,我将 React 用于动态 Stuff,例如 CommentBox,它是 autark。并且可以包含在任何带有特殊参数的点..

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

当我需要在 SSR 模板中包含一个应用程序时,我只需要包含一个带有“__react-root”类和一个特殊 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 完美支持代码拆分和延迟加载,我认为包含一个示例是有意义的,您不需要将所有应用程序加载到一个包中,而是将它们拆分并按需加载。

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

【讨论】:

  • 看起来不错,有人在使用 npm create-react-app 时运行过这个吗?我不认为这对我有用......我刚刚让它与 1 个应用程序一起运行,并且可以看到它是如何工作的,但我的构建不会创建一个正常工作的生产构建。
  • @Sprose 也应该与 create-react-app 一起使用,我错过了什么吗?也许你可以在 github 上分享一个没有的小例子,我看不出它不应该的原因
  • @Sprose 对不起,答案很晚,但我认为你尝试了完全不同的东西,这种方法试图解决什么。 IMO create react app 为您提供了一些简单的工具来创建 bundle.js。因此,我回答的目的是使用相同的 bundle.js 并在多个 SSR 站点中使用它,并将许多不同的 React 应用程序加载到一个页面中。抱歉,如果我的回答不符合您的需求,请随时创建一个新帖子并描述您正在尝试做的事情,我会尽力帮助您。
  • @SorcererApprentice cra 使用 webpack,你必须弹出然后检查基础知识webpack.js.org/guides/getting-started/#creating-a-bundle
  • @SorcererApprentice 基本上有人在此页面上发布了 webpack 配置:stackoverflow.com/a/41857199/5004923
【解决方案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 组件。

【讨论】:

  • 我在 webex 页面中阅读了以下内容。 webpack version &lt; 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+ 进行更新?
【解决方案3】:

我正在从头开始构建一个应用程序,并且正在学习,但我认为您正在寻找的是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
}

试试看。 This 教程是我对本主题和其他相关主题的理解方面最出色的教程。


原答案如下:

我在这里找到了相同的答案。看看this 的帖子是否能激发您的灵感。如果您的应用程序与我的应用程序类似,它将具有变化很小的区域,并且仅在主体中有所不同。您可以创建一个小部件,其职责是根据应用程序的状态呈现不同的小部件。使用 Flux 架构,您可以发送一个导航操作来更改您的 body 小部件打开的状态,从而有效地仅更新页面的 body。

这就是我现在正在尝试的方法。

【讨论】:

  • 如果 URL 路径是由我的后端代码(在本例中为 nodejs)创建的怎么办? Router 是否会像在单页应用中一样工作?
  • @Scott 如果我不想公开具有特殊小部件的管理页面功能怎么办?使用 react 可以在没有真正身份验证的情况下重新创建外观。
【解决方案4】:

您在使用 CMS 吗?他们往往喜欢更改可能会破坏您的应用程序的 url。

另一种方法是使用 React Habitat 之类的东西。

使用它,您可以注册组件,并且它们会自动暴露给 dom。

例子

注册组件:

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

然后它们可以像这样在你的 dom 中使用:

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

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

以上内容将自动替换为您的 react 组件。

然后您也可以自动将属性(或道具)传递给您的组件:

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

这会将size 作为组件公开。 additional options 用于传递其他类型,例如 json、array's、ints、floats 等。

【讨论】:

    【解决方案5】:

    我知道这个问题被问到已经有一段时间了,但希望这对某人有所帮助。

    正如@Cocomico 提到的,您可以在 webpack.config.js 文件中为应用程序提供多个入口点。如果你正在寻找一个简单的 Webpack 设置(基于多个入口点的想法),它允许你将 React 组件添加到静态页面,你可以考虑使用这个:https://github.com/przemek-nowicki/multi-page-app-with-react

    【讨论】:

      【解决方案6】:

      我建议你看看 InertiaJS:https://inertiajs.com/

      使用 Inertia,您可以像使用您选择的服务器端 Web 框架一样构建应用程序。您将框架的现有功能用于路由、控制器、中间件、身份验证、授权、数据获取等。

      唯一不同的是您的视图层。视图不是使用服务器端呈现(例如 Blade 或 ERB 模板),而是 JavaScript 页面组件。这允许您使用 React、Vue 或 Svelte 构建整个前端。

      【讨论】:

        猜你喜欢
        • 2016-05-17
        • 2017-06-26
        • 1970-01-01
        • 1970-01-01
        • 2016-01-16
        • 2017-12-22
        • 2019-10-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多