Slide 1

Slide 1 text

こえのブログでのPWA ~ 開発現場編 ~ 2019年4月15日 @Abema Towers Kazunari Hara

Slide 2

Slide 2 text

ようこそ Abema Towersへ

Slide 3

Slide 3 text

原 一成 Hara Kazunari Web Developer @herablog

Slide 4

Slide 4 text

新卒12年目

Slide 5

Slide 5 text

新卒12年目

Slide 6

Slide 6 text

2008 HTML CSS

Slide 7

Slide 7 text

2010 JavaScript 2011 Node.js 2016 React, Redux, DevOps 2018 CDN HTML5 Web Applicationの つくりかた https://ameblo.jp/ca-1pixel/entry-1100959 8050.html アメブロ2016 ~ React/Reduxでつ くるIsomorphic web app ~ https://developers.cyberagent.co.jp/blog/archives/ 636/ Optimized Server-Side Web Application In 2018 https://developers.cyberagent.co.jp/blog/archi ves/16818/ Amebaプラットフォームの 作りかた https://www.slideshare.net/herablog/ameba-2 2035207

Slide 8

Slide 8 text

2019 HTML / CSS JavaScript Node.js Opts / Infra CDN and PWA

Slide 9

Slide 9 text

喋るだけで ブログになる

Slide 10

Slide 10 text

Demo: https://voice.ameba.jp/embed/kuroaroma-day/7q9eG1SVdlZrgUCtCUDl

Slide 11

Slide 11 text

なぜ今、音声投稿なのか モバイル テキスト +α

Slide 12

Slide 12 text

スマホの個人利用率 (30代, 2016) 90.4% http://www.soumu.go.jp/johotsusintokei/whitepaper/ja/h29/html/nc111110.html

Slide 13

Slide 13 text

データ消費量は増加 (一人, 月間) 約5倍 http://www.soumu.go.jp/johotsusintokei/whitepaper/ja/h29/html/nc111110.html

Slide 14

Slide 14 text

本人の”声”でコンテンツ価値向上 https://voice.ameba.jp/emb ed/kobayashi-maya/rxxqHm 6s4iAqYRP4mjK5 https://voice.ameba.jp/e mbed/kose-sports/eaxzb 5mP6vMlw3FWpqX9 https://voice.ameba.jp/e mbed/toshl-official/9nzC7 iAFn6IDKHPerj6P

Slide 15

Slide 15 text

なぜWebアプリなのか クロスプラットフォーム 小さくリリースできる ブラウザ機能の充実

Slide 16

Slide 16 text

ネイティブアプリ のように動く

Slide 17

Slide 17 text

CSRで高速な アプリを目指す

Slide 18

Slide 18 text

Rendering on the Web: https://developers.google.com/web/updates/2019/02/rendering-on-the-web

Slide 19

Slide 19 text

Rendering on the Web: https://developers.google.com/web/updates/2019/02/rendering-on-the-web

Slide 20

Slide 20 text

Rendering on the Web: https://developers.google.com/web/updates/2019/02/rendering-on-the-web

Slide 21

Slide 21 text

Rendering on the Web: https://developers.google.com/web/updates/2019/02/rendering-on-the-web Network JS GET / render GET /bundle.js FCP TTI

Slide 22

Slide 22 text

Network JS GET / render TTI FCP GET /bundle.js

Slide 23

Slide 23 text

Network JS GET / TTI GET /lazy.js GET /bundle.js FCP render

Slide 24

Slide 24 text

Network JS GET / FCP TTI GET /bundle.js GET /lazy.js render

Slide 25

Slide 25 text

PRPL Pattern (Push, Render, Pre-cache, Lazy load) CDN

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

index.html voice-app.js voice-editor.js voice-home.js lazy-resources.js shared dependencies Entrypoint App Shell Lazy Load Fragment PRPL Pattern await import(); await import(); await import();

Slide 28

Slide 28 text

index.html voice-app.js voice-editor.js voice-home.js lazy-resources.js shared dependencies Entrypoint App Shell Lazy Load Fragment (P) HTTP/2 Server Push

Slide 29

Slide 29 text

index.html voice-app.js voice-editor.js voice-home.js lazy-resources.js shared dependencies Entrypoint App Shell Lazy Load (P) Pre-cache with Service Worker

Slide 30

Slide 30 text

ブラウザ機能対応率 (こえのブログへのアクセスから, WebViewは除く) Service Worker 84.9% Static Import 88.9%

Slide 31

Slide 31 text

https://www.fastly.com/blog/optimizing-http2-server-push-fastly “Fastly’s server push mechanism won’t push the same resource twice over the same h2 connection”

Slide 32

Slide 32 text

Origin Servers Client DB CDN Edge CDN Edge CDN Edge CDN活用 計算量が多い

Slide 33

Slide 33 text

Origin Servers Client DB CDN Edge CDN Edge CDN Edge

Slide 34

Slide 34 text

できるだけ長く CDNキャッシュ する

Slide 35

Slide 35 text

Web Components with LitElement CSRのWebアプリ モバイルター ゲット コンポーネント Web標準 Web Components

Slide 36

Slide 36 text

コンポーネント指向での開発 記述内容の影響が絞られている事 による 「捨てやすさ > 再利用性」

Slide 37

Slide 37 text

コンポーネント指向での開発 メニューを開く class VoiceMic extends LitElement { render() { const label = this.recording ? ‘停止する’ : ‘開始する’; } } class VoiceHeader extends LitElement { render() { return html` `; } }

Slide 38

Slide 38 text

:host { --mic-size: var(--voice-mic-size, 72px); } .mic { height: var(--mic-size); } .icon { … } font-family: sans-serif; voice-mic { --voice-mic-size: 100px; } Custom Property Cascading Scoped

Slide 39

Slide 39 text

https://www.webcomponents.org/

Slide 40

Slide 40 text

166 KB (gzip, style込み)

Slide 41

Slide 41 text

Lighthouseでhttps://voice.ameba.jp/をMobile、Simulated Fast 3G、4x CPU Slowdown、ローカル環境で測定しました。

Slide 42

Slide 42 text

WebでAudio Recording?

Slide 43

Slide 43 text

ブラウザの マイクを利用 navigator.mediaDevices .getUserMedia({ audio: { autoGainControl: false, channelCount: 1, echoCancellation: true, noiseSuppression: true, }, }) .then((stream) => { // use the stream }) .catch((err) => { // NotAllowedError or // NotFoundError });

Slide 44

Slide 44 text

マイクパー ミッション を取得 const installMicPermissionWatcher = async callback => { const permissionStatus = await navigator.permissions .query({ name: 'microphone' }); // granted or prompt or denied callback(permissionStatus.state); permissionStatus .addEventListener('change', () => callback(permissionStatus.state) ); };

Slide 45

Slide 45 text

マイクパー ミッション を取得

Slide 46

Slide 46 text

音声を圧縮 WAV MP3

Slide 47

Slide 47 text

https://github.com/Kagami/vmsg Kagami/vmsg

Slide 48

Slide 48 text

https://developers.cyberagent.co.jp/blog/archives/20506/ 詳細は・・・ CDN/PWA/Speech Recognition/WASM/Web Components/Service Worker/Performance Budget etc...

Slide 49

Slide 49 text

開発フロー

Slide 50

Slide 50 text

デザイン 実装 仕様 餅つき開発 細かい粒度でプルリクエスト 違ったら直せばいい 早い共通化より捨てやすい構造にする

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

餅つきの結果 1,000コミット超え

Slide 53

Slide 53 text

最速で プロトタイプ 改善サイクルを回せ、品質が向上する 無駄になることを恐れない Firebaseをフル活用

Slide 54

Slide 54 text

2.5ヶ月 HTML + Pure JS Component すぐ

Slide 55

Slide 55 text

2.5ヶ月 HTML + Pure JS Component すぐ

Slide 56

Slide 56 text

アクセシビリティ も標準対応 最初から対応するほうが簡単 ガイドラインにのっとり開発 https://openameba.github.io/a11y-guidelines/

Slide 57

Slide 57 text

No content

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

https://www.slideshare.net/MarinaToki/ss-135424096 詳細はスライ ドで

Slide 60

Slide 60 text

デプロイ 心理的安全性 簡単にデプロイできることは、 プロダクト改善に役立つ サーバレス利用でめったに失敗しない

Slide 61

Slide 61 text

デプロイ 心理的安全性 932デプロイ

Slide 62

Slide 62 text

Perf Budget システム性能は時間とともに劣化す るもの 財政予算に見立てて、システム指標 を管理していく TTI Budget

Slide 63

Slide 63 text

Budgetの種類 (例) Timing: FCP、TTI、SpeedIndexなど Resource: ファイルサイズ、リクエスト数など Original: Time to Tweet

Slide 64

Slide 64 text

Budgetの決め方 (こえのブログの例) 1. 計測するページを決め、計測する 2. 競合を定義し、計測する 3. 最速だったので、競合より20%早い値を算出 4. それでも現状のが早かったので現状を維持す るBudgetを設定 (劣化を早い段階で防ぐ)

Slide 65

Slide 65 text

FCP: 1.8s -> 1.5s (Updated) TTI: 4s -> 3s (Updated) App shell JS size: 120KB Chunk JS size: 20KB

Slide 66

Slide 66 text

https://github.com/siddharthkp/bundlesize siddharthkp/bundlesize https://github.com/siddharthkp/bundlesize Front-End Performance Checklist 2019 https://twitter.com/katiehempenius/status/107547 8356311924737 Example of how perf budgets change by network connection

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

OSSのように 開発する 数カ月後の自分は他人・・・ 「共通言語」でいつでも開発者が 参加できる