アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

96
アメブロフロント刷新にみる ひかりつらみ 2016/12/5 Frontrend Hara Kazunari @CyberAgent アメブロ2016

Upload: kazunari-hara

Post on 16-Apr-2017

3.515 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

アメブロフロント刷新にみる ひかりとつらみ

2016/12/5 Frontrend Hara Kazunari @CyberAgent

アメブロ2016

Page 2: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

🎉

Page 3: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

@herablog

@kouhin

Page 4: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

https://developers.cyberagent.co.jp/blog/archives/636/

Page 5: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ
Page 6: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ
Page 7: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

😂YES

Page 8: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

アメブロフロント刷新にみる ひかりとつらみ

アメブロ2016

Page 9: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

PV DOWN

Page 10: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

TOO SLOW TO LOAD

2016年4月のデータ

Page 11: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

バックエンドのAPI化 http://www.slideshare.net/nin2hanzo/spring-69237035

Page 12: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

! "#表示速度

改善システム モダン化

UX ver. 2016

GOAL

Page 13: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

#表示速度は、Web UXにとって、最も大事な項目のひとつです。

Page 14: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

モダンなエコシステムを使うことは、良いアプリを作るのに役立ちます。

!

Page 15: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

時代にあった、ユーザー体験を作ることで使いやすいアプリになります。

"

Page 16: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

! "#表示速度

改善システム モダン化

UX ver. 2016

GOAL

Page 17: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

コンセプト決め

Page 18: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

by Steve Souders

🙏

Page 19: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

by Steve Souders

Page 20: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

by Steve Souders

サーバーサイドははやい HTMLのサイズが大きめ

ブロッキングリソース多め リソース多いサイズも大きい

Page 21: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

💡

Page 22: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

サーバーサイドははやいまま HTMLのサイズ減らす

リソースの非同期読み込み ATF以外のリソースの遅延表示

💡

Page 23: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

ブログというプロダクト

テキスト中心の読み物 SEO大事 一度に複数ページ 見られている

Page 24: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

SSR SPA

Page 25: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Before

After

SPASSR

SSR SSR SSR

Page 26: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

SPA

SSR

First Paint SEO

Runtime Paint UX

Page 27: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Before After

Page 28: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

LAZY LOAD

Page 29: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Before

Main

Sub

Not displayed

Above The Fold

After

Main

Sub

Not displayed

Page 30: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

HTML Size -20%16.1 → 13.5 KB$

Page 31: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

#Under 100msHTML Response Time

Page 32: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

renderToString()8,000 rps at Ameba

300ms - 500ms, High CPU usage

Page 33: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Caching HTML/API Data Dynamic CSS Classes

Page 34: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

node

API

Cache

ClientHTTP

Blog Data

Blog Data

zlib

HTML

Add client info to <body>

as class name

Page 35: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

HTML ResponsesEntry List Pages

Entry Pages

2016年9月のデータ

Page 36: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

! "#表示速度

改善システム モダン化

UX ver. 2016

GOAL

Page 37: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

まるでexampleアプリのように

Page 38: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

React with Redux

コンポーネント志向 Pure functions

Page 39: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

React with Redux

Page

Navi Article Paging

コンポーネント志向

Page 40: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

React with Redux

Action

Page

Navi Article Paging

Reducer

props

State (Store)

propsobject

object

func

Pure functionsによる一定フロー

Page 41: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

React with Redux

State State State

Stateの情報だけで表示内容が確定できる

Page 42: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

CSS Modules各コンポーネントごとのスタイル

SpNavigationBar.js SpNavigationBar.css

.Nav { background: #fff; border-bottom: 1px solid #e3e5e4; display: flex; height: 40px; width: 100%; }

.Logo { text-align: center; }

import React from 'react'; import style from './SpNavigationBar.css'

export class SpBlogInfo extends React.Component { render() { return ( <nav className={style.Nav}> <div className={style.Logo}> <img alt="Ameba" height="24" src="logo.svg" width="71" /> </div> <div ...> </nav> ); } }

Page 43: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

css-loader

CSS Modules各コンポーネントごとのスタイル

.SpNavigationBar__Logo___${HASH}(BEM CamelCase style: MyBlock__SomeElem_modName_modVal)

https://en.bem.info/methodology/naming-convention/#camelcase-style

Page 44: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

CSS Modules各コンポーネントごとのスタイル

スコープがきれる 影響範囲が絞れる

モジュール・開発者多い アメブロでは機能

Page 45: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Atomic Design

Page 46: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Presentational and Container Components

% &Containers Components

状態を持つコンポーネント 表示内容だけのコンポーネント

Page 47: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Atomic Design

% &Containers Components

状態を持つコンポーネント 表示内容だけのコンポーネント状態が肥大化😿 処理が肥大化😿

どっちに書いていいかわからない🙀

Page 48: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Atomic Design

最小単位

<Icon>

状態持つ

<Entry>

再利用

<List>

各ページ SPA用

Page 49: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

organisms/SpEntry.js

organisms/SpBlogInfo.js

organisms/SpNavigationBar.js

atoms/Icon.js

molecules/BloggerThumbnail.js

Page 50: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

organisms/SpEntry.js

organisms/SpBlogInfo.js

organisms/SpNavigationBar.js

atoms/Icon.js

molecules/BloggerThumbnail.js

Page 51: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Atomic DesignOrganismのコンポーネントは状態を持てる

connectを使って状態を持てる データ取得処理を記述できる

Page 52: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

import React from 'react'; import { connect } from 'react-redux'; import { routerHooks } from 'react-router-hook'; import { fetchBloggerRequest } from '../../../actions/bloggerAction';

// データ取得処理 (react-router-hookを利用) const defer = async ({ dispatch }) => { await dispatch(fetchBloggerRequest()); };

// Redu storeのstateをpropsとして利用 const mapStateToProps = (state, owndProps) => { const amebaId = owndProps.params.amebaId; const blogger = state.bloggerMap.bloggerMap[amebaId].nickName; return { nickName, }; };

@connect(mapStateToProps) @routerHooks({ done }) export class SpProfileInfo extends React.Component { static propTypes = { nickName: React.PropTypes.string.isRequired, };

render() {

Page 53: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

SSR SPA

Isomorphic JavaScript

Page 54: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Isomorphic JavaScript

ほとんどJavaScript

Page 55: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Isomorphic JavaScript

Action

Page

Navi Article Paging

Reducer

State (Store)

% actions/

% components/

% reducers/

% services/

& server.js

& client.js ブラウザの入り口

サーバーの入り口

node API

Page 56: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Babel

決まっている未来は、 早めに試そう

Page 57: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Babel

http://node.green/

Page 58: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Babelexport function getPages(amebaId, page = 1) { const url = `https://api.jp/pages/${amebaId}/${page}`; return fetch(url); }

publicBlogger.getPages(amebaId) .then((res) => res.json()) .then(json => json.data);

fetch, Template Strings, default arguments, arrow functions, Promise

Page 59: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Babelexport default class SpThumbnail extends React.Component { render() { const { id, ...restProps } = this.props; return ( <Thumbnail

{...restProps} src=`https://img.com/${id}`

/> ); } }

Rest Parameters

Page 60: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Babelconst defer = async ({ dispatch, getState, params }) => { const amebaId = params.amebaId; const blogger = await dispatch(fetchBloggerRequest(amebaId)); if (blogger.isOfficial) {} };

@routerHooks({ defer }) export class SpBlogHeaderInfo extends React.Component { }

async/await, class, import/export, decorator

Page 61: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Babel

最悪、該当部分だけ書き直すのは難しくない …はず😅

Page 62: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

ESLint, Stylelint

比較的固めのルールを選択 ガイドラインを明確に

eslint-config-airbnb, stylelint-config-standard

Page 63: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

ESLint, Stylelint

例えばこんなのもエラー

Page 64: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

ESLint, Stylelintconst foo = { a: ‘a’, b: ‘b’ // comma-dangle } // semi

.Block{ // block-opening-brace-space-before border-top: 1px solid #CCC; // color-hex-case

border-bottom: 1px solid #ccc; // declaration-block-properties-order color:#333; // declaration-colon-space-after } // no-missing-end-of-source-newline

Page 65: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

ESLint, Stylelint

個人的な好みはあるが… ルールを統一して一貫性を保つ

レビュー時に毎回指摘は気まずい…😇

Page 66: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

CIPushされたものは 必ずCIテスト を通して 安全性を担保する

Page 67: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

CI

Page 68: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Docker

node.jsにポータビリティをもたらす

Page 69: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Docker

一度、イメージを作ってしまえば、 複数サーバーへのリリース

切り戻しも簡単

Page 70: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Docker

さらに、nodeのアップデートも 簡単

Page 71: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Docker

https://nodejs.org/en/download/releases/

Page 72: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Docker

FROM node:7.2

Dockerfileを変えるだけ

Page 73: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Docker

アメブロでは 極力node最新版を利用する

Page 74: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

CI, Lint Semantic Versioning

README.md CONTRIBUTING.md

PULL_REQUEST_TEMPLATE.md etc.

OSSっぽく開発

Page 75: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

外でもそのまま使える技術を

Page 76: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

! "#表示速度

改善システム モダン化

UX ver. 2016

GOAL

Page 77: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

No more ガタンッ🎯

ATFのコンテンツの高さを固定 誤タップはモバイルで

最悪のUXのひとつ

Page 78: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

No more ガタンッ🎯

Page 79: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

No more ガタンッ🎯

Page 80: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

コンテンツファースト

Before After

Page 81: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

アクセシビリディ

伊原 力也さん

太田 良典さん

Page 82: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

アクセシビリディ

https://speakerdeck.com/herablog/ameburowosukurinridadedu-mishang-getemita-2016nian-xia

Page 83: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

! "#表示速度

改善システム モダン化

UX ver. 2016

GOAL

Page 84: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ
Page 85: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ
Page 86: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

#Business & System✌

GOOD BOTH

'

Page 87: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Desktop version Markup, a11y

Design x Development Webpack2

https, HTTP/2 Service Worker, PWA, etc.

Roadmap

Page 88: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

https://developers.cyberagent.co.jp/blog/@ca_developers

@herablog

Page 89: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

アメブロフロント刷新にみる ひかりとつらみ

アメブロ2016

Page 90: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Reduxむずい😂

新メンバーが理解するまで 最大2ヶ月かかる (当社比)

(実装しながらわかってくる)

Page 91: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

Lintスパルタ😂

最初はだいたいCIエラー

Page 92: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

アメブロモジュール大杉😂

文章ママ

Page 93: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

周辺技術も大杉😂

Page 94: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

結論

みんなで、頑張ろ😂

Page 95: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

🍣🍕🍺🍣🍕🍺🍣🍕

🍺🍣🍕🍺🍣🍕🍺🍣

🍕🍺🍣🍕🍺🍣🍕🍺

🍺🍕🍺🍣🍕🍺🍣🍕

🍕🍺🍕🍺🍣🍕🍺🍣

Page 96: アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ

アメブロフロント刷新にみる ひかりとつらみ

Hara Kazunari @herablog

アメブロ2016