SlideShare a Scribd company logo
MILAN 25-26 NOVEMBER 2016
{ Universal JS Web Applications with React
Luciano Mammino
1
WHO IS
LUCIANO?
nodejsdesignpatterns.com
lmammino
loige
loige.co
2
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
3
ISOMORPHIC
bit.ly/universaljs
UNIVERSAL WHAT?
4
NOT ONLY
FOR THE WEB...
Desktop applications
Mobile applications
Hardware
5
ADVANTAGES
OF UNIVERSAL JAVASCRIPT
"JavaScript-only" development
Maintainability
Better SEO
Faster "perceived" load time
6
IN THE WILD
7
IT LOOKS GREAT BUT...
8
MODULE SHARING
Use Node.js modules in the browser.
UMD
9
UNIVERSAL RENDERING
Render the views of the application from
the server (first request) and then in the
browser (next requests)
10
UNIVERSAL ROUTING
Recognise the view associated to the
current route from both the server and the
browser.
11
UNIVERSAL DATA RETRIEVAL
Access data (and APIs) from both the server
and the browser.
AXIOS UNIVERSAL
FETCH
12
UNIVERSAL STATE
MANAGEMENT
Manage changes on the state tree both on
the server and the client...
13
FUTURISTIC/ALTERNATIVE JS?!
14
15
OK...
LET'S STOP COMPLAINING
AND BUILD SOMETHING!
16
WHAT TOOLS ARE
WE GOING TO USE?
17
WHAT ARE WE
GOING TO BUILD?
judo-heroes.herokuapp.com
bit.ly/judo-heroes-tutorial
18
19
20
21
curl -sS "https://judo-heroes.herokuapp.com/athlete/teddy-riner"
22
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': [
{ 'year': '1992', 'type': 'B', 'city': 'Barcelona', 'event': 'Olympic Games', 'category': '-57kg
{ 'year': '1993', 'type': 'B', 'city': 'Hamilton', 'event': 'World Championships', 'category': '
{ 'year': '1995', 'type': 'G', 'city': 'Chiba', 'event': 'World Championships', 'category': '-57
{ 'year': '1995', 'type': 'G', 'city': 'Mar del Plata', 'event': 'Pan American Games', 'category
{ 'year': '1996', 'type': 'G', 'city': 'Atlanta', 'event': 'Olympic Games', 'category': '-57kg'
// ...
],
},
// ...
];
export default athletes;
23
REACT
COMPONENTS
24
Layout component
25
// src/components/Layout.js
import React from 'react';
import { Link } from 'react-router';
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;
26
IndexPage component
27
// src/components/IndexPage.js
import React from 'react';
import AthletePreview from './AthletePreview';
import athletes from '../data/athletes';
const IndexPage = (props) => (
<div className="home">
<div className="athletes-selector">
{athletes.map(
athleteData => <AthletePreview
key={athleteData.id}
{...athleteData} />
)}
</div>
</div>
);
export default IndexPage;
28
AthletePreview component
29
// src/components/AthletePreview.js
import React from 'react';
import { Link } from 'react-router';
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;
30
AthletePage component
31
// src/components/AthletePage.js
import React from 'react';
import { Link } from 'react-router';
import NotFoundPage from './NotFoundPage';
import AthletesMenu from './AthletesMenu';
import Medal from './Medal';
import Flag from './Flag';
import athletes from '../data/athletes';
const AthletePage = (props) => {
const id = props.params.id;
const athlete = athletes.find((athlete) => athlete.id === id);
if (!athlete) {
return <NotFoundPage/>;
}
const headerStyle = { backgroundImage: `url(/img/${athlete.cover})` };
return (
<div className="athlete-full">
<AthletesMenu/>
<div className="athlete">
<header style={headerStyle}/>
<div className="picture-container">
<img src={`/img/${athlete.image}`}/>
<h2 className="name">{athlete.name}</h2>
</div>
<section className="description">
Olympic medalist from <strong><Flag {...athlete.country} showName="true"/></strong>,
born in {athlete.birth} (Find out more on <a href={athlete.link} target="_blank">Wikipedia</a>).
</section>
<section className="medals">
<p>Winner of <strong>{athlete.medals.length}</strong> medals:</p>
<ul>{
athlete.medals.map((medal, i) => <Medal key={i} {...medal}/>)
}</ul>
</section>
</div>
<div className="navigateBack">
<Link to="/">« Back to the index</Link>
</div>
</div>
);
};
export default AthletePage;
32
// src/components/AthletePage.js
// ...
const AthletePage = (props) => {
const id = props.params.id;
const athlete = athletes.find((athlete) => athlete.id === id);
if (!athlete) {
return <NotFoundPage/>;
}
const headerStyle = { backgroundImage: `url(/img/${athlete.cover})` };
return (
<div className="athlete-full">
<AthletesMenu/>
<div className="athlete">
<header style={headerStyle}/>
<div className="picture-container">
<img src={`/img/${athlete.image}`}/>
<h2 className="name">{athlete.name}</h2>
</div>
// ...
33
// src/components/AthletePage.js
// ...
<section className="description">
Olympic medalist from
<strong><Flag {...athlete.country} showName="true"/></strong>,
born in {athlete.birth}
(Find out more on <a href={athlete.link} target="_blank">Wikipedia</a>).
</section>
<section className="medals">
<p>Winner of <strong>{athlete.medals.length}</strong> medals:</p>
<ul>{
athlete.medals.map((medal, i) => <Medal key={i} {...medal}/>)
}</ul>
</section>
</div>
<div className="navigateBack">
<Link to="/">« Back to the index</Link>
</div>
</div>
);
};
export default AthletePage;
34
AthletesMenu component
35
// src/components/AthletesMenu.js
import React from 'react';
import { Link } from 'react-router';
import athletes from '../data/athletes';
const AthletesMenu = (props) => (
<nav className="atheletes-menu">
{athletes.map(athlete => {
return <Link key={athlete.id}
to={`/athlete/${athlete.id}`}
activeClassName="active">
{athlete.name}
</Link>;
})}
</nav>
);
export default AthletesMenu;
36
Flag component
37
// src/components/Flag.js
import React from 'react';
const Flag = (props) => (
<span className="flag">
<img className="icon"
title={props.name}
src={`/img/${props.icon}`}/>
{props.showName && <span className="name"> {props.name}</span>}
</span>
);
export default Flag;
38
Medal component
39
// src/components/Medal.js
import React from 'react';
const medalTypes = {
'G': 'Gold',
'S': 'Silver',
'B': 'Bronze'
};
const Medal = (props) => (
<li className="medal">
<span className={`symbol symbol-${props.type}`}
title={medalTypes[props.type]}>
{props.type}
</span>
<span className="year">{props.year}</span>
<span className="city"> {props.city}</span>
<span className="event"> ({props.event})</span>
<span className="category"> {props.category}</span>
</li>
);
export default Medal;
40
NotFoundPage component
// src/components/NotFoundPage.js
import React from 'react';
import { Link } from 'react-router';
const NotFoundPage = (props) => (
<div className="not-found">
<h1>404</h1>
<h2>Page not found!</h2>
<p>
<Link to="/">Go back to the main page</Link>
</p>
</div>
);
export default NotFoundPage;
41
ROUTING
42
2 ROUTES
Index Page: /
Athlete Page: /athlete/:id
43
// src/Routes.js
import React from 'react';
import { Route, IndexRoute } from 'react-router'
import Layout from './components/Layout';
import IndexPage from './components/IndexPage';
import AthletePage from './components/AthletePage';
import NotFoundPage from './components/NotFoundPage';
const routes = (
<Route path="/" component={Layout}>
<IndexRoute component={IndexPage}/>
<Route path="athlete/:id" component={AthletePage}/>
<Route path="*" component={NotFoundPage}/>
</Route>
);
export default routes;
44
// src/components/AppRoutes.js
import React from 'react';
import { Router, hashHistory } from 'react-router';
import routes from '../Routes';
const AppRoutes = (props) => (
<Router history={hashHistory}
routes={routes}
onUpdate={() => window.scrollTo(0, 0)}/>
);
export default AppRoutes;
45
CLIENT APP
46
// src/app-client.js
import React from 'react';
import ReactDOM from 'react-dom';
import AppRoutes from './components/AppRoutes';
window.onload = () => {
ReactDOM.render(<AppRoutes/>,
document.getElementById('main'));
};
47
HTML WRAPPER
48
// src/static/index.html
<!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"></div>
<script src="/js/bundle.js"></script>
</body>
</html>
49
BUILD CONFIG
(BABEL + WEBPACK)
50
.babelrc
import webpack from 'webpack';
import path from 'path';
const config = {
entry: { js: './src/app-client.js' },
output: {
path: path.join(__dirname, 'src', 'static', 'js'),
filename: 'bundle.js'
},
module: {
loaders: [{
test: path.join(__dirname, 'src'),
loaders: [{ loader: 'babel-loader' }]
}]
},
};
export default config;
.webpack.config.babel.js
{
"presets": ["react", "es2015"]
}
51
LET'S BUILD IT!
52
// src/server.js
import path from 'path';
import { Server } from 'http';
import Express from 'express';
const app = new Express();
const server = new Server(app);
// define the folder that will be used for static assets
app.use(Express.static(path.join(__dirname, 'static')));
// start the server
const port = process.env.PORT || 3000;
const env = process.env.NODE_ENV || 'production';
server.listen(port, err => {
if (err) {
return console.error(err);
}
console.info(`Server running on http://localhost:${port} [${env}]`);
});
Static Express server
53
READY... LET'S TEST IT
54
RECAP
What we learned so far
1. Define views combining React components
2. Add Routing using React Router
3. Compiling our frontend bundle with Babel
and Webpack
4. Run the app with a static Express server
55
SERVER SIDE
RENDERING AND
ROUTING
56
Using browser history
57
// 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>
Converting static index.html into a template
58
Updating the server app
59
// ...
// universal routing and rendering
app.get('*', (req, res) => {
match(
{ routes, location: req.url },
(err, redirectLocation, renderProps) => {
// in case of error display the error message
if (err) {
return res.status(500).send(err.message);
}
// in case of redirect propagate the redirect to the browser
if (redirectLocation) {
return res.redirect(302, redirectLocation.pathname +
redirectLocation.search);
}
// generate the React markup for the current route
let markup;
if (renderProps) {
// if the current route matched we have renderProps
markup = renderToString(<RouterContext {...renderProps}/>);
} else {
// otherwise we can render a 404 page
markup = renderToString(<NotFoundPage/>);
res.status(404);
}
// render the index template with the embedded React markup
return res.render('index', { markup });
}
);
}); 60
THAT'S IT!
LET'S TEST AGAIN
61
RECAP
What 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 out
Express app
62
UNIVERSAL DATA RETRIEVAL
api-proxy & async-props
(COMPLETE CHAPTER in )
UNIVERSAL STATE MANAGEMENT
Redux
Node.js Design Patterns
WHERE DO WE GO
from here...
Code: https://github.com/lmammino/judo-heroes-2
63
THANKS!
loige loige.colmammino
(Special thanks to , , Aleksandar Čambas & )@cirpo @andreaman87 @quasi_modal
64

More Related Content

What's hot (20)

ODP
AngularJs Crash Course
Keith Bloomfield
 
PPTX
Angular2 + rxjs
Christoffer Noring
 
PDF
Angular2 - In Action
Sebastian Pożoga
 
PDF
AngularJS - Services
Nir Kaufman
 
PDF
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Ontico
 
PDF
Angular2 & ngrx/store: Game of States
Oren Farhi
 
PPTX
Migrating an application from Angular 1 to Angular 2
Ross Dederer
 
PPTX
Angular js
Behind D Walls
 
PDF
Solid angular
Nir Kaufman
 
PDF
An introduction to Angular2
Apptension
 
PPTX
Angular 5
Bartłomiej Narożnik
 
PDF
Angular2 workshop
Nir Kaufman
 
PDF
Ultimate Introduction To AngularJS
Jacopo Nardiello
 
PDF
Angular server side rendering - Strategies & Technics
Eliran Eliassy
 
PDF
Angular 2: core concepts
Codemotion
 
PDF
Workshop 26: React Native - The Native Side
Visual Engineering
 
PDF
AngularJS - Overcoming performance issues. Limits.
Dragos Mihai Rusu
 
PPTX
Angular 2.0 Dependency injection
Eyal Vardi
 
PDF
React on es6+
Nikolaus Graf
 
PPTX
Angular2 and TypeScript
David Giard
 
AngularJs Crash Course
Keith Bloomfield
 
Angular2 + rxjs
Christoffer Noring
 
Angular2 - In Action
Sebastian Pożoga
 
AngularJS - Services
Nir Kaufman
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Ontico
 
Angular2 & ngrx/store: Game of States
Oren Farhi
 
Migrating an application from Angular 1 to Angular 2
Ross Dederer
 
Angular js
Behind D Walls
 
Solid angular
Nir Kaufman
 
An introduction to Angular2
Apptension
 
Angular2 workshop
Nir Kaufman
 
Ultimate Introduction To AngularJS
Jacopo Nardiello
 
Angular server side rendering - Strategies & Technics
Eliran Eliassy
 
Angular 2: core concepts
Codemotion
 
Workshop 26: React Native - The Native Side
Visual Engineering
 
AngularJS - Overcoming performance issues. Limits.
Dragos Mihai Rusu
 
Angular 2.0 Dependency injection
Eyal Vardi
 
React on es6+
Nikolaus Graf
 
Angular2 and TypeScript
David Giard
 

Viewers also liked (20)

PDF
How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
Codemotion
 
PDF
Come rendere il proprio prodotto una bomba creandogli una intera community in...
Codemotion
 
PDF
Milano Chatbots Meetup - Vittorio Banfi - Bot Design - Codemotion Milan 2016
Codemotion
 
PPTX
DevOps in Cloud, dai Container all'approccio Codeless - Gabriele Provinciali,...
Codemotion
 
PDF
Games of Simplicity - Pozzi; Molinari - Codemotion Milan 2016
Codemotion
 
PDF
Lo sviluppo di Edge Guardian VR - Maurizio Tatafiore - Codemotion Milan 2016
Codemotion
 
PDF
Developing apps for developing countries - Natalie Pistunovich - Codemotion M...
Codemotion
 
PDF
How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016
Codemotion
 
PDF
Hacking for Salone: Drone Races - Di Saverio; Lippolis - Codemotion Milan 2016
Codemotion
 
PDF
Lo sviluppo di Edge Guardian VR - Marco Giammetti - Codemotion Milan 2016
Codemotion
 
PDF
Getting started with go - Florin Patan - Codemotion Milan 2016
Codemotion
 
PDF
Cyber Analysts: who they are, what they do, where they are - Marco Ramilli - ...
Codemotion
 
PPTX
Master the chaos: from raw data to analytics - Andrea Pompili, Riccardo Rossi...
Codemotion
 
PDF
Progressive Web Apps: trick or real magic? - Maurizio Mangione - Codemotion M...
Codemotion
 
PDF
The (almost) lost art of Smalltalk - Nikolas Martens - Codemotion Milan 2016
Codemotion
 
PDF
The hitchhiker's guide to UXing without a UXer - Chrissy Welsh - Codemotion M...
Codemotion
 
PDF
A-Frame in the Virtual World, small bricks of virtual reality web - Giovanni ...
Codemotion
 
PPTX
Sviluppare applicazioni nell'era dei "Big Data" con Scala e Spark - Mario Car...
Codemotion
 
PDF
The Evolution of Asynchronous Javascript - Alessandro Cinelli - Codemotion Mi...
Codemotion
 
PDF
Big Data, Small Dashboard - Andrea Maietta - Codemotion Milan 2016
Codemotion
 
How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
Codemotion
 
Come rendere il proprio prodotto una bomba creandogli una intera community in...
Codemotion
 
Milano Chatbots Meetup - Vittorio Banfi - Bot Design - Codemotion Milan 2016
Codemotion
 
DevOps in Cloud, dai Container all'approccio Codeless - Gabriele Provinciali,...
Codemotion
 
Games of Simplicity - Pozzi; Molinari - Codemotion Milan 2016
Codemotion
 
Lo sviluppo di Edge Guardian VR - Maurizio Tatafiore - Codemotion Milan 2016
Codemotion
 
Developing apps for developing countries - Natalie Pistunovich - Codemotion M...
Codemotion
 
How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016
Codemotion
 
Hacking for Salone: Drone Races - Di Saverio; Lippolis - Codemotion Milan 2016
Codemotion
 
Lo sviluppo di Edge Guardian VR - Marco Giammetti - Codemotion Milan 2016
Codemotion
 
Getting started with go - Florin Patan - Codemotion Milan 2016
Codemotion
 
Cyber Analysts: who they are, what they do, where they are - Marco Ramilli - ...
Codemotion
 
Master the chaos: from raw data to analytics - Andrea Pompili, Riccardo Rossi...
Codemotion
 
Progressive Web Apps: trick or real magic? - Maurizio Mangione - Codemotion M...
Codemotion
 
The (almost) lost art of Smalltalk - Nikolas Martens - Codemotion Milan 2016
Codemotion
 
The hitchhiker's guide to UXing without a UXer - Chrissy Welsh - Codemotion M...
Codemotion
 
A-Frame in the Virtual World, small bricks of virtual reality web - Giovanni ...
Codemotion
 
Sviluppare applicazioni nell'era dei "Big Data" con Scala e Spark - Mario Car...
Codemotion
 
The Evolution of Asynchronous Javascript - Alessandro Cinelli - Codemotion Mi...
Codemotion
 
Big Data, Small Dashboard - Andrea Maietta - Codemotion Milan 2016
Codemotion
 
Ad

Similar to Universal JavaScript Web Applications with React - Luciano Mammino - Codemotion Milan 2016 (20)

PDF
Universal JavaScript - Frontend United Athens 2017
Luciano Mammino
 
PDF
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Codemotion
 
PDF
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Luciano Mammino
 
PDF
Stay with React.js in 2020
Jerry Liao
 
PDF
Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...
Luciano Mammino
 
PDF
Introduction to React JS
Bethmi Gunasekara
 
PDF
Why react matters
ShihChi Huang
 
PDF
2- Components.pdf
jibreelkhan2
 
PDF
Basic Tutorial of React for Programmers
David Rodenas
 
PDF
The road-to-learn-react
imdurgesh
 
PPTX
Up and Running with ReactJS
Loc Nguyen
 
PPTX
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
Karmanjay Verma
 
PDF
React Best Practices All Developers Should Follow in 2024.pdf
BOSC Tech Labs
 
PPTX
thinking in react slides for students.pptx
AneesLarik1
 
PDF
React js notes for professionals
Zafer Galip Ozberk
 
PPTX
React for JavaScipt Introduction and functions
MaithiliGogteParanja
 
PDF
React: JSX and Top Level API
Fabio Biondi
 
PPTX
The productive developer guide to React
Maurice De Beijer [MVP]
 
PDF
Simple React Todo List
Ritesh Chaudhari
 
PPTX
slides.pptx
HafidzIhzaPratama
 
Universal JavaScript - Frontend United Athens 2017
Luciano Mammino
 
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Codemotion
 
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Luciano Mammino
 
Stay with React.js in 2020
Jerry Liao
 
Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...
Luciano Mammino
 
Introduction to React JS
Bethmi Gunasekara
 
Why react matters
ShihChi Huang
 
2- Components.pdf
jibreelkhan2
 
Basic Tutorial of React for Programmers
David Rodenas
 
The road-to-learn-react
imdurgesh
 
Up and Running with ReactJS
Loc Nguyen
 
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
Karmanjay Verma
 
React Best Practices All Developers Should Follow in 2024.pdf
BOSC Tech Labs
 
thinking in react slides for students.pptx
AneesLarik1
 
React js notes for professionals
Zafer Galip Ozberk
 
React for JavaScipt Introduction and functions
MaithiliGogteParanja
 
React: JSX and Top Level API
Fabio Biondi
 
The productive developer guide to React
Maurice De Beijer [MVP]
 
Simple React Todo List
Ritesh Chaudhari
 
slides.pptx
HafidzIhzaPratama
 
Ad

More from Codemotion (20)

PDF
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Codemotion
 
PDF
Pompili - From hero to_zero: The FatalNoise neverending story
Codemotion
 
PPTX
Pastore - Commodore 65 - La storia
Codemotion
 
PPTX
Pennisi - Essere Richard Altwasser
Codemotion
 
PPTX
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Codemotion
 
PPTX
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Codemotion
 
PPTX
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Codemotion
 
PPTX
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Codemotion
 
PDF
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Codemotion
 
PDF
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Codemotion
 
PDF
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Codemotion
 
PDF
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Codemotion
 
PDF
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Codemotion
 
PDF
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Codemotion
 
PPTX
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Codemotion
 
PPTX
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
Codemotion
 
PDF
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Codemotion
 
PDF
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Codemotion
 
PDF
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Codemotion
 
PDF
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Codemotion
 
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Codemotion
 
Pompili - From hero to_zero: The FatalNoise neverending story
Codemotion
 
Pastore - Commodore 65 - La storia
Codemotion
 
Pennisi - Essere Richard Altwasser
Codemotion
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Codemotion
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Codemotion
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Codemotion
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Codemotion
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Codemotion
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Codemotion
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Codemotion
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Codemotion
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Codemotion
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Codemotion
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Codemotion
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
Codemotion
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Codemotion
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Codemotion
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Codemotion
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Codemotion
 

Recently uploaded (20)

PDF
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
PDF
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
PDF
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
PDF
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
PDF
The 2025 InfraRed Report - Redpoint Ventures
Razin Mustafiz
 
PDF
Peak of Data & AI Encore AI-Enhanced Workflows for the Real World
Safe Software
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PPTX
Designing_the_Future_AI_Driven_Product_Experiences_Across_Devices.pptx
presentifyai
 
PDF
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
PDF
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
PPTX
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
PPTX
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
PDF
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
PDF
Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
PDF
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
DOCX
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
PDF
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PDF
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
PDF
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
The 2025 InfraRed Report - Redpoint Ventures
Razin Mustafiz
 
Peak of Data & AI Encore AI-Enhanced Workflows for the Real World
Safe Software
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
Designing_the_Future_AI_Driven_Product_Experiences_Across_Devices.pptx
presentifyai
 
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 

Universal JavaScript Web Applications with React - Luciano Mammino - Codemotion Milan 2016

  • 1. MILAN 25-26 NOVEMBER 2016 { Universal JS Web Applications with React Luciano Mammino 1
  • 3. 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 3
  • 5. NOT ONLY FOR THE WEB... Desktop applications Mobile applications Hardware 5
  • 6. ADVANTAGES OF UNIVERSAL JAVASCRIPT "JavaScript-only" development Maintainability Better SEO Faster "perceived" load time 6
  • 8. IT LOOKS GREAT BUT... 8
  • 9. MODULE SHARING Use Node.js modules in the browser. UMD 9
  • 10. UNIVERSAL RENDERING Render the views of the application from the server (first request) and then in the browser (next requests) 10
  • 11. UNIVERSAL ROUTING Recognise the view associated to the current route from both the server and the browser. 11
  • 12. UNIVERSAL DATA RETRIEVAL Access data (and APIs) from both the server and the browser. AXIOS UNIVERSAL FETCH 12
  • 13. UNIVERSAL STATE MANAGEMENT Manage changes on the state tree both on the server and the client... 13
  • 15. 15
  • 16. OK... LET'S STOP COMPLAINING AND BUILD SOMETHING! 16
  • 17. WHAT TOOLS ARE WE GOING TO USE? 17
  • 18. WHAT ARE WE GOING TO BUILD? judo-heroes.herokuapp.com bit.ly/judo-heroes-tutorial 18
  • 19. 19
  • 20. 20
  • 21. 21
  • 23. 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': [ { 'year': '1992', 'type': 'B', 'city': 'Barcelona', 'event': 'Olympic Games', 'category': '-57kg { 'year': '1993', 'type': 'B', 'city': 'Hamilton', 'event': 'World Championships', 'category': ' { 'year': '1995', 'type': 'G', 'city': 'Chiba', 'event': 'World Championships', 'category': '-57 { 'year': '1995', 'type': 'G', 'city': 'Mar del Plata', 'event': 'Pan American Games', 'category { 'year': '1996', 'type': 'G', 'city': 'Atlanta', 'event': 'Olympic Games', 'category': '-57kg' // ... ], }, // ... ]; export default athletes; 23
  • 26. // src/components/Layout.js import React from 'react'; import { Link } from 'react-router'; 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; 26
  • 28. // src/components/IndexPage.js import React from 'react'; import AthletePreview from './AthletePreview'; import athletes from '../data/athletes'; const IndexPage = (props) => ( <div className="home"> <div className="athletes-selector"> {athletes.map( athleteData => <AthletePreview key={athleteData.id} {...athleteData} /> )} </div> </div> ); export default IndexPage; 28
  • 30. // src/components/AthletePreview.js import React from 'react'; import { Link } from 'react-router'; 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; 30
  • 32. // src/components/AthletePage.js import React from 'react'; import { Link } from 'react-router'; import NotFoundPage from './NotFoundPage'; import AthletesMenu from './AthletesMenu'; import Medal from './Medal'; import Flag from './Flag'; import athletes from '../data/athletes'; const AthletePage = (props) => { const id = props.params.id; const athlete = athletes.find((athlete) => athlete.id === id); if (!athlete) { return <NotFoundPage/>; } const headerStyle = { backgroundImage: `url(/img/${athlete.cover})` }; return ( <div className="athlete-full"> <AthletesMenu/> <div className="athlete"> <header style={headerStyle}/> <div className="picture-container"> <img src={`/img/${athlete.image}`}/> <h2 className="name">{athlete.name}</h2> </div> <section className="description"> Olympic medalist from <strong><Flag {...athlete.country} showName="true"/></strong>, born in {athlete.birth} (Find out more on <a href={athlete.link} target="_blank">Wikipedia</a>). </section> <section className="medals"> <p>Winner of <strong>{athlete.medals.length}</strong> medals:</p> <ul>{ athlete.medals.map((medal, i) => <Medal key={i} {...medal}/>) }</ul> </section> </div> <div className="navigateBack"> <Link to="/">« Back to the index</Link> </div> </div> ); }; export default AthletePage; 32
  • 33. // src/components/AthletePage.js // ... const AthletePage = (props) => { const id = props.params.id; const athlete = athletes.find((athlete) => athlete.id === id); if (!athlete) { return <NotFoundPage/>; } const headerStyle = { backgroundImage: `url(/img/${athlete.cover})` }; return ( <div className="athlete-full"> <AthletesMenu/> <div className="athlete"> <header style={headerStyle}/> <div className="picture-container"> <img src={`/img/${athlete.image}`}/> <h2 className="name">{athlete.name}</h2> </div> // ... 33
  • 34. // src/components/AthletePage.js // ... <section className="description"> Olympic medalist from <strong><Flag {...athlete.country} showName="true"/></strong>, born in {athlete.birth} (Find out more on <a href={athlete.link} target="_blank">Wikipedia</a>). </section> <section className="medals"> <p>Winner of <strong>{athlete.medals.length}</strong> medals:</p> <ul>{ athlete.medals.map((medal, i) => <Medal key={i} {...medal}/>) }</ul> </section> </div> <div className="navigateBack"> <Link to="/">« Back to the index</Link> </div> </div> ); }; export default AthletePage; 34
  • 36. // src/components/AthletesMenu.js import React from 'react'; import { Link } from 'react-router'; import athletes from '../data/athletes'; const AthletesMenu = (props) => ( <nav className="atheletes-menu"> {athletes.map(athlete => { return <Link key={athlete.id} to={`/athlete/${athlete.id}`} activeClassName="active"> {athlete.name} </Link>; })} </nav> ); export default AthletesMenu; 36
  • 38. // src/components/Flag.js import React from 'react'; const Flag = (props) => ( <span className="flag"> <img className="icon" title={props.name} src={`/img/${props.icon}`}/> {props.showName && <span className="name"> {props.name}</span>} </span> ); export default Flag; 38
  • 40. // src/components/Medal.js import React from 'react'; const medalTypes = { 'G': 'Gold', 'S': 'Silver', 'B': 'Bronze' }; const Medal = (props) => ( <li className="medal"> <span className={`symbol symbol-${props.type}`} title={medalTypes[props.type]}> {props.type} </span> <span className="year">{props.year}</span> <span className="city"> {props.city}</span> <span className="event"> ({props.event})</span> <span className="category"> {props.category}</span> </li> ); export default Medal; 40
  • 41. NotFoundPage component // src/components/NotFoundPage.js import React from 'react'; import { Link } from 'react-router'; const NotFoundPage = (props) => ( <div className="not-found"> <h1>404</h1> <h2>Page not found!</h2> <p> <Link to="/">Go back to the main page</Link> </p> </div> ); export default NotFoundPage; 41
  • 43. 2 ROUTES Index Page: / Athlete Page: /athlete/:id 43
  • 44. // src/Routes.js import React from 'react'; import { Route, IndexRoute } from 'react-router' import Layout from './components/Layout'; import IndexPage from './components/IndexPage'; import AthletePage from './components/AthletePage'; import NotFoundPage from './components/NotFoundPage'; const routes = ( <Route path="/" component={Layout}> <IndexRoute component={IndexPage}/> <Route path="athlete/:id" component={AthletePage}/> <Route path="*" component={NotFoundPage}/> </Route> ); export default routes; 44
  • 45. // src/components/AppRoutes.js import React from 'react'; import { Router, hashHistory } from 'react-router'; import routes from '../Routes'; const AppRoutes = (props) => ( <Router history={hashHistory} routes={routes} onUpdate={() => window.scrollTo(0, 0)}/> ); export default AppRoutes; 45
  • 47. // src/app-client.js import React from 'react'; import ReactDOM from 'react-dom'; import AppRoutes from './components/AppRoutes'; window.onload = () => { ReactDOM.render(<AppRoutes/>, document.getElementById('main')); }; 47
  • 49. // src/static/index.html <!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"></div> <script src="/js/bundle.js"></script> </body> </html> 49
  • 50. BUILD CONFIG (BABEL + WEBPACK) 50
  • 51. .babelrc import webpack from 'webpack'; import path from 'path'; const config = { entry: { js: './src/app-client.js' }, output: { path: path.join(__dirname, 'src', 'static', 'js'), filename: 'bundle.js' }, module: { loaders: [{ test: path.join(__dirname, 'src'), loaders: [{ loader: 'babel-loader' }] }] }, }; export default config; .webpack.config.babel.js { "presets": ["react", "es2015"] } 51
  • 53. // src/server.js import path from 'path'; import { Server } from 'http'; import Express from 'express'; const app = new Express(); const server = new Server(app); // define the folder that will be used for static assets app.use(Express.static(path.join(__dirname, 'static'))); // start the server const port = process.env.PORT || 3000; const env = process.env.NODE_ENV || 'production'; server.listen(port, err => { if (err) { return console.error(err); } console.info(`Server running on http://localhost:${port} [${env}]`); }); Static Express server 53
  • 55. RECAP What we learned so far 1. Define views combining React components 2. Add Routing using React Router 3. Compiling our frontend bundle with Babel and Webpack 4. Run the app with a static Express server 55
  • 58. // 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> Converting static index.html into a template 58
  • 60. // ... // universal routing and rendering app.get('*', (req, res) => { match( { routes, location: req.url }, (err, redirectLocation, renderProps) => { // in case of error display the error message if (err) { return res.status(500).send(err.message); } // in case of redirect propagate the redirect to the browser if (redirectLocation) { return res.redirect(302, redirectLocation.pathname + redirectLocation.search); } // generate the React markup for the current route let markup; if (renderProps) { // if the current route matched we have renderProps markup = renderToString(<RouterContext {...renderProps}/>); } else { // otherwise we can render a 404 page markup = renderToString(<NotFoundPage/>); res.status(404); } // render the index template with the embedded React markup return res.render('index', { markup }); } ); }); 60
  • 62. RECAP What 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 out Express app 62
  • 63. UNIVERSAL DATA RETRIEVAL api-proxy & async-props (COMPLETE CHAPTER in ) UNIVERSAL STATE MANAGEMENT Redux Node.js Design Patterns WHERE DO WE GO from here... Code: https://github.com/lmammino/judo-heroes-2 63
  • 64. THANKS! loige loige.colmammino (Special thanks to , , Aleksandar Čambas & )@cirpo @andreaman87 @quasi_modal 64