Подтвердить что ты не робот

Отправка серверной части с помощью реакции, реакции-маршрутизатора и выражения

Я пытаюсь настроить рендеринг на стороне сервера для своего реагирующего приложения, и я пытаюсь использовать отличный react-router модуль, позволяющий ему обрабатывать ситуации, отличные от js (некоторые искатели, когда пользователь по какой-то причине отключил js). Однако у меня проблемы. Я использовал отличный ответ здесь qaru.site/info/63603/... в качестве руководства, но я получаю странные ошибки, брошенные на меня. При попытке использовать react.renderToString() я получаю постоянный Syntax Error. Я неправильно настроил рендеринг на стороне сервера, потерял что-то очевидное или что-то еще?

Моя настройка:

Действительно основной сервер Express

require('babel/register');

var app = express();


// misc. express config...

var Router = require('react-router'),
    routes = require('../jsx/app').routes,
    React = require('react');


app.use(function(req, res, next) {
  var router = Router.create({location: req.url, routes: routes});
  router.run(function(Handler, state) {
    console.log(Handler);
    var html = React.renderToString(<Handler/>);
    return res.render('react_page', {html: html});
  });
});

Компонент <App/> для верхнего уровня

// Shims
require('intl');
require('es5-shim');

var React = require('react/addons'),
  Router = require('react-router'),
  Nav = require('./nav'),
  injectTapEventPlugin = require("react-tap-event-plugin"),


  window.React = React; // export for http://fb.me/react-devtools

// Intl
var ReactIntl = require('react-intl'),
  IntlMixin = ReactIntl.IntlMixin;

var Route = Router.Route,
  DefaultRoute = Router.DefaultRoute,
  NotFoundRoute = Router.NotFoundRoute,
  RouteHandler = Router.RouteHandler;


var App = React.createClass({
      mixins: [IntlMixin],

      getInitialState: function() {
        return {
          connected: false,
          loaded: false,
          user: true
        };
      },
      render: function() {
          return ( 
            <div className="container-fluid">
              <Nav/>
              <RouteHandler/>
              <Footer/>
            </div>
      );
  }

});

var routes = (
<Route name="Home" path="/" handler={App}>
    <DefaultRoute name="Welcome " handler={Welcome}/>
    <Route name="Bar" path="/bar" handler={Bar}>
    <Route name="foo" path="/foo" handler={Foo}></Route>
 </Route>
);

Router.run(routes, Router.HistoryLocation , function(Handler) {
  React.render(<Handler/>, document.getElementById('app'));
});

module.routes = routes;

вывод:

flo-0,1,2 (err):       <div className="progressbar-container" >
flo-0,1,2 (err):       ^
flo-0,1,2 (err): SyntaxError: Unexpected token <
flo-0,1,2 (err):     at exports.runInThisContext (vm.js:73:16)
flo-0,1,2 (err):     at Module._compile (module.js:443:25)
flo-0,1,2 (err):     at Module._extensions..js (module.js:478:10)
flo-0,1,2 (err):     at Object.require.extensions.(anonymous function) [as .js] (/Users/user/Code/foobar/apps/flo/node_modules/babel/node_modules/babel-core/lib/babel/api/register/node.js:161:7)
flo-0,1,2 (err):     at Module.load (module.js:355:32)
flo-0,1,2 (err):     at Function.Module._load (module.js:310:12)
flo-0,1,2 (err):     at Function.<anonymous> (/Users/user/.nvm/versions/node/v0.12.4/lib/node_modules/pm2/node_modules/pmx/lib/transaction.js:62:21)
flo-0,1,2 (err):     at Function.cls_wrapMethod (/Users/user/Code/foobar/apps/bar/node_modules/newrelic/lib/shimmer.js:230:38)
flo-0,1,2 (err):     at Function.<anonymous> (/Users/user/Code/foobar/apps/bar/node_modules/pmx/lib/transaction.js:62:21)
flo-0,1,2 (err):     at Module.require (module.js:365:17)
flo-0,1,2 (err):     at require (module.js:384:17)
4b9b3361

Ответ 1

Итак, я сам решил это решить. Ошибка, которую я получал, была получена из не-визуализированного вложенного компонента, поэтому механизм js жаловался на случайный < char.

И теперь к моей экспресс-настройке. Для тех, кто не знает, как реагировать на рендеринг на стороне сервера, он довольно прост: Node или io.js могут использоваться для вызова метода React renderToString() на компоненте, а затем отправки этого запроса клиент. Вероятно, вы слышали преимущества, которые приносит этот подход, но для тех, кто этого не знает:

  • вы получаете больше оптимизма для SEO, хотя Google уже может запускать JS в своих сканерах; это в значительной степени просто более безопасная ставка.
  • Откат для ситуаций, не связанных с js. Если ваше приложение script загружается медленно, вы все равно можете отобразить фактическую страницу для своего клиента и не заставлять их ждать, глядя на пустой экран. Это также позволяет кому-то с отключенным JS в своем браузере по-прежнему взаимодействовать с вашим приложением по большей части; ссылки будут по-прежнему работать, формы все равно могут быть отправлены, и c.
  • Вы можете получить дополнительные преимущества обмена кодами между клиентом и сервером. В этом нет ничего невероятного, кроме того, что сложность снижается и, как таковая, вы получаете все преимущества уменьшенной сложности (потенциально меньшую связь, более легкую ремонтопригодность, большую простоту в структуре, изоморфность и т.д.)
  • Дополнительным побочным преимуществом является возможность использовать API-интерфейс API-интерфейсов html5, а не раздражающий материал хэш-фрагмента, который вам нужно использовать в дальнейшем.

Вы можете даже сходить с ума от такого подхода и обрабатывать такие вещи, как заполнители для своего приложения, когда он загружает или предоставляют другие механизмы обратной связи для состояния медленной загрузки (a la Facebook во время загрузки).

Основной подход работает примерно следующим образом:

  • При загрузке приложение Node создает экземпляр реактивного маршрутизатора на основе routes.jsx
  • Запрос отправляется на сервер, который затем использует экспресс 'req.path для предоставления строки маршрута для взаимодействия с маршрутизатором.
  • React router затем соответствует предоставленному маршруту и ​​пытается отобразить соответствующий компонент для экспресс-отправки.
  • React отправляет ответ html, и ваш клиент получает что-то кратное, независимо от скорости вашего приложения script. Мы обслуживаем наших клиентов над отличным CDN, но даже с лучшим распределением и сжатием медленные сети все равно оставят людей с временно пустым экраном.
  • Загрузив необходимое приложение script, React может использовать тот же файл routes.jsx, чтобы захватить и сгенерировать html с react-router отсюда. Другое преимущество здесь в том, что ваш код приложения может быть кэширован, и будущие взаимодействия, надеюсь, даже не придется полагаться на другой вызов.

Еще один момент, который стоит отметить: я использую webpack для связывания кода реакции, и теперь browser.jsx является точкой входа. До рефакторинга для рендеринга на стороне сервера это было ранее app.jsx; вам может потребоваться переконфигурировать вашу структуру, чтобы приспособить то, что получает.:)

le Код:

Browser.jsx

const React = require('react');
const Router = require('react-router').Router;
const hist = require('history');
const routes = require('./routes');

const newHistory = hist.createHistory();

React.render(<Router history={newHistory}>{routes}</Router>, window.document);

App.js(экспресс-сервер):

//...other express configuration

const routes = require('../jsx/routes');
const React = require('react');
const {RoutingContext, match} = require('react-router');
const hist = require('history');

app.use((req, res, next) => {
  const location = hist.createLocation(req.path);
  match({
    routes: routes,
    location: location,
  }, (err, redirectLocation, renderProps) => {
    if (redirectLocation) {
      res.redirect(301, redirectLocation.pathname + redirectLocation.search);
    } else if (err) {
      console.log(err);
      next(err);
      // res.send(500, error.message);
    } else if (renderProps === null) {
      res.status(404)
        .send('Not found');
    } else {
      res.send('<!DOCTYPE html>' + React.renderToString(<RoutingContext {...renderProps}/>));
    }
  });
});

    //...other express configuration

Routes.jsx

<Route path="/" component={App}>
  <DefaultRoute component={Welcome}/>
  <Route path="dashboard" component={Dashboard}/>
  <Route path="login" component={Login}/>
</Route>

App.jsx

<html>
<head>
  <link rel="stylesheet" href="/assets/styles/app.css"/>
</head>
  <body>
    <Navigation/>
    <RouteHandler/>
    <Footer/>
  <body/>
</html>

полезные ссылки: