Riotでサーバーレス
にした話
@aggre
WWD JAPAN.com
INFAS PUBLICATIONS, INC.
Frontend
Backend
Git / CI
Collaboration
Technology stack
What
サーバーレスとは
インフラを任せる
スケーリングを任せる
スケーリングを任せる
彡
実行時間だけで課金
実行時間だけで課金
彡
Why
なぜサーバーレスなのか
パフォーマンス
可用性
コスト All OK!
パフォーマンス
可用性
コスト
整備不要
ベンダーロックイン
開発者は
プログラミングに集中
How
どうやるのか
サーバーレスの
制約
プログラムと状態
は完全に切り離す
あるべき姿です
セッションもCookieも
使えない
これもHTTPのあるべき姿です
できれば
?
サーバサイドは
APIだけ書いていたい
ビューロジックがサーバに混ざる
とアレですしね
そこで...
フロントエンドは一切のコードを
サーバから排除して S3 に集約
バックエンドは一切のテンプレート
を排除して API を返すことに集中
実際の話
WWD JAPAN.com
Before
サーバーレスにする前
SERVER
SERVER
SERVER
SERVER
MovableType から
謎の rsync
EC2 に全ファイル。
スケーリングできない
からよく停止する
After
サーバーレスにしたあと
SERVER
SERVERLESS
SERVERLESS
SERVERLESS
SERVERLESS
SERVER
※
Aurora で
フルマネージド化
Aurora はフルマネージドだがサーバーレ
スといえるほど高速なスケーリングはでき
ないのと、実行時間課金ではない
EC2 は管理画面だけ
Lambda の API から
RDS に接続
API Gateway で HTTP リクエス
トから Lambda を呼び出す
S3 に html, js, css
CloudFront の Error Page を
index.html にする
/dist/*
/*
...
/shop/123
S3
index.html
存在すればそのまま
存在しなければ
200
200
404
<app></app>
<script src="/dist/bundle.js"></script>
index.html
404 / SSR
404が返せない問題
Bot/非Bot不明問題
に対応する
API Gateway の
プロキシ統合で
Lambda をプロキシ
サーバにする
Lambda で SSR して、返ってきた HTML を
元に適宜ステータスコードを設定
プロキシ統合によって UA などのヘッダで
処理を自由に変えることが可能
いつか
CloudFrontのなかで
UAの振り分け
できないかなぁ
Riot
SPA
コンポーネント構成
Atomic Design
コンポーネントを分類する
Pages
Templates
Organisms
Molecules
Atoms
名前と中身が
一致しない
Screens
Areas
Widgets
Compornents
Modules
Pages
Templates
Organisms
Molecules
Atoms
Screens
Areas
Widgets
Compornents
Modules
Lifecycle
アプリケーションの動かし方
<app>Mount
<screen-xxx>Mount
URLアクションFlux
コンテキストストアの更新Flux
<app>
<div ref=”screens”></div>
<script>
( … )
</script>
</app>
app.tag
import riot from ‘riot’
import route from ‘riot-route’
import urlListener from ‘./my/libs/urlListener’
route( urlListener )
riot.mount( ‘app’ )
init.js
Flux
riot-observable
riot-control
flux
obseriot by me
Action with Obseriot
action.context.replace = {
handler: {
name: ‘action_context_replace’,
action: ( screen, id, url ) => [ screen, id, url ]
} }
Store with Obseriot
store.context = {
state: {},
handler: {
name: ‘store_context’,
action: () => store.context.state
} }
Dispatch Action with Obseriot
obseriot.notify( action.context.replace,
screen,
id,
url
)
Reduce Store with Obseriot
obseriot.listen( action.context.replace, ( s, i, u) =>
{
store.cotext.state = { screen: s, id: i, url: u }
obseriot.notify( store.context )
} )
<screen-xxx>Mount
URLアクションFlux
コンテキストストアの更新Flux
URLが変更されるたびに繰り返し
context, history, browser, windowSize,
user, posts, modal, menu, ad, ...
なるべく多くの状態をストアで管理
キャッチされない例外が発生したら
ストアのデータを送信すれば、
バグの改善につながる
window.onerror = msg => {
mySendFn( msg, getAllState() )
}
How much
いくらするのか
CloudFront
API Gateway
Lambda
S3
RDS
EC2
$3,703
Before
$6,737
After
$3,490
Now
CloudFront + API Gateway +
Lambda + S3
$773
インスタンス変えるの
サボっているだけ
CloudFront 3,732 GB
API Gateway 360.12 GB
Lambda 9,910,208.48 s
12,710,517 Request
S3 ...
Cost

Riotでサーバレスにした話