Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Backends for frontends
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Daniele Polencic
May 10, 2016
Technology
150
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Backends for frontends
Daniele Polencic
May 10, 2016
More Decks by Daniele Polencic
See All by Daniele Polencic
Zero to Kubernetes — Developer's Gym Singapore
danielepolencic
2
230
Scaling Microservices with Message Queues, Spring Boot and Kubernetes
danielepolencic
3
390
7 tips and tricks on how to make the most of your Kubernetes journey
danielepolencic
3
320
Deploying and Scaling Spring Boot Microservices to Amazon EKS
danielepolencic
1
710
From Zero to Forex Trading Bot Hero with Node.js and Typescript
danielepolencic
0
390
Kubernetes Chaos Engineering: Lessons Learned in Networking
danielepolencic
0
270
Deploying and Scaling Spring Boot Microservices to Kubernetes
danielepolencic
0
130
Scaling Machine Learning in the Cloud with Kubernetes
danielepolencic
0
130
From Zero to Forex Trading bot Hero
danielepolencic
0
150
Other Decks in Technology
See All in Technology
MCPでAIが自分で調べに行く
cdataj
0
130
お客様の「やりたい」の先を見通す合意形成プロセス ~裏にある課題と不安を解きほぐすコツ~
yukakoseki
0
140
FinOpsを導入してマルチプロダクトのコスト最適化を実現する
kworkdev
PRO
0
140
コードレビューをなくして見えたもの
henteko
0
140
並列度を下げたら速くなった — go build の重複コンパイルを実測で見る
tomoaki25
2
1k
Kiro IDE 入門 (画面の各部から、頼み方、任せ方、戻し方まで) | 目指せ Kiro マスター 02
inariku
PRO
4
180
[dbts2026]数十PBの超巨大データ×AI活用を支えるSnowflakeの実力〜大規模環境におけるアーキテクチャと運用のリアル〜
y_matsubara
0
120
Copilot Coworkで「みのるん式」やってみた
minorun365
PRO
2
1.7k
会社説明資料_最新版
demaecan
0
32k
Active Directory と Entra ID のむむむな関係
murachiakira
PRO
4
1.7k
セキュリティ専任チームなしで攻撃を先回りするSREが実践したSIEM on Amazon OpenSearch Service
cscengineer
PRO
1
730
Reticulum, le réseau cypherpunk dont vous avez besoin !
rlifchitz
0
120
Featured
See All Featured
What's in a price? How to price your products and services
michaelherold
247
13k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
570
Rebuilding a faster, lazier Slack
samanthasiow
85
9.7k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
670
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.4k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.9k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
980
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
470
Amusing Abliteration
ianozsvald
1
380
Designing for Performance
lara
612
70k
Transcript
backends for frontends @danielepolencic
the good old days !
None
monolith templates cosmetic js
ajax ! revolution
None
api driven js widgets encapsulation
modern js era
None
serverless single page apps js bunsiness logic
serverless
just html, js & css
easy to deploy easy to build easy to scale
what about backend?
perfect rest api
None
everybody wins
None
!
how do you authenticate?
server side class UsersController < ApplicationController before_action :logged_in_user ... end
1. user requests page 2. redirected to login
client side UsersApi.isLoggedIn(cookie).then(user => { ... });
1. user requests page 2. wait for app to load
3. ajax request to /me 4. redirect
! are we there yet?
also1
auth server api
PUBLIC FACING AUTH SERVER
PUBLIC FACING AUTH SERVER
rest api + auth
frontend ! architecture
also2
tokens vs !!
CORS stateless CSRF JWT mobile
frontend ! backend apis
also3
little secrets
None
None
no harm, but... do you have a choice?
!
!
what about bootstrapping?
server side <body> ... <script> App.photos = new Photos([ {
id: 2, name: "My dog", filename: "IMG_0392.jpg" }, { id: 3, name: "Our house", filename: "IMG_0393.jpg" }, { id: 4, name: "My favorite food", filename: "IMG_0394.jpg" }, { id: 5, name: "His bag", filename: "IMG_0394.jpg" }, ... ]); </script> </body>
client side function AppController() { loadPhotos().then(photos => { ... });
}
1. user requests page 2. wait for app to load
3. ajax request to /photos 4. render page
! are we there yet?
… and this is the best case scenario
1. ajax request to /photos 2. ajax request to /posts
3. ajax request to /comments
!
what about aggregating calls?
server side class ClientsController < ApplicationController def fetch posts_response =
conn.get '/posts' followers_response = conn.get '/followers' ... end end <body> ... <script> App.photos = new Photos([ { id: 2, name: "My dog", filename: "IMG_0392.jpg" }, { id: 3, name: "Our house", filename: "IMG_0393.jpg" }, { id: 4, name: "My favorite food", filename: "IMG_0394.jpg" }, { id: 5, name: "His bag", filename: "IMG_0394.jpg" }, ... ]); </script> </body>
3 db queries
3 http requests server ✌ server
client side 3 http requests
! are we there yet?
SELECT * FROM Photos INNER JOIN Followers
!
!
cannot trust the user
None
client side <body> <form action="" method="post"> <div class="g-recaptcha" data-sitekey="site_key_here"></div> <input
type="submit" value="Submit" /> </form> <script src='https://www.google.com/recaptcha/api.js'></script> </body>
backend $reCaptcha = new ReCaptcha($secret); if ($_POST["g-recaptcha-response"]) { $response =
$reCaptcha->verifyResponse( $_SERVER["REMOTE_ADDR"], $_POST["g-recaptcha-response"] ); }
sadly, no client side only captcha
None
! solution !
REST SERVER
CAPTCHA API REST SERVER
client specific code in the rest api !
!
cross-origin resource sharing
fe: www.mysite.com be: api.mysite.com
nginx config # # Wide-open CORS config for nginx #
location / { if ($request_method = 'GET') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept'; } # ... }
front-end specific code in the web server
whatch out for glitches1
cookies are not included with preflight requests
None
PUBLIC FACING AUTH SERVER
PUBLIC FACING AUTH SERVER IF PREFLIGHT
in the auth server unless is_preflight_request? do authorise_request end
client specific code in the rest api !
whatch out for glitches2
ie9 doesn't send cookies at all
None
None
client specific code in nginx !
whatch out for glitches3
None
If the 302 status code is received in response to
a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued - w3
CORS REDIRECT Y U NO WORK???
!"#$...
websockets, sse, long polling batch api calls api data filter/enhance
validation
but...
just html, js & css
meanwhile your app...
it's fast !
it's easy to develop !
it's secure !
meanwhile your architecture...
AUTH SERVER REST API #2 REST API #1
AUTH SERVER REST API #2 REST API #1 FRONT-END CODE
AUTH SERVER REST API #2 REST API #1 CAPTCHA
AUTH SERVER REST API #2 REST API #1 CAPTCHA PREFLIGHT
PREFLIGHT
AUTH SERVER REST API #2 REST API #1 CAPTCHA PREFLIGHT
CORS PREFLIGHT
AUTH SERVER REST API #2 REST API #1 CAPTCHA PREFLIGHT
CORS PREFLIGHT BOOTSTRAPPING
AUTH SERVER REST API #2 REST API #1 CAPTCHA PREFLIGHT
CORS PREFLIGHT BOOTSTRAPPING FRONT-END CODE
AUTH SERVER REST API #2 REST API #1 CAPTCHA PREFLIGHT
CORS PREFLIGHT BOOTSTRAPPING FRONT-END CODE
AUTH SERVER REST API #2 REST API #1 CAPTCHA PREFLIGHT
CORS PREFLIGHT BOOTSTRAPPING infrastructure coupling
AUTH SERVER REST API #2 REST API #1 CAPTCHA PREFLIGHT
CORS PREFLIGHT BOOTSTRAPPING no separation of concerns
AUTH SERVER REST API #2 REST API #1 CAPTCHA PREFLIGHT
CORS PREFLIGHT BOOTSTRAPPING hidden dependencies
just html, js & css
so what shall you do?
going back to server side rendering?
nope.
ignore and move on?
nope.
good artists copy, great artists steal — Pablo Picasso
! presentation layer !
None
None
FRONT-END CODE
does it help?
PRESENTATION LAYER
PRESENTATION LAYER same domain
!! issues no more
cors & preflight request const express = require('express'); const cors
= require('cors'); const app = express(); app.options('/products/:id', cors()); app.del('/products/:id', cors(), (req, res) => { res.json({msg: 'CORS-enabled for all origins!'}); }); app.listen(3000, () => { console.log('web server listening on port 80'); });
user authentication const express = require('express'); const passport = require('passport');
const app = express(); app.post('/login', passport.authenticate('local'), (req, res) => { res.redirect('/'); });
bootstrapping1 const express = require('express'); const app = express(); app.get('/dashboard',
(req, res) => { res.render('homepage.html', { googleAnalyticsId: '123', locale: 'en_GB' }); });
bootstrapping2 <body> ... <script> angular .module('myApp', []) .constant('GA', '{{ googleAnalyticsId
}}') .constant('locale', '{{ locale }}') </script> </body>
captcha const express = require('express'); const app = express(); const
Captcha = require('./captcha'); const captcha = new Captcha(PUBLIC_KEY, PRIVATE_KEY); app.post('/comment', (req, res) => { captcha .verify(req.body['g-recaptcha-response']) .then(() => res.send('success!')); });
api aggregation const express = require('express'); const app = express();
app.post('/posts-and-flower', (req, res) => { Promise.all([ request.get('http://service1.com/posts'), request.get('http://service2.com/flowers') ]).spread((posts, flowers) => res.json({ posts, flowers })) });
websockets const http = require('http'); const sockjs = require('sockjs'); var
echo = sockjs.createServer({...}); echo.on('connection', (conn) => { conn.on('data', (message) => { request.get(`http://service1.com/${message}`) .then(response => conn.write(response)); }); conn.on('close', () => {}); }); const server = http.createServer(); echo.installHandlers(server, {prefix:'/echo'}); server.listen(9999, '0.0.0.0');
all requests are routed through the presentation layer
API {aggregation, filtering, enhancing}, data validation, encapsulation, state, cors, credentials,
caching, bootstrapping
wait
this is not front-end
PRESENTATION LAYER
this is the new front-end
None
freedom to create api, architecture visibility, better ux, SRP and
SOC, clearer responsabilities in the team
great power great responsability
static html vs real server
deployment
AUTH SERVER REST API #2 REST API #1 CAPTCHA PREFLIGHT
CORS PREFLIGHT BOOTSTRAPPING FRONT-END CODE PRESENTATION LAYER
scalability
performance
security and testing
point of failure
no, it doesn't make sense if you're building todo apps
nothing new adapter pattern
netflix
None
None
soundcloud
None
None
spotify
None
paypal
None
uber
None
what about you?
thanks