76
Universal JavaScript ? 肬禂 SOHO 螲᪠螂 ݷ(Jerry-Hong)

Universal JavaScript

  • Upload
    -

  • View
    1.042

  • Download
    0

Embed Size (px)

Citation preview

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