Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

66

Transcript of Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Page 1: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Vue.js Tokyo v‑meetup #5

Page 2: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Page 3: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Q. 秋といえば?

Page 4: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

A. 読書の秋 �

Page 5: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Q. Vue.js で作られた SPA SSR な

電子書籍 (マンガ) 配信サービスは?

Page 6: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

A. マンガZERO

Page 7: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Nuxt 無しで作ってしまった

恨み辛み妬み

Page 8: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Vue.js Tokyo v‑meetup #5

Nuxt less SPA SSR で乗り越えるべきnの壁Nuxt less SPA SSR で乗り越えるべきnの壁

Page 9: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

const n = 5;

Page 10: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

構成構成

SPA of Vue.js + Vuex

SSR by Express

Device switching between PC/SP

Backend as API by Go

Page 11: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

vue‑hackernews‑2.0 頼み

Page 12: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

1の壁: メタタグ1の壁: メタタグ

SSR 対応

Fetch の結果から動的に扱えること

手間がかからないこと

Page 13: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

declandewet/vue‑metadeclandewet/vue‑meta

メタタグ吐く

SSR 対応

公式ドキュメントにも載ってる

Page 14: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

export default { metaInfo() { let metaBase = { title: this.title, meta: [ { vmid: 'og:title', property: 'og:title', content: this.title }, { vmid: 'description', name: 'description', content: this.description }, ... ], link: [ { vmid: 'canonical', rel: 'canonical', href: this.canonical } ] };

if (this.prev) { metaBase.link.push({ rel: 'prev', href: 'https://manga-zero.coroco3.com' + this.prev }); }

Page 15: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

// server.js .on('beforeStart', () => { const { title, link, meta } = context.meta.inject(); context.head = (context.head || '') + title.text() + meta.text() + link})

Page 16: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Nuxt にも入ってる �

Page 17: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

2の壁: Google Analytics2の壁: Google Analytics

非 SPA の PV と同じになること

手間がかからないこと

Page 18: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

MatteoGabriele/vue‑analyticsMatteoGabriele/vue‑analytics

SSR 対応

vue‑router と同期し自動で PV を送ってくれる

Page 19: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

// router.js Vue.use(Router); Vue.use(Meta);

if (process.env.VUE_ENV === 'client') { Vue.use(VueAnalytics, { id: 'UA-xxxxxxxx-xx', router, ready() { const ga = window.ga || {}; ga('require', 'linkid'); ga('set', 'dimension1', val); } }); }

export default router;

Page 20: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

イベントとか送るのもちょっと楽

this.$ga.event('グローバル', 'メニュータップ', '', 0, { nonInteraction: true });

Page 21: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

App analytics を使うなら ScreamZ/vue‑analytics

Page 22: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

あるのかよ �

Page 23: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

3の壁: デバイス切り替え3の壁: デバイス切り替え

同一 Express から配信したい

Store とか共通で使いたい

手間がかからないこと

デバイス切り替ェ �

Page 24: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Webpack の MultiCompile でいける...

Page 25: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

デバイス切り替ェ �

// webpack.config.server.js { ... plugin: [ ... new VueSSRServerPlugin({ filename: 'sp/vue-ssr-server-bundle.json' }) ] ... }, { ... plugins: [ ... new VueSSRServerPlugin({ filename: 'pc/vue-ssr-server-bundle.json' }) ] ... }

Page 26: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

デバイス切り替ェ �

const template = { pc: fs.readFileSync(resolve('./src/app/templates/pc.html'), 'utf-8'), sp: fs.readFileSync(resolve('./src/app/templates/sp.html'), 'utf-8') };

Page 27: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

デバイス切り替ェ �

// srever.js if (!isDevelop) { const bundle = { sp: require('./dist/sp/vue-ssr-server-bundle.json'), pc: require('./dist/pc/vue-ssr-server-bundle.json') }; const clientManifest = { sp: require('./dist/sp/vue-ssr-client-manifest.json'), pc: require('./dist/pc/vue-ssr-client-manifest.json') }; renderer = { sp: createRenderer(bundle.sp, { clientManifest: clientManifest.sp }, pc: createRenderer(bundle.pc, { clientManifest: clientManifest.pc }, }; } else { readyPromise = setupDevServer(app, (bundle, options) => { renderer = { sp: createRenderer(bundle.sp, options, template.sp), pc: createRenderer(bundle.pc, options, template.pc) }; }); }

Page 28: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

webpack.config.client.js も同様

dev‑middleware と hot‑middleware も同様

Page 29: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

デバイス切り替ェ �

// server.js function render(req, res) { ... const device = (req.useragent.isMobile) ? 'sp' : 'pc'; const context = { url: req.url, device };

renderer[device].renderToStream(context) ... }

Page 30: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

流石に無いよな... � ?

Page 31: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

4の壁: 他民族4の壁: 他民族

国内ではまだ若干弱め

1.0 の時のイケてない印象

手間がかからないこと

Page 32: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

☝ � Angular ぽく書けるよ �☝

Page 33: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

vue‑class‑componentvue‑class‑component

TS でいい感じに書ける

ES でも使える

Angular ぽく書けるイメージ

Page 34: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

import Vue from 'vue'; import Component from 'vue-class-component';

@Component({ name: 'component-hoge', metaInfo: { ... }, proprs: { ... } }) export default class ComponentHoge extends Vue { // initial data msg = 123;

// lifecycle hook mounted () { this.greet(); }

// computed get computedMsg () { return 'computed ' + this.msg; }

// method greet () { alert('greeting: ' + this.msg); } }

Page 35: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

他民族においても他民族においても

直帰率の低下 ⬆⬆⬆

リテンションの底上げ ⬆⬆⬆

布教にも貢献 ���

Page 36: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

親クラス作って継承したり

Page 37: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

vue‑class‑component/createDecoratorvue‑class‑component/createDecorator

デコレータを作れる

Page 38: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

例えば PC/SP 間で

殆ど同じだけど微妙に異なる (Props とか)

コンポーネントを沢山作る時

Page 39: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

同じ: Template, Style, Props

違う: Method, Computed

Page 40: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

import Vue from 'vue'; import createDecorator from 'vue-class-component';

function ComponentTopDefault() { return createDecorator((options) => { options = object.assign({}, { name: 'view-top', props: { hoge: { ... } } }, options); }); }

@Component() @ComponentTopDefault() export default class ViewTop extends Vue {}

Page 41: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

metaInfo とか proprs とか

Mixin はちょっと違うなってものを

createDecrator で定義した

Page 42: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

v5.0.2 でこの使い方はできなくなった

Page 43: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

次の日には PR できてた

Page 44: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

���

Page 45: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Nuxt 関係ない �

Page 46: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

5の壁: HTTP Status5の壁: HTTP Status

状況に合わせた HTTP ステータスが打てる

404 デザインが Vue でレンダリングできる

手間がかからない

Page 47: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

vue‑hackernews‑2.0 の 404 は

Page 48: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁
Page 49: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

さすがにこれはない �

Page 50: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

のでやってみた �

Page 51: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Router にマッチしなかった時Router にマッチしなかった時

/unkounko

Page 52: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁
Page 53: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Router にマッチしなかった時Router にマッチしなかった時

/unkounko

// router [ ... { path: '*', name: 'not-found', component: notFound } ]

// server.js .once('data', () => { if (context.state.route.name === 'not-found') res.status(404); })

Page 54: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

API のステータスからAPI のステータスから

/product/999999

// store/action.js export const FETCH_ITEMS = ({ commit }, { path, key, type }) => { return fetchItem(path, key).then((result) => { if (result.status === 200) { ... } else if (result.mainQuery) { /* ↑ メインクエリに値する API のレスポンスが200 じゃない時 ↑ */ /* ↓ state に error コードをセットする ↓ */ commit(types.SET_STATUS, { key: 'error', value: result.status }); } else { ... } }).catch((error) => { console.error('catch FETCH_ITEMS', error); }); };

Page 55: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

API のステータスからAPI のステータスから// server.js .once('data', () => { const termState = (context.state.error && context.state.error !== 0);

if (context.state.error !== 0) { res.status(context.state.error); } })

Page 56: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Nuxt だと

Page 57: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

でいいらしい �

async fetch({ store, route, app, error }) { let url = `/api/${route.params.id}` let data = await app.$axios.$get(url) if (data.items.length === 0) { // there's no data this should be a 404 // No! there is no Content so throw `204 No Content` response: // https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_Succes error({statusCode: 204, message: "The server successfully processed t } store.commit('item', data.Items[0]) }

Page 58: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

結論結論

色々頑張ったけど...

もしかして Nuxt 使えば楽なの �?

Page 59: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

最後に最後に

Page 60: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

お前誰?

Page 61: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

Yutaro Miyazaki (@vwxyutarooo)Yutaro Miyazaki (@vwxyutarooo)

ニート ↓

フリーの Web 屋 ↓

アプリ屋のフロントエンド

Dvorak + Vim に悩んでいる

Page 62: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁
Page 63: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁
Page 64: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁
Page 65: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁
Page 66: Nuxt なしで Vue App 作る時に乗り越えるべき5つの壁

ありがとうございました �ありがとうございました �