React.js in Rakuten Taiwan
Integration with Content Management System
Jayden Lin
Python Django Co-Creater Jacob Kaplan-Moss @ Pycon 2015
Hi, I'm Jayden, and I'm a much more mediocre programmer.
Yahoo! Taiwan Intern (2012~2013) Rakuten Taiwan F2E Engineer (2014~)
Outline
- Problem: What a mess
- Solution: Content Management System + React.js
-
Technical Sharing:
- Server side rendering troubleshooting
- Asyc loading script setting with webpack
Mess ??
"Move the section to right"
"Move that section down.."
"Switch the position of that two sections.."
"Then.. add a banner between them.."
"Add a carousel here"
CVR & RSR
Matters!
CVR & RSR
Matters!
Text
API Input
API Input
API Input
API Input
API Input
API Input
Manually Input
Manually Input
Manually Input
Manually Input
Manually Input
Manually Input
Manully Input
Exchange
Exchange
Manully Input
Manully Input
Manully Input
Manully Input
API Input
API Input
API Input
API Input
There are other more 40 channel pages...
and there is only 1 f2e engineer at the time.
Mess Up!!!
Problems that we faced...
(1) Can't respond to changes with speed
(2) Code maintenance
Assemble them yourself!
Could you kindly assemble them by yourself?
Introduce CMS for arranging the page
(An open source WYSIWYG Editor written by PHP)
more demo about C5: https://www.youtube.com/watch?v=KEThnpJcFjc
Exchange
Manully Input
Manully Input
Manully Input
Manully Input
React Component
React Component
React
Component
React
Component
React
Component
Manually Input and API input
Why React + Webpack
It's easy for management of each component's
html markup & js , css
Architecture Overview
Node.js
Server
Markup
API
Style
API
(webpack)
CMS
CDN
Backend Data API
deploy js & css
request
html
script
&link
tags
request
request
deploy
combined
html
Manully Input
Manully Input
Manully Input
Manully Input
node module
node module
node module
node module
node module
ref: https://github.com/facebook/react/tree/master/examples/server-rendering
Inspired by Facebook server side rendering example
Markup API
React.renderToString()
Style API
1. Collect all components' file path
2. write the temp entry file
3. run webpack on server site
4. deploy files to CDN
5. return <script> & <link> tags
(1) Unify each component's rendering code (sample code)
(2) Seperate css for each componet
var SuperFocus = require("./components/super_focus.jsx");
React.render(<SuperFocus id="super-focus"
contentObject={window.["super-focus"].data}/>,
document.getElementById('super-focus'));
var TopBanner = require("./components/top_banner.jsx");
React.render(<TopBanner id="top-banner"
contentObject={window.["top-banner"].data}/>,
document.getElementById('top-banner'));
var HotKeywords=require("./components/hot_keywords.jsx");
React.render(<HotKeywords id="hot-keywords"
contentObject={window.["hot-keywords"].data}/>,
document.getElementById('hot-keywords'));
require("./components/super_focus.css");
var SuperFocus = require("./components/super_focus.jsx");
require("./components/top_banner.css");
var TopBanner = require("./components/top_banner.jsx");
require("./components/hot_keywords.css");
var HotKeywords=require("./components/hot_keywords.jsx");
Pros
1. Composability.
2. Response to changes with speed.
(no need programmers)
3. Easy for optimization and refactoring
Cons
1. Interactions between components is hard to be implemented.
2. BE CAREFUL for developing components without messy dependencies.
Technical Sharing
1. Server side rendering troubleshooting
2. Asyc loading script setting with webpack
Libraries that use dom or window...
Issue:
Solution:
var jsdom = require("jsdom").jsdom;
global.document = jsdom("hello world");
global.window = document.parentWindow;
var swiper = require("swiper");
1. Use jsdom
2. put them into compontDidMount
renderToString doesn't wait asyc API call
Issue:
Solution:
var TopBanner = require("./components/top_banner.jsx");
React.render(<TopBanner id="top-banner" contentObject={window.data}/>,
document.getElementById('top-banner'));
<script>
window.data={ ... }
</script>
<div id="top-banner"> <img src="..."/> </div>
Webpack require("xxx.css") breaks the server side rendering
Issue:
Solution:
require("./components/top_banner.css");
var TopBanner = require("./components/top_banner.jsx");
React.render(<TopBanner id="top-banner" contentObject={window.data}/>,
document.getElementById('top-banner'));
Aync loading script with webpack setting
{
entry: { a: "./a", b: "./b" },
output: { filename: "[name].js" },
plugins: [ new webpack.optimize.CommonsChunkPlugin("init.js") ]
}
webpack.optimize.CommonsChunkPlugin
&
aync
<script src="init.js"/>
<script src="a.js" asyc/>
<script src="b.js" asyc/>
/*sample code*/
var ready=function(fn) {
if (document.readyState != 'loading'){
fn();
} else if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', fn);
} else {
document.attachEvent('onreadystatechange', function() {
if (document.readyState != 'loading')
fn();
});
}
}
ready(function(){
[
'init.js',
'a.js',
'b.js'
].forEach(function(src,index)
{
var script = document.createElement('script');
if(index===0){
script.async=false;
}
script.src = src;
document.body.appendChild(script);
);
});
webpack.optimize.CommonsChunkPlugin
/*callback hell*/
var React=require("react");
require("./chucks/view0.jsx")(React,function(){
require("./chucks/view1.jsx")(React,function(){
require("./chucks/view2.jsx")(React,function(){
require("./chucks/view3.jsx")(React,function(){
require("./chucks/view4.jsx")(React,function(){
require("./chucks/view5.jsx")(Reactfunction(){
require("./chucks/view6.jsx")(React,function(){
});
});
});
});
});
});
});
require.ensure
One more thing...
Q&A
var TopBanner = require("./components/top_banner.jsx");
React.render(<TopBanner id="top-banner" contentObject={window.data}/>,
document.getElementById('top-banner'));
<script>
window.data={ ... }
</script>
<div id="top-banner"> <img src="..."/> </div>
Issue 1: Better way to put the server values to client ?
Issue 2: Duplicated React key
WE ARE HIRING!!
Node.js & React.js
Jenkins + Docker + Mocha
React.js in Rakuten Taiwan
By Jayden Lin
React.js in Rakuten Taiwan
Talktalk in React.js tw meetup. 2015/06/24 40mins
- 3,453