如何在反应服务器端渲染中添加额外的快速路由以用作后端

泰勒奥斯汀

在底部找到编辑

我一直在研究很多教程,甚至是位于此处的 React 培训服务器端渲染的文档:https : //reacttraining.com/react-router/web/guides/server-rendering

对我来说一直有问题的是使用其他路由以获得完整的堆栈应用程序。例如,我们将使用 MERN 堆栈 ( mongodb express React/Redux nodejs)。假设我们有两条路线

app.js 像这样:

app.use('/users', users);
app.use('/posts', posts);

并且我们的服务器端渲染的设置与这些教程中的大多数一样,实际上我找不到一个不是这样设置的,为了节省时间,我将把 SSR 代码放在那里。如果您不知道如何进行 SSR,请查看我上面提供的链接中的文档。我认为它可能不需要,但如果让我知道,我可以添加一个简单的设置。

就像是:

app.get('*', (req, res) => { //server side rendering code here});

所以这里的问题是它触及每条路由和服务器端渲染的内部React Router 4,大多数人会使用matchRoutes函数并传入他们用于反应端的路由。

好的,我已经解释了很多,但并不是真正的问题是什么:

问题:在反应方面,让我们说使用动作,我们将在这里使用 axios 作为一个简单的例子。

如果我做:

axios.get('/posts')
.then(response => { 
 console.log(response.data);
 })
.catch(err => {
 console.log(err);
 });

这遇到了问题。对于任何了解 express 和 SSR 的人,您都会知道原因。app.get('*')是命中每条路线,或者更确切地说,每条路线请求都将通过这里,问题是当我们向/posts两种情况之一发送请求时会发生。

情况 1:/posts反应端的路由文件中有一个客户端路由,这种情况将返回服务器端 html,response.data这显然不是我们想要的。

情况 2:/posts反应端的路由文件中没有客户端路由,如果您正确设置了 SSR,这种情况将返回 404 错误或类似于路由或页面未找到的内容。

我需要一种能够使用我的后端的方法,但也能够使用 SSR 进行反应。

可能的解决方案?

  1. 使用某种类型的代理,/api/routename然后说如果然后使用代理,您的调用不会通过app.get('*').

  2. 或者某种仅在单个路由上执行 SSR 的方法。

  3. 或者排除某些路由,但能够使用所有客户端路由。在这我的意思是,如果我有 client side/users和 express side /users,如果我 exclude /users我不希望 client 端中断,但有些人仍然排除 express 端。

如果可能的话,我不完全确定如何执行这些解决方案,但我需要能够使用我的快速路线,而且我找不到具体的方法来做到这一点,或者什么是最佳实践。

编辑:

服务器端 app.js:

require('babel-core/register')({
  presets: ['env', 'react', 'stage-0', 'stage-1']
});

const pkg_json = require('./package.json');
const vertex = require('vertex360')({ site_id: pkg_json.app });
var renderer = require('./renderer.js');

// initialize app
const app = vertex.app();

// import routes
const index = require('./routes/index');
const api = require('./routes/api');
const users = require('./routes/users');

// set routes
app.use('/api/users', users);

// hopefully will be used on every Route, this should handle SSR RR4
app.use(renderer);

module.exports = app;

渲染器.js:

import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { renderRoutes } from 'react-router-config';
import serialize from 'serialize-javascript';
import { Helmet } from 'react-helmet';
import { matchRoutes } from 'react-router-config';

import routes from './src/routes';
import createStore from './src/stores';

function handleRender(req, res) {
  const store = createStore.configure(null); // create Store in order to get data from redux

  const promises = matchRoutes(routes, req.path)
    .map(({ route }) => {
      // Matches the route and loads data if loadData function is there
      return route.loadData ? route.loadData(store) : null;
    })
    .map(promise => {
      if (promise) {
        return new Promise((resolve, reject) => {
          promise.then(resolve).catch(resolve); // lets all data load even if route fails
        });
      }
    });

  Promise.all(promises).then(() => {
    const context = {};
    if (context.url) {
      return res.redirect(301, context.url); // redirect for non auth users
    }

    if (context.notFound) {
      res.status(404); // set status to 404 for unknown route
    }

    const content = renderToString(
      <Provider store={store}>
        <StaticRouter location={req.path} context={context}>
          <div>{renderRoutes(routes)}</div>
        </StaticRouter>
      </Provider>
    );

    const initialState = serialize(store.getState());

    const helmet = Helmet.renderStatic();

    res.render('index', { content, initialState, helmet });
  });
}

module.exports = handleRender;

反应入口点:

import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { renderRoutes } from 'react-router-config';
import serialize from 'serialize-javascript';
import { Helmet } from 'react-helmet';
import { matchRoutes } from 'react-router-config';

import routes from './src/routes';
import createStore from './src/stores';

function handleRender(req, res) {
  const store = createStore.configure(null); // create Store in order to get data from redux

  const promises = matchRoutes(routes, req.path)
    .map(({ route }) => {
      // Matches the route and loads data if loadData function is there
      return route.loadData ? route.loadData(store) : null;
    })
    .map(promise => {
      if (promise) {
        return new Promise((resolve, reject) => {
          promise.then(resolve).catch(resolve); // lets all data load even if route fails
        });
      }
    });

  Promise.all(promises).then(() => {
    const context = {};
    if (context.url) {
      return res.redirect(301, context.url); // redirect for non auth users
    }

    if (context.notFound) {
      res.status(404); // set status to 404 for unknown route
    }

    const content = renderToString(
      <Provider store={store}>
        <StaticRouter location={req.path} context={context}>
          <div>{renderRoutes(routes)}</div>
        </StaticRouter>
      </Provider>
    );

    const initialState = serialize(store.getState());

    const helmet = Helmet.renderStatic();

    res.render('index', { content, initialState, helmet });
  });
}

module.exports = handleRender;
泰勒奥斯汀

感谢@VivekN,您这样做的方式是确保您app.get('*')的路线低于每个声明的路线。这应该允许您的其他路线首先通过。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

反应路由器和服务器端渲染

来自分类Dev

如何在React-Router中以编程方式进行服务器端路由?

来自分类Dev

反应服务器端渲染-addEventListener

来自分类Dev

反应服务器端渲染校验和警告

来自分类Dev

在服务器端访问反应路由参数

来自分类Dev

React服务器端仅渲染特定路由

来自分类Dev

安装程序如何对服务器端渲染做出反应?

来自分类Dev

在角度服务器端渲染中渲染图像

来自分类Dev

如何在Meteor中添加或删除集合文档字段服务器端?

来自分类Dev

如何在服务器端路由中使用Aurelia的路由器

来自分类Dev

如何在客户端渲染的React应用中发出服务器端请求?

来自分类Dev

如何在共享服务器服务中运行服务器端Javascript?

来自分类Dev

具有React前端路由的Express服务器,无需服务器端渲染

来自分类Dev

如何通过道具服务器端反应

来自分类Dev

如何使用Angular 2服务器端渲染

来自分类Dev

如何在服务器端快速显示动态图像?

来自分类Dev

如何在blazor服务器端使用type ='text'渲染输入?

来自分类Dev

如何在服务器端使用异步数据渲染组件

来自分类Dev

如何在服务器端渲染之前向我的商店发送操作?- 还原

来自分类Dev

服务器端的条件渲染

来自分类Dev

使用客户端和服务器端渲染来反应同构组件

来自分类Dev

在 Angular Universal 中,如何在服务器端渲染期间避免 API 客户端并将它们推迟到客户端?

来自分类Dev

如何将服务器端渲染中的数据从节点传递到reactjs组件

来自分类Dev

用客户端路由来响应服务器端渲染

来自分类Dev

使用VSCode Remote SSH时,如何在服务器端的PATH中添加某些内容?

来自分类Dev

流星选取器服务器端路由器使用快速中间件

来自分类Dev

服务器端反应路由器,而不是同构的

来自分类Dev

vue 3与Vuex和路由器的服务器端渲染

来自分类Dev

在Meteor中,如何在服务器端完成操作时在客户端知道?

Related 相关文章

  1. 1

    反应路由器和服务器端渲染

  2. 2

    如何在React-Router中以编程方式进行服务器端路由?

  3. 3

    反应服务器端渲染-addEventListener

  4. 4

    反应服务器端渲染校验和警告

  5. 5

    在服务器端访问反应路由参数

  6. 6

    React服务器端仅渲染特定路由

  7. 7

    安装程序如何对服务器端渲染做出反应?

  8. 8

    在角度服务器端渲染中渲染图像

  9. 9

    如何在Meteor中添加或删除集合文档字段服务器端?

  10. 10

    如何在服务器端路由中使用Aurelia的路由器

  11. 11

    如何在客户端渲染的React应用中发出服务器端请求?

  12. 12

    如何在共享服务器服务中运行服务器端Javascript?

  13. 13

    具有React前端路由的Express服务器,无需服务器端渲染

  14. 14

    如何通过道具服务器端反应

  15. 15

    如何使用Angular 2服务器端渲染

  16. 16

    如何在服务器端快速显示动态图像?

  17. 17

    如何在blazor服务器端使用type ='text'渲染输入?

  18. 18

    如何在服务器端使用异步数据渲染组件

  19. 19

    如何在服务器端渲染之前向我的商店发送操作?- 还原

  20. 20

    服务器端的条件渲染

  21. 21

    使用客户端和服务器端渲染来反应同构组件

  22. 22

    在 Angular Universal 中,如何在服务器端渲染期间避免 API 客户端并将它们推迟到客户端?

  23. 23

    如何将服务器端渲染中的数据从节点传递到reactjs组件

  24. 24

    用客户端路由来响应服务器端渲染

  25. 25

    使用VSCode Remote SSH时,如何在服务器端的PATH中添加某些内容?

  26. 26

    流星选取器服务器端路由器使用快速中间件

  27. 27

    服务器端反应路由器,而不是同构的

  28. 28

    vue 3与Vuex和路由器的服务器端渲染

  29. 29

    在Meteor中,如何在服务器端完成操作时在客户端知道?

热门标签

归档