Slide 1

Slide 1 text

LUCIANO MAMMINO UNIVERSAL JAVASCRIPT UNIVERSAL JAVASCRIPT LUCIANO MAMMINO loige.link/athens-2017 ATHENS, 27 MAY 2017 1

Slide 2

Slide 2 text

WHO IS LUCIANO lmammino loige loige.co mt. Etna Νάξος 2

Slide 3

Slide 3 text

NeBK20FUA -20% eBook NpBK15FUA -15% Print loige.link/node-book ⚡ ⚡CONTAINS A WHOLE CHAPTER ABOUT UNIVERSAL JAVASCRIPT ⚡ ⚡ GET A DISCOUNT ​ 3

Slide 4

Slide 4 text

fullstackbulletin.com 4

Slide 5

Slide 5 text

5

Slide 6

Slide 6 text

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" 6

Slide 7

Slide 7 text

ISOMORPHIC loige.link/universal-js-story UNIVERSAL... WAIT, WHAT? 7

Slide 8

Slide 8 text

NOT ONLY FOR THE WEB... Desktop applications Mobile applications Hardware! 8

Slide 9

Slide 9 text

ADVANTAGES OF UNIVERSAL JAVASCRIPT "JavaScript-only" development Maintainability Better SEO Faster "perceived" load time 9

Slide 10

Slide 10 text

ADVANTAGES... MOAR Keep using React/JS paradigms also for "static" websites Speed up content loading with linkprefetch loige.link/universal-react-made-easy-talk 10

Slide 11

Slide 11 text

IN THE WILD 11

Slide 12

Slide 12 text

IT LOOKS GREAT BUT... 12

Slide 13

Slide 13 text

MODULE SHARING Use Node.js modules in the browser UMD 13

Slide 14

Slide 14 text

UNIVERSAL RENDERING Render the views of the application from the server (first request) and then in the browser (next requests) 14

Slide 15

Slide 15 text

UNIVERSAL ROUTING Recognise the view associated to the current route from both the server and the browser. 15

Slide 16

Slide 16 text

UNIVERSAL DATA RETRIEVAL Access data (and APIs) from both the server and the browser. AXIOS UNIVERSAL FETCH 16

Slide 17

Slide 17 text

UNIVERSAL STATE MANAGEMENT Manage changes on the state tree both on the server and the client... 17

Slide 18

Slide 18 text

FUTURISTIC/ALTERNATIVE JS?! 18

Slide 19

Slide 19 text

19

Slide 20

Slide 20 text

OK... LET'S STOP COMPLAINING AND BUILD SOMETHING! 20

Slide 21

Slide 21 text

WHAT ARE WE GOING TO BUILD? loige.link/judo-heroes-app​ loige.link/judo-heroes-tutorial v 2.0 21

Slide 22

Slide 22 text

22

Slide 23

Slide 23 text

23

Slide 24

Slide 24 text

24

Slide 25

Slide 25 text

curl -sS "http://localhost:3000/athlete/teddy-riner" 25

Slide 26

Slide 26 text

WHAT TOOLS ARE WE GOING TO USE? v2 v15.4 v4 v5-alpha 26

Slide 28

Slide 28 text

28

Slide 29

Slide 29 text

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: '-57kg' }, { id: 2, year: '1993', type: 'B', city: 'Hamilton', event: 'World Championships', category: '-57kg' }, { id: 3, year: '1995', type: 'G', city: 'Chiba', event: 'World Championships', category: '-57kg' }, { id: 4, year: '1995', type: 'G', city: 'Mar del Plata', event: 'Pan American Games', category: '-57kg' }, { id: 5, year: '1996', type: 'G', city: 'Atlanta', event: 'Olympic Games', category: '-57kg' }, // ... ], }, // ... ]; export default athletes; 29

Slide 30

Slide 30 text

REACT COMPONENTS 30

Slide 31

Slide 31 text

Layout component 31

Slide 32

Slide 32 text

IndexPage component 32

Slide 33

Slide 33 text

AthletePage component 33

Slide 34

Slide 34 text

NotFoundPage component 34

Slide 35

Slide 35 text

AthletePreview component 35

Slide 36

Slide 36 text

AthletesMenu component 36

Slide 37

Slide 37 text

Flag component 37

Slide 38

Slide 38 text

Medal component 38

Slide 39

Slide 39 text

// src/components/Layout.js import React from 'react'; import { Link } from 'react-router-dom'; export const Layout = props => (
{props.children}

This is a demo app to showcase universal Javascript with React and Express.

); export default Layout; 39

Slide 40

Slide 40 text

// src/components/IndexPage.js import React from 'react'; import { AthletePreview } from './AthletePreview'; export const IndexPage = ({ athletes }) => (
{ athletes.map( athleteData => ) }
); export default IndexPage; 40

Slide 41

Slide 41 text

// src/components/AthletePreview.js import React from 'react'; import { Link } from 'react-router'; export const AthletePreview = (props) => (

{props.name}

{props.medals.length}
); export default AthletePreview; 41

Slide 42

Slide 42 text

ROUTING 42

Slide 43

Slide 43 text

2 ROUTES Index Page: / Athlete Page: /athlete/:id 43

Slide 44

Slide 44 text

// 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 = () => ( ); export default App; 44

Slide 45

Slide 45 text

// src/components/App.js // ... const renderIndex = () => ; const renderAthlete = ({ match, staticContext }) => { const id = match.params.id; const athlete = athletes.find(current => current.id === id); if (!athlete) { return ; } return ; }; 45

Slide 46

Slide 46 text

CLIENT APP 46

Slide 47

Slide 47 text

// 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 = () => ( ); window.onload = () => { render( , document.getElementById('main') ); }; 47

Slide 48

Slide 48 text

HTML TEMPLATE 48

Slide 49

Slide 49 text

// src/views/index.ejs Judo Heroes - A Universal JavaScript demo application with React
<%- markup -%>
49

Slide 50

Slide 50 text

BUILD CONFIG (BABEL + WEBPACK) 50

Slide 51

Slide 51 text

.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' }, }, ], }, }; export default config; .webpack.config.babel.js { "presets": ["react", "es2015"] } 51

Slide 52

Slide 52 text

LET'S BUILD IT! 52

Slide 53

Slide 53 text

// 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 templates app.set('view engine', 'ejs'); app.set('views', path.join(__dirname, 'views')); // define the folder that will be used for static assets app.use(Express.static(path.join(__dirname, 'static'))); // render the index for every non-matched route app.get('*', (req, res) => { let markup = ''; let status = 200; return res.status(status).render('index', { markup }); }); // start the server const port = process.env.PORT || 3000; const env = process.env.NODE_ENV || 'production'; server.listen(port); "Static" Express server 53

Slide 54

Slide 54 text

READY... LET'S TEST IT 54

Slide 55

Slide 55 text

RECAP What 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 server 55

Slide 56

Slide 56 text

SERVER SIDE RENDERING AND ROUTING 56

Slide 57

Slide 57 text

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( , ); // context.url will contain the URL to // redirect to if a was used if (context.url) { return res.redirect(302, context.url); } if (context.is404) { status = 404; } return res.status(status).render('index', { markup }); }); 57

Slide 58

Slide 58 text

THAT'S IT! LET'S TEST AGAIN 58

Slide 59

Slide 59 text

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 the Express app 59

Slide 60

Slide 60 text

UNIVERSAL DATA RETRIEVAL api-proxy & async-props (COMPLETE CHAPTER in ) UNIVERSAL STATE MANAGEMENT Redux PROGRESSIVE WEB APPS (PWA) + Node.js Design Patterns @addyosmani's tutorial Create React App WHERE DO WE GO from here... Code: loige.link/judo-heroes-2 60

Slide 61

Slide 61 text

THANKS! loige loige.co lmammino (Special thanks to , , Aleksandar Čambas & ) @cirpo @andreaman87 @quasi_modal loige.link/athens-2017​ 61