Java + React.jsで
Sever Side Rendering
2015-04-24 React.js meetup #1 LT
Toshiaki Maki (@making)
自己紹介
• @making
• Java界隈にいます
• Spring Framework好き
自己紹介
• @making
• Java界隈にいます
• Spring Framework好き
「はじめてのSpring Boot」
著者
自己紹介
• @making
• Java界隈にいます
• Spring Framework好き
「はじめてのSpring Boot」
著者
Spring IO 2015スピーカー
私とServer Side Rendering
• SPAでブログ作った!
http://blog.ik.am
私とServer Side Rendering
• SPAでブログ作った!
Backend
API
(Java)
Frontend
SPA
(Backbone.js)
Backend
SPA
(Backbone.js)
REST API
REST API
http://blog.ik.am
https://github.com/making/categolj2-backend
_人人人人人人人_
> ググれない <
 ̄Y^Y^Y^Y^Y^Y ̄
_人人人人人人人_
> ググれない <
 ̄Y^Y^Y^Y^Y^Y ̄
アフィリエイト収入が
1/4に😭
はてブ
はてブ
_人人人人人人人_
> Loading... <
 ̄Y^Y^Y^Y^Y^Y ̄
Sever Side Rendering
やるしかない!
SSR候補
•Prerender
•Rendr (Backbone.js)
•React.js
SSR候補
•Prerender
•Rendr (Backbone.js)
•React.js
採用理由:
流行っているから
React.jsで SSR?
React.jsで SSR?
それJavaでもできるよ
JavaScript Engine in Java
• ScriptEngine API (JSR-223)
• Java SE 6, 7 … Rhino
• Java SE 8 … Nashorn
JavaScript Engine in Java
• ScriptEngine API (JSR-223)
• Java SE 6, 7 … Rhino
• Java SE 8 … Nashorn
JavaとJavaScriptの関係は
インドとインドネシア
の関係ほど単純じゃない
ScriptEngine
ScriptEngineManager engineManager = 

new ScriptEngineManager();

ScriptEngine engine = 

engineManager.getEngineByName("js");

engine 

.eval("function sum(a,b){return a + b;}");

System.out.println(engine.eval("sum(1,2);"));

// 3
http://www.oracle.com/technetwork/articles/java/jf14-nashorn-2126515.html
ScriptEngineを使って
Sever Side Rendering
V8バインディング
いらず!
React.js側のコード
window.renderOnClient = function (initialData) { 

React.render( 

<App data={initialData} />, 

document.getElementById('content') 

); 

}; 



window.renderOnServer = function (initialData) { 

//initialData = Java.from(initialData); Listの場合

return React.renderToString( 

<App data={initialData} /> 

); 

};
React.js側のコード
var App = React.createClass({ 

render: function () { 

return ( 

<div> 

<h1>React.js</h1> 

<Greet 

data={this.props.data} /> 

</div> 

); 

} 

}); サーバーサイドで用意さ
れたデータが渡される
React.js側のコード
var Greet = React.createClass({ 

getInitialState: function () { 

return this.props.data || 

{id: 0, content: 'Now Loading...'}; 

}, 

// … 

});
getInitialState()でサーバー
で用意したデータを返す
サーバーサイド// JSONマッパー                           

ObjectMapper objectMapper = new ObjectMapper();       

// ScriptEngineのラッパー                      

ScriptEngine engine = new JavaScriptEngine()         

.polyfill()                        

.load("static/bundle.js")                

.get();                          
                                    

@RequestMapping("/")                        

String index(Model model) throws Exception {         

Greet initialData = new Greet(100, "Data on Server"); 

Object markup = ((Invocable) engine)           

.invokeFunction("renderOnServer", initialData);

model.addAttribute("markup", markup);           

model.addAttribute("initialData",             

objectMapper.writeValueAsString(initialData)); 

return "index";                        

}
HTMLテンプレート
(Thymeleaf)
<body> 

<div id="content" th:utext="${markup}"></div> 

<script src="bundle.js"></script> 

<script type="text/javascript" 

th:inline="javascript"> 

document.addEventListener("DOMContentLoaded", function () { 

var initialData = JSON.parse(/*[[${initialData}]]*/ 

'{"id": -1, "content": "モックデータ"}'); 

renderOnClient(initialData); 

}, false); 

</script> 

</body> エンジン経由だとコメントの中身が評価される
テンプレートを直で開くとコメントの後ろが評価さ
れるので、フロントエンドに閉じて開発可能!
サーバーで生成した
HTMLを埋め込む
componentDidMount (Ajax)
SSRできた!
JSも評価されてる
ということで
フロントをReact.jsで作り直した
Backend
API
(Java)
Frontend
SPA
(React.js)
Backend
SPA
(Backbone.js)
REST API
REST API
https://github.com/making/categolj2-backend/tree/master/frontend-ui-reactjs
ぐぐれ・・・・
ぐぐれとるやん
ん?
ん?
ブログのフロントエンドは
React.jsで書いてみたけど
SSR対応はまだだった!!
ん?
ブログのフロントエンドは
React.jsで書いてみたけど
SSR対応はまだだった!!
Google先生が優秀だった
まとめ
• NashornがあればJavaでも
サーバーサイドレンダリングで
きた
• Google先生はSPAに対応して
いた 今日のソースコード
https://github.com/making/ssr-demo

Java + React.jsでSever Side Rendering #reactjs_meetup