KEMBAR78
Universal JavaScript | PDF
Universal JavaScript ?
SOHO
(Jerry-Hong)
Universal JavaScript ?
Universal JavaScript
• Isomorphic JavaScript
• Isomorphic JavaScript Single Page Application
Client Server SPA
• Universal JavaScript Isomorphic JavaScript
• Single Page Application
Single Page Application (SPA)
• (User Experience)
•
• AJAX, Client-Side Render, Client-Side Router
• Gmail, kkbox web player
Server-rendered Server-rendered + AJAX SPA
Load Performance
Dev Effort
User Experence
From: How instagram.com Works
SPA
SPA
1.
2.
•
class MyTitle extends Component {
render() {
return (
<h1>Hello World</h1>
);
}
}
React
Vue.component('my-title', {
render(h) {
return (
<h1>Hello World</h1>
);
}
})
Vue 2 (JSX)
Vue.component('my-title', {
template: '<h1>Hello World</h1>'
})
Vue 2
@Component({
selector: 'my-title',
template: '<h1>Hello World</h1>'
})
class MyTitle { }
NG 2
•
•
• Flux
• Redux
• Vuex
• CSS class scope
• CSS module
• web component
• vue style scpoed
• View
• Server-Side Render
• Native app
•
•
• Flux
• Redux
• Vuex
• CSS Class Scope
• CSS module
• web component
• vue style scpoed
• View
• Server-Side Render
• Native app
•
•
• Flux
• Redux
• Vuex
• CSS class scope
• CSS module
• web component
• vue style scpoed
• View
• Server-Side Render
• Native app
.
.
.
2.
3. SEO
Universal JavaScript
4. First Time Loading
Universal JavaScript
- React / Redux
• SPA Server Template Engine
• SPA Function (F)
F(n)
F(n) => HTML
• SPA Server Client Server
• Function (F)
• request F HTML
• request Client SPA
SPA Universal JS?
• (1~ 5)
•
•
Universal JS -
Step 1. Router
app
.use(compress())
.use(serve('./static')))
.use(router.routes())
.use(serverRender)
.use(errorBoot)
.listen(process.env.PORT || 8080,
() => {
console.log('listen 3000')
});
Step 1 - Router
• Server Router
API
app
.use(compress())
.use(serve('./static')))
.use(router.routes())
.use(serverRender)
.use(errorBoot)
.listen(process.env.PORT || 8080,
() => {
console.log('listen 3000')
});
Step 1 - Router
• Server Router
API
• Server Render
const store = createStore();
const childRoutes = createRoute(store);
match({
routes: childRoutes,
location: ctx.request.url
}, (error, redirectLocation, renderProps) => {
if (error) { // 500 }
else if (redirectLocation) { // 300 }
else if (renderProps) {
const component = (
<Provider store={ store }>
<RouterContext { ...renderProps }/>
</Provider>
);
const content = ReactDOMServer.renderToString(component);
ctx.response.type = 'text/html';
ctx.body = `<!DOCTYPE html> ... ${content}...</html>`
}
});
app
.use(compress())
.use(serve('./static')))
.use(router.routes())
.use(serverRender)
.use(errorBoot)
.listen(process.env.PORT || 8080,
() => {
console.log('listen 3000')
});
Step 1 - Router
• Server Router
API
• Server Render
•
Step 2. AJAX
• SPA ComponentDidMount AJAX
• Server Render ComponentWillMount Render
• Server Render AJAX Response Render
Step 2. AJAX
•
• Server Render
• redux-async-connect
• async-props
• React-Router onEnter API ( )
• universal-router
@fetchData((dispatch, state, routeState, replace) => {
return dispatch(getAllArticle());
})
class Home extends Component {
...
}
// fetchData(...)(Home)
<Route component={ App }>
<Route
path="/"
component={ Home }
onEnter={ Home.onEnter(store) }/>
</Route>
// fetchData.js
export default fetchCall => Component => {
Component.onEnter = (store) =>
(nextState, replace, callback) => {
const result = fetchCall(
store.dispatch,
store.getState(),
nextState,
replace) || Promise.resolve(true);
if(typeof window === 'undefined') {
result.then(() => callback())
.catch((error) => callback(error))
} else {
callback();
}
}
return Component;
}
Step 3.
• Server Render HTML JS
Client Render Client Render
Step 3.
•
• Server Render HTML
• Client Render
(initialState)
const store = createStore();
const childRoutes = createRoute(store);
match({
routes: childRoutes,
location: ctx.request.url
}, (error, redirectLocation, renderProps) => {
...
ctx.body = `<!DOCTYPE html> ... ${content}...
<script>
window.reduxState = ${JSON.stringify(store.getState())

</script>
</html>`
});
Step 4.
• SPA webpack JS
• css-loader
• url-loader
• NodeJS
Step 4.
•
• webpack bundle server code ( )
• js
•
• CSS Module css-modules-require-hook
var nodeExternals =
require('webpack-node-externals');
...
module.exports = {
...
target: 'node',
externals: [nodeExternals()]
...
};
Step 4 - Bundle node
• target node
• webpack-node-
externals
hint: context
Step 5.
• Server Client
• webpack
new webpack.DefinePlugin({
'process.env.BROWSER': true
}))
new webpack.DefinePlugin({
'process.env.BROWSER': false
}))
webpack-server.config.js webpack.config.js


Universal JavaScript


SEO First Time Loading
Universal JavaScript
MVC View
• MVC View
• HTML
• Universal JavaScript
• Client SPA View
Critical Render Path
CSS Critical Render Path
• CSS
• Style head CSS
•
• Universal JavaScript
Universal JavaScript
• isomorphic-style-loader
• Render style head
for react-router: https://goo.gl/PYYoLL
...
CSS Secret Lea Verou
CSS in JS ?
http://www.ituring.com.cn/article/261344
– Lea Verou, CSS Secret
If all you have is a hammer, everything looks like a nail.
Lea Verou


JavaScript
3D
HTML CSS
3D
CSS-Module
React-Native
3D
Universal JavaScript
Q&A

Universal JavaScript