universal js web applications with react - luciano mammino - codemotion rome 2017

60
Rome 24-25 MARCH 2017 { Universal JS Web Applications with React Luciano Mammino loige.link/codemotion-rome-2017 1

Upload: luciano-mammino

Post on 11-Apr-2017

21 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

Rome 24-25 MARCH 2017

{ Universal JS Web Applications with React

Luciano Mammino

loige.link/codemotion-rome-20171

Page 5: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

AGENDA

1. The term "Universal" JS

2. Who & Why

3. Common problems and technologies

4. Building a frontend only Single Page App

5. Making it universal

5

Page 6: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

ISOMORPHIC

loige.link/universal-js-story

UNIVERSAL WHAT?6

Page 7: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

NOT ONLYFOR THE WEB...

Desktop applications

Mobile applications

Hardware!

7

Page 8: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

ADVANTAGESOF UNIVERSAL JAVASCRIPT

"JavaScript-only" development

Maintainability

Better SEO

Faster "perceived" load time8

Page 9: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

ADVANTAGES...MORE

Keep using React/JS paradigms also to

generate "static" websites

Speed up content loading with

linkprefetch

loige.link/universal-react-made-easy-talk9

Page 10: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

IN THE WILD

10

Page 11: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

IT LOOKS GREAT BUT...

11

Page 13: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

UNIVERSAL RENDERING

Render the views of the application from

the server (first request) and then in the

browser (next requests)

13

Page 14: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

UNIVERSAL ROUTING

Recognise the view associated to the

current route from both the server and the

browser.

14

Page 15: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

UNIVERSAL DATA RETRIEVAL

Access data (and APIs) from both the server

and the browser.

AXIOS UNIVERSALFETCH

15

Page 16: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

UNIVERSAL STATEMANAGEMENT

Manage changes on the state tree both on

the server and the client...

16

Page 17: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

FUTURISTIC/ALTERNATIVE JS?!

17

Page 18: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

18

Page 19: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

OK...LET'S STOP COMPLAININGAND BUILD SOMETHING!

19

Page 20: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

WHAT ARE WEGOING TO BUILD?

loige.link/judo-heroes-app

loige.link/judo-heroes-tutorial

v 2.0

20

Page 21: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

21

Page 22: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

22

Page 23: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

23

Page 24: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

curl -sS "https://judo-heroes.herokuapp.com/athlete/teddy-riner"

24

Page 27: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

27

Page 28: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

The data set// src/data/athletes.js

const athletes = [ { id: 'driulis-gonzalez', name: 'Driulis González', country: { id: 'cu', name: 'Cuba', icon: 'flag-cu.png', }, birth: '1973', image: 'driulis-gonzalez.jpg', cover: 'driulis-gonzalez-cover.jpg', link: 'https://en.wikipedia.org/wiki/Driulis_González', medals: [ { id: 1, year: '1992', type: 'B', city: 'Barcelona', event: 'Olympic Games', category: { id: 2, year: '1993', type: 'B', city: 'Hamilton', event: 'World Championships', category: { id: 3, year: '1995', type: 'G', city: 'Chiba', event: 'World Championships', category: { id: 4, year: '1995', type: 'G', city: 'Mar del Plata', event: 'Pan American Games', { id: 5, year: '1996', type: 'G', city: 'Atlanta', event: 'Olympic Games', category: // ... ], }, // ...];

export default athletes;

28

Page 29: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

REACTCOMPONENTS

29

Page 30: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

Layout component

30

Page 31: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

IndexPage component

31

Page 32: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

AthletePage component

32

Page 33: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

NotFoundPage component

33

Page 34: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

AthletePreview component

34

Page 35: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

AthletesMenu component

35

Page 36: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

Flag component

36

Page 37: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

Medal component

37

Page 38: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

// src/components/Layout.js

import React from 'react';import { Link } from 'react-router-dom';

export const Layout = props => ( <div className="app-container"> <header> <Link to="/"> <img className="logo" src="/img/logo-judo-heroes.png" /> </Link> </header> <div className="app-content">{props.children}</div> <footer> <p> This is a demo app to showcase <strong>universal Javascript</strong> with <strong>React</strong> and <strong>Express</strong>. </p> </footer> </div>);

export default Layout;

38

Page 39: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

// src/components/IndexPage.js

import React from 'react';import { AthletePreview } from './AthletePreview';

export const IndexPage = ({ athletes }) => ( <div className="home"> <div className="athletes-selector"> { athletes.map( athleteData => <AthletePreview key={athleteData.id} {...athleteData} /> ) } </div> </div>);

export default IndexPage;39

Page 40: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

// src/components/AthletePreview.js

import React from 'react';import { Link } from 'react-router';

export const AthletePreview = (props) => ( <Link to={`/athlete/${props.id}`}> <div className="athlete-preview"> <img src={`img/${props.image}`}/> <h2 className="name">{props.name}</h2> <span className="medals-count"> <img src="/img/medal.png"/> {props.medals.length} </span> </div> </Link>);

export default AthletePreview;

40

Page 41: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

ROUTING

41

Page 42: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

2 ROUTES

Index Page: /

Athlete Page: /athlete/:id

42

Page 43: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

// src/components/App.js

import React from 'react';import { Route, Switch } from 'react-router-dom';import { Layout } from './Layout';import { IndexPage } from './IndexPage';import { AthletePage } from './AthletePage';import { NotFoundPage } from './NotFoundPage';import athletes from '../data/athletes';

// ...

export const App = () => ( <Layout> <Switch> <Route exact path="/" render={renderIndex} /> <Route exact path="/athlete/:id" render={renderAthlete} /> <Route component={NotFoundPage} /> </Switch> </Layout>);

export default App;

43

Page 44: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

// src/components/App.js

// ...

const renderIndex = () => <IndexPage athletes={athletes} />;

const renderAthlete = ({ match, staticContext }) => { const id = match.params.id; const athlete = athletes.find(current => current.id === id); if (!athlete) { return <NotFoundPage staticContext={staticContext} />; }

return <AthletePage athlete={athlete} athletes={athletes} />;};

44

Page 45: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

CLIENT APP

45

Page 46: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

// src/app-client.js

import React from 'react';import { render } from 'react-dom';import { BrowserRouter as Router } from 'react-router-dom'import { App } from './components/App';

const AppClient = () => ( <Router> <App /> </Router>);

window.onload = () => { render( <AppClient />, document.getElementById('main') );};

46

Page 47: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

HTML TEMPLATE

47

Page 48: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

// src/views/index.ejs

<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title> Judo Heroes - A Universal JavaScript demo application with React </title> <link rel="stylesheet" href="/css/style.css"> </head> <body> <div id="main"><%- markup -%></div> <script src="/js/bundle.js"></script> </body></html>

48

Page 49: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

BUILD CONFIG(BABEL + WEBPACK)

49

Page 50: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

.babelrc

import path from 'path';

const config = { entry: { js: './src/app-client.js', }, output: { path: path.join(__dirname, 'src', 'static', 'js'), filename: 'bundle.js', }, module: { rules: [ { test: path.join(__dirname, 'src'), use: { loader: 'babel-loader' }, }, ], },};

.webpack.config.babel.js

{ "presets": ["react", "es2015"]}

50

Page 51: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

LET'S BUILD IT!

51

Page 52: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

// src/server.js

import path from 'path';import { Server } from 'http';import Express from 'express';

const app = new Express();const server = new Server(app);

// use ejs templatesapp.set('view engine', 'ejs');app.set('views', path.join(__dirname, 'views'));

// define the folder that will be used for static assetsapp.use(Express.static(path.join(__dirname, 'static')));

// render the index for every non-matched routeapp.get('*', (req, res) => { let markup = ''; let status = 200; return res.status(status).render('index', { markup });});

// start the serverconst port = process.env.PORT || 3000;const env = process.env.NODE_ENV || 'production';server.listen(port);

"Static" Express server

52

Page 53: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

READY... LET'S TEST IT

53

Page 54: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

RECAPWhat we learned so far

1. Define views combining React components

2. Add routing using React Router

3. Compile the client bundle with Babel and

Webpack

4. Run the app with a static Express server54

Page 55: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

SERVER SIDERENDERING AND

ROUTING

55

Page 56: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

Updating the server app// ...import { renderToString } from 'react-dom/server';import { StaticRouter as Router } from 'react-router-dom';import { App } from './components/App';

// ...app.get('*', (req, res) => { let markup = ''; let status = 200;

const context = {}; markup = renderToString( <Router location={req.url} context={context}> <App /> </Router>, );

// context.url will contain the URL to // redirect to if a <Redirect> was used if (context.url) { return res.redirect(302, context.url); }

if (context.is404) { status = 404; }

return res.status(status).render('index', { markup });});

56

Page 57: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

THAT'S IT!

LET'S TEST AGAIN

57

Page 58: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

RECAPWhat we learned so far

1. Create a Single Page Application with

React and React Router

2. Add server side routing and rendering

using React and React Router libraries in the

Express app58

Page 59: Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome 2017

UNIVERSAL DATA RETRIEVAL

api-proxy & async-props(COMPLETE CHAPTER in )

UNIVERSAL STATE MANAGEMENT

Redux

Node.js Design Patterns

WHERE DO WE GOfrom here...

Code: loige.link/judo-heroes-2 59