Slide 1

Slide 1 text

~ Julien Phalip Confident Web Development With React September, 9th, 2015 DJANGOCON 2015 - AUSTIN, TX

Slide 2

Slide 2 text

CONNECTED PERSONAL OBJECTS 5/2012 About me... ‣ Worked with Django since 2007 (v 0.96). ‣ Django core committer since 2011. ‣ @julienphalip

Slide 3

Slide 3 text

CONNECTED PERSONAL OBJECTS 5/2012 www.nurun.com

Slide 4

Slide 4 text

CONNECTED PERSONAL OBJECTS 5/2012 About this talk…

Slide 5

Slide 5 text

CONNECTED PERSONAL OBJECTS 5/2012 About this talk… ‣ Basic principles of Flux & React. ‣ Examples of how Django & React may work together.

Slide 6

Slide 6 text

CONNECTED PERSONAL OBJECTS 5/2012 Flux: Unidirectional
 data flow

Slide 7

Slide 7 text

CONNECTED PERSONAL OBJECTS 5/2012 Flux: Unidirectional
 data flow Action

Slide 8

Slide 8 text

CONNECTED PERSONAL OBJECTS 5/2012 Flux: Unidirectional
 data flow Action Dispatcher

Slide 9

Slide 9 text

CONNECTED PERSONAL OBJECTS 5/2012 Flux: Unidirectional
 data flow Action Dispatcher Store

Slide 10

Slide 10 text

CONNECTED PERSONAL OBJECTS 5/2012 View Flux: Unidirectional
 data flow Action Dispatcher Store

Slide 11

Slide 11 text

CONNECTED PERSONAL OBJECTS 5/2012 View Flux: Unidirectional
 data flow Action Sub-view Sub-view Sub-view Dispatcher Store

Slide 12

Slide 12 text

CONNECTED PERSONAL OBJECTS 5/2012 View Flux: Unidirectional
 data flow Action Sub-view Sub-view Action Sub-view Dispatcher Store

Slide 13

Slide 13 text

CONNECTED PERSONAL OBJECTS 5/2012 View Flux: Unidirectional
 data flow Action Sub-view Sub-view Action Sub-view Dispatcher Store

Slide 14

Slide 14 text

CONNECTED PERSONAL OBJECTS 5/2012 View Flux: Unidirectional
 data flow Action Sub-view Sub-view Action Sub-view Dispatcher Store

Slide 15

Slide 15 text

CONNECTED PERSONAL OBJECTS 5/2012 View Flux: Unidirectional
 data flow React Action Sub-view Sub-view Action Sub-view Dispatcher Store

Slide 16

Slide 16 text

CONNECTED PERSONAL OBJECTS 5/2012 Advantages of Flux

Slide 17

Slide 17 text

CONNECTED PERSONAL OBJECTS 5/2012 Advantages of Flux ‣ Streamlined rendering process.

Slide 18

Slide 18 text

CONNECTED PERSONAL OBJECTS 5/2012 Advantages of Flux ‣ Streamlined rendering process. ‣ Reduced cognitive load.

Slide 19

Slide 19 text

CONNECTED PERSONAL OBJECTS 5/2012 Advantages of Flux ‣ Streamlined rendering process. ‣ Reduced cognitive load. ‣ Simpler codebase.

Slide 20

Slide 20 text

CONNECTED PERSONAL OBJECTS 5/2012 Advantages of Flux ‣ Streamlined rendering process. ‣ Reduced cognitive load. ‣ Simpler codebase. ‣ Consistent, predictable behaviors.

Slide 21

Slide 21 text

CONNECTED PERSONAL OBJECTS 5/2012 Advantages of React

Slide 22

Slide 22 text

CONNECTED PERSONAL OBJECTS 5/2012 Advantages of React ‣ Abstracts the DOM with components.

Slide 23

Slide 23 text

CONNECTED PERSONAL OBJECTS 5/2012 Advantages of React ‣ Abstracts the DOM with components. ‣ Handles DOM mutations automatically.

Slide 24

Slide 24 text

CONNECTED PERSONAL OBJECTS 5/2012 Advantages of React ‣ Abstracts the DOM with components. ‣ Handles DOM mutations automatically. ‣ Agnostic about the rest of the stack.

Slide 25

Slide 25 text

CONNECTED PERSONAL OBJECTS 5/2012 Simple demo app ‣ Display list of photos ‣ User can select their favorite photos

Slide 26

Slide 26 text

CONNECTED PERSONAL OBJECTS 5/2012 A simple React-Django integration

Slide 27

Slide 27 text

CONNECTED PERSONAL OBJECTS 5/2012 A simple React-Django integration ‣ Django provides a REST API that serves as a gateway for accessing & manipulating data.

Slide 28

Slide 28 text

CONNECTED PERSONAL OBJECTS 5/2012 A simple React-Django integration ‣ Django provides a REST API that serves as a gateway for accessing & manipulating data. ‣ React renders the UI client-side and handles user interactions.

Slide 29

Slide 29 text

CONNECTED PERSONAL OBJECTS 5/2012 Client-server interaction

Slide 30

Slide 30 text

CONNECTED PERSONAL OBJECTS 5/2012 Client-server interaction Client React renders
 the page

Slide 31

Slide 31 text

CONNECTED PERSONAL OBJECTS 5/2012 Client-server interaction Client User clicks
 a photo React renders
 the page

Slide 32

Slide 32 text

CONNECTED PERSONAL OBJECTS 5/2012 Client-server interaction Client Server (Django) User clicks
 a photo React renders
 the page POST request

Slide 33

Slide 33 text

CONNECTED PERSONAL OBJECTS 5/2012 Client-server interaction Client Server (Django) User clicks
 a photo Updates the database React renders
 the page POST request

Slide 34

Slide 34 text

CONNECTED PERSONAL OBJECTS 5/2012 Client-server interaction Client Server (Django) User clicks
 a photo Updates the database Serializes
 current data React renders
 the page POST request

Slide 35

Slide 35 text

CONNECTED PERSONAL OBJECTS 5/2012 Client-server interaction Client Server (Django) User clicks
 a photo Updates the database Serializes
 current data React renders
 the page POST request Current data

Slide 36

Slide 36 text

CONNECTED PERSONAL OBJECTS 5/2012 Client-server interaction Client Server (Django) User clicks
 a photo Updates the database Serializes
 current data React renders
 the page POST request Current data React (re-)renders the page

Slide 37

Slide 37 text

CONNECTED PERSONAL OBJECTS 5/2012 Client-server interaction Client Server (Django) User clicks
 a photo Updates the database Serializes
 current data React renders
 the page POST request Current data React (re-)renders the page

Slide 38

Slide 38 text

CONNECTED PERSONAL OBJECTS 5/2012 Initial client-side store hydration

Slide 39

Slide 39 text

CONNECTED PERSONAL OBJECTS 5/2012 Initial client-side store hydration ‣ Conventional method:
 Client fetches data via Ajax after initial page load.

Slide 40

Slide 40 text

CONNECTED PERSONAL OBJECTS 5/2012 Initial client-side store hydration ‣ Conventional method:
 Client fetches data via Ajax after initial page load. ‣ Less conventional method:
 Server serializes data as global Javascript variable in the initial HTML payload (see Instagram).

Slide 41

Slide 41 text

CONNECTED PERSONAL OBJECTS 5/2012 …Live demo… https://github.com/jphalip/django-react-djangocon2015

Slide 42

Slide 42 text

CONNECTED PERSONAL OBJECTS 5/2012 Server-side rendering

Slide 43

Slide 43 text

CONNECTED PERSONAL OBJECTS 5/2012 Server-side rendering ‣ Advantages:

Slide 44

Slide 44 text

CONNECTED PERSONAL OBJECTS 5/2012 Server-side rendering ‣ Advantages: ‣ SEO-friendly

Slide 45

Slide 45 text

CONNECTED PERSONAL OBJECTS 5/2012 Server-side rendering ‣ Advantages: ‣ SEO-friendly ‣ Less resource intensive for the client

Slide 46

Slide 46 text

CONNECTED PERSONAL OBJECTS 5/2012 Server-side rendering ‣ Advantages: ‣ SEO-friendly ‣ Less resource intensive for the client ‣ First page is immediately consumable

Slide 47

Slide 47 text

CONNECTED PERSONAL OBJECTS 5/2012 Server-side rendering ‣ Advantages: ‣ SEO-friendly ‣ Less resource intensive for the client ‣ First page is immediately consumable ‣ Single codebase (“Universal JS”)

Slide 48

Slide 48 text

CONNECTED PERSONAL OBJECTS 5/2012 Server-side rendering ‣ Advantages: ‣ SEO-friendly ‣ Less resource intensive for the client ‣ First page is immediately consumable ‣ Single codebase (“Universal JS”) ‣ Easy to implement with python-react and a simple Node HTTP server.

Slide 49

Slide 49 text

CONNECTED PERSONAL OBJECTS 5/2012 Server-side rendering: Workflow

Slide 50

Slide 50 text

CONNECTED PERSONAL OBJECTS 5/2012 Client Initial
 request Server-side rendering: Workflow

Slide 51

Slide 51 text

CONNECTED PERSONAL OBJECTS 5/2012 Client Server Initial
 request Fetch &
 serialize data GET request Server-side rendering: Workflow Django

Slide 52

Slide 52 text

CONNECTED PERSONAL OBJECTS 5/2012 Client Server Initial
 request Fetch &
 serialize data Render
 React components
 as HTML GET request Server-side rendering: Workflow Django Node JSON data (via HTTP) React components

Slide 53

Slide 53 text

CONNECTED PERSONAL OBJECTS 5/2012 Client Server Initial
 request Fetch &
 serialize data Render
 React components
 as HTML GET request Server-side rendering: Workflow Django Node Assemble initial HTML response JSON data (via HTTP) React components HTML

Slide 54

Slide 54 text

CONNECTED PERSONAL OBJECTS 5/2012 Client Server Initial
 request Fetch &
 serialize data Render
 React components
 as HTML GET request HTML response Server-side rendering: Workflow Django Node Assemble initial HTML response JSON data (via HTTP) React components HTML

Slide 55

Slide 55 text

CONNECTED PERSONAL OBJECTS 5/2012 Client Server Initial
 request Fetch &
 serialize data Render
 React components
 as HTML GET request HTML response Server-side rendering: Workflow Django Node Assemble initial HTML response Subsequently re-render client-side JSON data (via HTTP) React components React components HTML

Slide 56

Slide 56 text

CONNECTED PERSONAL OBJECTS 5/2012 Django view from django.shortcuts import render
 from react.render import render_component
 from myapp.models import MyModel
 from myapp.api import MySerializer
 
 def myview(request):
 items = MySerializer(MyModel.objects.all())
 
 rendered_html = render_component(
 'path/to/my/component.js',
 props = {'items': items.data})
 
 return render( request, 'template.html', {'rendered_html': rendered_html})

Slide 57

Slide 57 text

CONNECTED PERSONAL OBJECTS 5/2012 Django template {% extends "base.html" %}
 
 
 {% block content %}

{{ rendered_html|safe }}

 {% endblock %}

Slide 58

Slide 58 text

CONNECTED PERSONAL OBJECTS 5/2012 Simple ExpressJS server var http = require('http');
 var express = require('express');
 var bodyParser = require('body-parser');
 var reactRender = require('react-render');
 
 require('babel/register');
 
 var app = express();
 var server = http.Server(app);
 
 app.use(bodyParser.json());
 
 app.post('/', function(request, response) {
 reactRender(request.body, function(error, html){
 response.json({
 error: error,
 markup: html
 });
 });
 });
 
 server.listen(9009, '127.0.0.1');

Slide 59

Slide 59 text

CONNECTED PERSONAL OBJECTS 5/2012 …Live demo… Server-side rendering

Slide 60

Slide 60 text

CONNECTED PERSONAL OBJECTS 5/2012 Asset pipelines

Slide 61

Slide 61 text

CONNECTED PERSONAL OBJECTS 5/2012 Asset pipelines ‣ Webpack or Gulp+Browserify for JS bundling.

Slide 62

Slide 62 text

CONNECTED PERSONAL OBJECTS 5/2012 Asset pipelines ‣ Webpack or Gulp+Browserify for JS bundling. ‣ Babel for JSX transpiling.

Slide 63

Slide 63 text

CONNECTED PERSONAL OBJECTS 5/2012 Asset pipelines ‣ Webpack or Gulp+Browserify for JS bundling. ‣ Babel for JSX transpiling. ‣ Cache busting in production with ManifestStaticFilesStorage.

Slide 64

Slide 64 text

CONNECTED PERSONAL OBJECTS 5/2012 Testing

Slide 65

Slide 65 text

CONNECTED PERSONAL OBJECTS 5/2012 Testing ‣ Unit testing: Jasmine, Mocha, Jest, QUnit…

Slide 66

Slide 66 text

CONNECTED PERSONAL OBJECTS 5/2012 Testing ‣ Unit testing: Jasmine, Mocha, Jest, QUnit… ‣ Functional testing: Selenium with LiveServerTestCase.

Slide 67

Slide 67 text

CONNECTED PERSONAL OBJECTS 5/2012 Testing ‣ Unit testing: Jasmine, Mocha, Jest, QUnit… ‣ Functional testing: Selenium with LiveServerTestCase. ‣ Hybrid unit/integration testing:
 Test individual rendered React components with python-react, ExpressJS, PyQuery & assertHTMLEqual().

Slide 68

Slide 68 text

CONNECTED PERSONAL OBJECTS 5/2012 from django.test import TestCase
 from react.render import render_component
 from pyquery import PyQuery
 from photos.api import FavoriteSerializer
 from photos.models import Photo, Favorite
 
 class ReactComponentsTests(TestCase):
 
 def setUp(self):
 photo1 = Photo.objects.create(url='photo1.jpg')
 photo2 = Photo.objects.create(url='photo2.jpg')
 photo3 = Photo.objects.create(url='photo3.jpg')
 
 Favorite.objects.create(photo=photo2)
 Favorite.objects.create(photo=photo3)

Slide 69

Slide 69 text

CONNECTED PERSONAL OBJECTS 5/2012 def test_favorite_panel(self): 
 favorites = FavoriteSerializer(
 Favorite.objects.all(), many=True)
 
 html = str(render_component(
 'js/components/favorite-panel.js',
 to_static_markup=True,
 props = {
 'favorites': favorites.data,
 }))
 
 self.assertFalse('photo1.jpg' in html)
 self.assertTrue('photo2.jpg' in html)
 self.assertTrue('photo3.jpg' in html)

Slide 70

Slide 70 text

CONNECTED PERSONAL OBJECTS 5/2012 def test_favorite_panel(self):
 … pq = PyQuery(html) self.assertEqual( pq('.badge').text(), '2') self.assertHTMLEqual( pq('h4').outerHtml(), '

Favorites ' '2

' )

Slide 71

Slide 71 text

@julienphalip http://julienphalip.com http://nurun.com Code from this talk: https://github.com/jphalip/django-react-djangocon2015 Thank you!