2015-06-03 30 views
29

Tôi đang cố gắng thiết lập hiển thị phía máy chủ cho ứng dụng phản ứng của mình và tôi đang cố sử dụng mô-đun react-router tuyệt vời để cho phép nó xử lý các trường hợp không phải js (một số trình thu thập thông tin, khi người dùng đã tắt js vì một số lý do). Tuy nhiên, tôi đang gặp rắc rối. Tôi đã sử dụng phản ứng tuyệt vời ở đây https://stackoverflow.com/a/28558545/3314701 như một hướng dẫn về các loại, nhưng tôi nhận được lỗi lạ ném vào tôi. Tôi nhận được sự liên tục Syntax Error khi cố gắng sử dụng react.renderToString(). Tôi có đang thiết lập hiển thị phía máy chủ không chính xác, thiếu điều gì đó hiển nhiên hoặc bất kỳ điều gì khác không?Hiển thị bên máy chủ với phản ứng, phản ứng-bộ định tuyến và hiển thị

thiết lập của tôi:

máy chủ Really cơ bản nhanh

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

cấp cao phản ứng <App/> phần

// 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; 

đầu ra:

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) 
+0

Các lỗi dường như không có liên quan đến mã bạn đăng, giống như bạn quên bao gồm một JSX pa rser một nơi nào đó – David

+0

Tôi đã làm việc trên một số ví dụ [ở đây] (https://github.com/goatslacker/isomorphic-react-examples) bằng cách sử dụng alt và iso với bộ định tuyến phản ứng, hy vọng nó có thể hữu ích –

Trả lời

40

Vì vậy, tôi đã tự mình giải quyết vấn đề này. Lỗi tôi đã nhận được từ một thành phần lồng nhau không được trả lại, đó là lý do tại sao động cơ js đã phàn nàn về ngẫu nhiên < char.

Và bây giờ để thiết lập nhanh của tôi. Đối với những người không biết làm thế nào phản ứng có thể được sử dụng với dựng hình phía máy chủ, nó khá đơn giản: Node hoặc io.js có thể được sử dụng để gọi phương thức renderToString() của React trên một thành phần và sau đó gửi cho khách hàng yêu cầu. Bạn có thể đã nghe những lợi ích mà cách tiếp cận này mang lại, nhưng đối với những người không biết:

  1. bạn nhận được nhiều thông tin hơn về SEO, mặc dù google có thể thực thi JS trong trình thu thập dữ liệu của nó; đây là khá nhiều chỉ là một cược an toàn hơn
  2. Dự phòng cho các tình huống không phải js. Nếu kịch bản ứng dụng của bạn đang tải chậm, bạn vẫn có thể hiển thị trang thực cho khách hàng của bạn và không làm cho chúng đợi trong khi nhìn chằm chằm vào màn hình trống. Điều này cũng cho phép một người nào đó với JS bị vô hiệu hóa trên trình duyệt của họ vẫn tương tác với ứng dụng của bạn cho hầu hết các phần; các liên kết sẽ vẫn hoạt động, các biểu mẫu vẫn có thể gửi, & c.
  3. Bạn có thể nhận được các lợi ích bổ sung khi chia sẻ mã giữa máy khách và máy chủ. Không có gì đáng ngạc nhiên về điều này ngoài thực tế là độ phức tạp bị giảm và, như vậy, bạn nhận được tất cả những lợi ích của độ phức tạp giảm (khả năng ghép nối ít hơn, dễ bảo trì hơn, đơn giản hơn trong cấu trúc, isomorphic-ness, & c.)
  4. Một lợi ích phụ nữa là khả năng sử dụng API lịch sử html5 của router phản ứng thay vì các công cụ băm băm phiền toái mà bạn phải sử dụng.

Bạn thậm chí có thể bị điên với cách tiếp cận này và xử lý những thứ như trình giữ chỗ cho ứng dụng của bạn trong khi tải hoặc cung cấp cơ chế phản hồi khác cho trạng thái tải chậm (a la Facebook khi tải).

Cách tiếp cận cơ bản hoạt động xấp xỉ theo cách sau đây:

  1. Khi bootstrap, ứng dụng nút instantiates một trường hợp phản ứng-router dựa trên routes.jsx
  2. Yêu cầu đi đến máy chủ, sau đó sử dụng nhanh req.path để cung cấp chuỗi tuyến đường cho phản ứng-bộ định tuyến để xử lý.
  3. Bộ phản hồi sau đó đối sánh với tuyến được cung cấp và cố gắng hiển thị thành phần tương ứng để thể hiện để gửi lại.
  4. Phản hồi gửi phản hồi html và khách hàng của bạn sẽ vẽ thứ gì đó bất kể tốc độ của tập lệnh ứng dụng của bạn. Chúng tôi phục vụ chúng tôi trên một CDN tuyệt vời, nhưng ngay cả với sự phân phối tốt nhất và các mạng chậm nén sẽ vẫn để người khác với một màn hình tạm thời trống.
  5. Sau khi tải tập lệnh ứng dụng cần thiết, React có thể sử dụng cùng một tệp routes.jsx để tiếp quản và tạo html với react-router từ đây trở đi. Một lợi ích khác ở đây là mã ứng dụng của bạn có thể được lưu trong bộ nhớ cache và tương tác trong tương lai hy vọng thậm chí sẽ không phải dựa vào một cuộc gọi khác.

Một điểm đáng lưu ý: Tôi sử dụng gói webpack để đóng mã phản ứng của tôi và bây giờ là browser.jsx là điểm vào. Trước khi tái cấu trúc cho hiển thị phía máy chủ, trước đây là app.jsx; bạn có thể cần phải cấu hình lại cấu trúc của bạn để phù hợp với những gì được hiển thị ở đâu. :)

le Code:

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 (bày tỏ server):

//...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> 

liên kết hữu ích:

+5

Niềm vui của tôi - sẽ cập nhật lại đôi khi sớm w/bất kỳ thay đổi API bộ phản ứng-bộ định tuyến nào mới hơn – markthethomas

+1

@markthethomas Bạn đã sử dụng JSX như thế nào trong tập lệnh máy chủ app.js của mình? –

+0

bạn cũng có thể kiểm tra redux khởi động của tôi, redux-saga, phản ứng-router v4 https://github.com/gzoreslav/react-redux-saga-universal-application –

Các vấn đề liên quan