SlideShare a Scribd company logo
1 of 64
Download to read offline
初夏のJavaScript 祭in mixi
Vue.js 2.0 で自社プロダクトを
SPA + SSR 化した話
Yutaro Miyazaki (@vwxyutarooo)
ニート↓
フリーランス(Web制作)↓
アプリ屋のWeb(フロントエンド)
今日話すこと
導入してみてどうだった?ってとこ
地味に困ったこと
今日話さないこと
Vue.jsSSRのしくみ、ロジックなど
他フレームワークとの比較
サービスの概要
マンガ無料配信サービス
アプリを主軸に展開しているサービス
Webでもコンテンツを活かそう
リニューアルと導入の背景
Web経験者無しでv1を作ってしまった
イケてない
Webでももっとこう
アプリっぽい体験できないですかね
v1:Riotでページ毎にマウント
→SPA
クライアントレンダリング
→SSR(SEOほんとにいいのか?)
Vue.jsの評判がいい
どっかの調査で満足度1位
構成 (全体)
構成 (Web)
前提知識
vuejs/vue‑hackernews‑2.0
公式が作るSPA+SSRプロジェクト
https://github.com/vuejs/vue‑hackernews‑2.0
Webpack の例
https://ssr.vuejs.org
地味に悩んだポイント集
SSRは誰がやる?
404ハンドリング
デバイス切り替えってどうする?
共通処理どうする?
メタタグの管理めんどいやりたくない
Analyticsどうしよう?
広告
メモリリーク
Q: SSR は誰がやる?
バックエンドからもJSが起動できる
go
go‑duktape
goja+goja‑node
素直にExpressから起動することに
Q: 404 ハンドリング
vue‑hackernews2では
ルータ設定にマッチするページが見つからなければ
Expressが404返すようになってる
if (err && err.code === 404) {
res.status(404).end('404 | Page Not Found')
}
404ページのデザイン欲しい
// router.js
[
{ path: '/', name: 'top', component: top },
...
{ path: '*', name: 'not-found', component: notFound }
]
// server.js
const termRoute = (context.state.route.name === 'not-found');
if (termRoute) res.status(404);
ルータにマッチするけど404の時は?
// router.js
{ path: '/comics/tag/:id', name: 'tag-archive', component: tagArchive },
APIリクエスト時に、メインクエリを設定
// preFetch
const options = { isMainQuery: (key === mainQueryKey) }
メインクエリのAPIレスポンスが
200じゃなかったらstateにエラーをセット
// action.js
if (result.status === 200) {
commit(mutation, { key, result: result.data });
} else if (options.isMainQuery) {
commit(types.SET_STATUS, { key: type, value: {} });
commit(types.SET_STATUS, {
key: 'error',
value: result.status // 404
});
}
Expressサーバで、コンテキストを通じて
stateのエラーからステータスを打つ
// server.js
const termState = (context.state.error); // 404 | 50x
if (termState) res.status(context.state.error);
ちょっとイケてないけど
対象Viewコンポーネント内でnotfoundを表示させた
<div :key="`tag-archives-${id}-${currentPage}`">
<div v-if="isLoading" class="l-root">
<screen-spinner></screen-spinner>
</div>
<content-not-found v-else-if="status === 404"></content-not-found>
<template v-else="v-else">
...
</template>
</div>
Q: デバイス切り替えってどうする?
PC/SP用エントリーポイントをそれぞれ用意
// webpack.config.client.js
entry: {
'polyfills': [path.join(..., 'app/entry/polyfills.js')],
'vendor': [path.join(..., 'app/entry/vendor.js')],
'app.pc': [path.join(..., 'app/entry/pc/client-entry.js')],
'app.sp': [path.join(..., 'app/entry/sp/client-entry.js')]
},
// webpack.config.server.js
entry: {
'server-bundle.pc': path.join(..., 'app/entry/pc/server-entry.js'),
'server-bundle.sp': path.join(..., 'app/entry/sp/server-entry.js')
}
テンプレートも2つ
// webpack.config.client.js
new HTMLPlugin({
template: path.join(..., 'templates/pc.html'),
filename: 'index.pc.html',
excludeChunks: ['app.sp']
}),
new HTMLPlugin({
template: path.join(..., 'templates/sp.html'),
filename: 'index.sp.html',
excludeChunks: ['app.pc']
}),
createRendererでレンダラを2つ作成
// server.js
const bundle = {
pc: fs.readFileSync(resolve('./dist/js/server-bundle.pc.js'), 'utf-8'),
sp: fs.readFileSync(resolve('./dist/js/server-bundle.sp.js'), 'utf-8')
}
const template = {
pc: fs.readFileSync(resolve('./dist/index.pc.html'), 'utf-8'),
sp: fs.readFileSync(resolve('./dist/index.sp.html'), 'utf-8')
}
renderer = {
pc: createRenderer(bundle.pc, template.pc),
sp: createRenderer(bundle.sp, template.sp)
};
ExpressでUA判定して起動するレンダラを切り替え
// server.js
const useragent = require('express-useragent');
...
app.use(useragent.express());
app.get('*', (req, res) => {
...
const device = (req.useragent.isMobile) ? 'sp' : 'pc';
...
renderer[device].renderToStream(context)...
}
2.3.0からcreateRenderer
にバンドル突っ込むのは非推奨に...
別の方法を考え中
Serverバンドルはエントリーポイント分けず
contextにデバイス情報渡して切り替えるのもありか?
Q: 共通処理どうする?
vuejs/vue-class-component
もともとTypeScriptで書けるようにするため
Classでコンポーネントを定義できる
継承は非対応だが、Decoratorと組み合わせる
import Vue from 'vue'
import Component from 'vue-class-component'
@Component({
props: {
propMessage: String
}
})
export default class App extends Vue {
// initial data
msg = 123
// use prop values for initial data
helloMsg = 'Hello, ' + this.propMessage
// lifecycle hook
mounted () {
this.greet()
}
...
}
import { createDecorator } from 'vue-class-component';
export const Options = createDecorator((options) => {
Object.assign(options, {
...
watch: {
// call again the method if the route changes
'$route': 'routeUpdated'
}
};
});
使い方は君しだい!
Q: メタタグの管理めんどいやりたくない
declandewet/vue-meta
export default {
name: 'App',
metaInfo: {
title: METAINFO.title,
titleTemplate: METAINFO.titleTemplate,
meta: [
{
vmid: 'og:title',
name: 'og:title',
content: METAINFO.title
},
{
vmid: 'description',
name: 'description',
content: METAINFO.description
}
...
]
}
}
コンポーネントの深いやつが勝つ
全コンポーネント検査してるからパフォーマンスは疑問
SSR対応(Vueの公式にも例あり)
Q: Analytics どうしよう?
WebAnalytics:MatteoGabriele/vue-analytics
AppAnalytics:ScreamZ/vue-analytics
routerとくっつけて自動でPV|SV送れる
Q: 広告
GoogleAdsenseはSPA非対応
ページのリフレッシュ無しに広告を打ち直すことは禁止
impが絶望的
GoogleAdsense以外のSSP等広告運用が必須
Q: メモリリーク
起こしてた
1日でメモリを食い尽くし
ガベージコレクション走りまくり、CPU回りまくり
APIキャッシュ周りが原因
最新のVuehackernewsでは直ってる
所感
SSR の実装はそれほど大変ではないのかも
普通にSPAを作る+ちょっとの手間でいい
メタタグとかアプリケーション側で扱いたいからついでに
SSRしちゃってたり
まあまあ安定稼働もする
CPUはそこそこ回るためページキャッシュを併用
コンポーネントキャッシュは考えて設計すべし
状態変化によるケースやslotが多いと効果的ではないかも?
KPI 的には
PV/セッション上がり
滞在時間は平行
回遊しやすくなってるって思いたい
なんか下がることはなかった
まとめ
あり
SEO対策としてだけやるなら要らない
メタタグさえサーバ側で作れていれば
堅いこと言わずに作ってみようぜ
Vue.js 楽しいな! おい!!
ありがとうございました!

More Related Content

What's hot

Node.jsではじめるサーバ構築
Node.jsではじめるサーバ構築Node.jsではじめるサーバ構築
Node.jsではじめるサーバ構築
AimingStudy
 

What's hot (20)

Node.js Hands-On
Node.js Hands-OnNode.js Hands-On
Node.js Hands-On
 
Node.jsではじめるサーバ構築
Node.jsではじめるサーバ構築Node.jsではじめるサーバ構築
Node.jsではじめるサーバ構築
 
jQueryを中心としたJavaScript
jQueryを中心としたJavaScriptjQueryを中心としたJavaScript
jQueryを中心としたJavaScript
 
Node.js で Web アプリ開発
Node.js で Web アプリ開発Node.js で Web アプリ開発
Node.js で Web アプリ開発
 
Sails.jsのメリット・デメリット
Sails.jsのメリット・デメリットSails.jsのメリット・デメリット
Sails.jsのメリット・デメリット
 
いまさら聞けない!?Backbone.js 超入門
いまさら聞けない!?Backbone.js 超入門いまさら聞けない!?Backbone.js 超入門
いまさら聞けない!?Backbone.js 超入門
 
React.js + Reduxで作るSPA
React.js + Reduxで作るSPAReact.js + Reduxで作るSPA
React.js + Reduxで作るSPA
 
Rubyで始めるWebスクレイピング
Rubyで始めるWebスクレイピングRubyで始めるWebスクレイピング
Rubyで始めるWebスクレイピング
 
Nodeにしましょう
NodeにしましょうNodeにしましょう
Nodeにしましょう
 
Node.jsに縁のない職場でnode.jsを使い始める戦術
Node.jsに縁のない職場でnode.jsを使い始める戦術Node.jsに縁のない職場でnode.jsを使い始める戦術
Node.jsに縁のない職場でnode.jsを使い始める戦術
 
Nodeとフロントエンド − 知っておかなければならない、今と未来の話 −
Nodeとフロントエンド − 知っておかなければならない、今と未来の話 −Nodeとフロントエンド − 知っておかなければならない、今と未来の話 −
Nodeとフロントエンド − 知っておかなければならない、今と未来の話 −
 
ReactをRailsとどっぷり使ってみた話と、フロントエンド×AWSのこれから
ReactをRailsとどっぷり使ってみた話と、フロントエンド×AWSのこれからReactをRailsとどっぷり使ってみた話と、フロントエンド×AWSのこれから
ReactをRailsとどっぷり使ってみた話と、フロントエンド×AWSのこれから
 
Node.js を選ぶとき 選ばないとき
Node.js を選ぶとき 選ばないときNode.js を選ぶとき 選ばないとき
Node.js を選ぶとき 選ばないとき
 
Capybaraで雑にWebスクレイピング
Capybaraで雑にWebスクレイピングCapybaraで雑にWebスクレイピング
Capybaraで雑にWebスクレイピング
 
なぜ人は必死でjQueryを捨てようとしているのか
なぜ人は必死でjQueryを捨てようとしているのかなぜ人は必死でjQueryを捨てようとしているのか
なぜ人は必死でjQueryを捨てようとしているのか
 
React + FLUX + Redux + Redux Saga のお話
React + FLUX + Redux + Redux Saga のお話React + FLUX + Redux + Redux Saga のお話
React + FLUX + Redux + Redux Saga のお話
 
Node js 入門
Node js 入門Node js 入門
Node js 入門
 
Clojure の各種React系ラッパーライブラリのサーバーサイドレンダリングの現状について
Clojure の各種React系ラッパーライブラリのサーバーサイドレンダリングの現状についてClojure の各種React系ラッパーライブラリのサーバーサイドレンダリングの現状について
Clojure の各種React系ラッパーライブラリのサーバーサイドレンダリングの現状について
 
Google Web Toolkit(GWT)入門
Google Web Toolkit(GWT)入門Google Web Toolkit(GWT)入門
Google Web Toolkit(GWT)入門
 
One Time Binding & Digest Loop
One Time Binding & Digest LoopOne Time Binding & Digest Loop
One Time Binding & Digest Loop
 

Similar to Vue.js 2.0 で自社プロダクトを SPA + SSR 化した話

Similar to Vue.js 2.0 で自社プロダクトを SPA + SSR 化した話 (20)

我が家のフロントエンド開発事情
我が家のフロントエンド開発事情我が家のフロントエンド開発事情
我が家のフロントエンド開発事情
 
Riot.jsを用いたweb開発 takusuta tech conf #1
Riot.jsを用いたweb開発   takusuta tech conf #1Riot.jsを用いたweb開発   takusuta tech conf #1
Riot.jsを用いたweb開発 takusuta tech conf #1
 
【Web TECH FORUM 2017 in大阪】Webシステム開発とJavaScript UIコンポーネント
【Web TECH FORUM 2017 in大阪】Webシステム開発とJavaScript UIコンポーネント【Web TECH FORUM 2017 in大阪】Webシステム開発とJavaScript UIコンポーネント
【Web TECH FORUM 2017 in大阪】Webシステム開発とJavaScript UIコンポーネント
 
Service workerとwebプッシュ通知
Service workerとwebプッシュ通知Service workerとwebプッシュ通知
Service workerとwebプッシュ通知
 
AngularJS x Chrome Apps (2014.08.23 #gdgkobe event)
AngularJS x Chrome Apps (2014.08.23 #gdgkobe event)AngularJS x Chrome Apps (2014.08.23 #gdgkobe event)
AngularJS x Chrome Apps (2014.08.23 #gdgkobe event)
 
第12回rest勉強会 これまでの補足・展望編
第12回rest勉強会 これまでの補足・展望編第12回rest勉強会 これまでの補足・展望編
第12回rest勉強会 これまでの補足・展望編
 
Nuxt.js入門 2018/02/02 Vue.js入門勉強会@渋谷 発表資料
Nuxt.js入門 2018/02/02 Vue.js入門勉強会@渋谷 発表資料Nuxt.js入門 2018/02/02 Vue.js入門勉強会@渋谷 発表資料
Nuxt.js入門 2018/02/02 Vue.js入門勉強会@渋谷 発表資料
 
React.js + Flux
React.js + FluxReact.js + Flux
React.js + Flux
 
Rails×React×TS で作るwebアプリ入門【weseek tech conf #10】
Rails×React×TS で作るwebアプリ入門【weseek tech conf #10】Rails×React×TS で作るwebアプリ入門【weseek tech conf #10】
Rails×React×TS で作るwebアプリ入門【weseek tech conf #10】
 
Vue.js Outline
Vue.js OutlineVue.js Outline
Vue.js Outline
 
Web開発初心者がReactをチームに導入して半年経った
Web開発初心者がReactをチームに導入して半年経ったWeb開発初心者がReactをチームに導入して半年経った
Web開発初心者がReactをチームに導入して半年経った
 
Interoperability of webassembly with javascript
Interoperability of webassembly with javascriptInteroperability of webassembly with javascript
Interoperability of webassembly with javascript
 
JavaScript(AngularJS・React.js)で作る iOS・Androidアプリハンズオン
JavaScript(AngularJS・React.js)で作る iOS・AndroidアプリハンズオンJavaScript(AngularJS・React.js)で作る iOS・Androidアプリハンズオン
JavaScript(AngularJS・React.js)で作る iOS・Androidアプリハンズオン
 
アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ
アメブロ2016 アメブロフロント刷新にみる ひかりとつらみアメブロ2016 アメブロフロント刷新にみる ひかりとつらみ
アメブロ2016 アメブロフロント刷新にみる ひかりとつらみ
 
なるほどわかった!App Service on Linux
なるほどわかった!App Service on Linuxなるほどわかった!App Service on Linux
なるほどわかった!App Service on Linux
 
フロントエンド技術の変遷
フロントエンド技術の変遷フロントエンド技術の変遷
フロントエンド技術の変遷
 
React.jsでサービスを作ってみた話
React.jsでサービスを作ってみた話React.jsでサービスを作ってみた話
React.jsでサービスを作ってみた話
 
React.js・ReactNative・Redux入門
React.js・ReactNative・Redux入門React.js・ReactNative・Redux入門
React.js・ReactNative・Redux入門
 
Web Component Framework Urushiのご紹介(OSC2017 Tokyo/Spring)
Web Component Framework Urushiのご紹介(OSC2017 Tokyo/Spring)Web Component Framework Urushiのご紹介(OSC2017 Tokyo/Spring)
Web Component Framework Urushiのご紹介(OSC2017 Tokyo/Spring)
 
Vue Fes Japan 2018 LINE株式会社 LunchスポンサーLT
Vue Fes Japan 2018 LINE株式会社 LunchスポンサーLTVue Fes Japan 2018 LINE株式会社 LunchスポンサーLT
Vue Fes Japan 2018 LINE株式会社 LunchスポンサーLT
 

Recently uploaded

Recently uploaded (11)

Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 

Vue.js 2.0 で自社プロダクトを SPA + SSR 化した話