Roppongi.vue #1
https://gyazo.com/ea52c6afc3760e36f4c4e6c1caed0d62
https://roppongi-vue.connpass.com/event/129289/
https://www.youtube.com/watch?v=HPsVAakHXCU
JavaScriptで実装したVue.jsプロジェクトをTypeScriptへ移行する話
https://speakerdeck.com/53able/javascriptdeshi-zhuang-sitavuejs-puroziekutowotypescriptheyi-xing-suruhua
Go Tadano
GitHub.icon https://github.com/53able
株式会社GameWith
フロントエンドエンジニア
Roppongi.vue運営メンバー
いつやるか?なぜやるのか?
プロジェクトが予想より大きくなった
リファクタリングの効率化
副作用に怯えない
TypeScriptのサポート強化
まだつくったことがない
学び
1. TypeScriptのインストール
vue add @vue/typescript
依存モジュールは2つイエス
差分にtsファイルが生成される
同名のファイルは上書きされる
Vuex Module
この時点でコンパイラエラーが発生してる
型をつけてあげる
2. TypeScriptを使用したVueコンポーネントの実装
<script lang="ts">
デコレータを仕様
vue-property-decorator
@Componentを使うとメタデータがクラスに渡される
data, methods, components, mixinなど
JSXをTSX化
拡張子を.tsxに変更
すぐにコンパイルエラーが発生するので修正
render関数
引数、戻り数に型をつける
イベントハンドラーに型定義
コンポーネントをローカル登録
componentsキー
3. Vuexモジュールの作成
Vuex ModuleをTypeScript化
クラスベースで実装する
vuex-module-decorators
configのtranspileDependenciesに追加
名前空間付きであることを明示
namespaced: true
state => publicクラスプロパティ
mutations => @Mutationを付与したクラスメソッド
getters => クラスのgetter
4. Vuexとコンポーネントのバインド
vuex-class
名前空間のデコレータを作成
Vuexプロパティとバインド
同じ型・名前のクラスプロパティ
getters, mutationsも同じ宣言
Vuex mutationsは関数型
Definite Assignment Assertion 演算子
宣言時に初期化しないとエラー
クラスプロパティの型チェック
適当な型でも通ってしまう
イベントハンドラーの型定義
プロジェクト構成
vue-cli
SFC
JSX
まとめ
Vuex ModuleがTSのクラスベース実装になった
問題点
関数の戻り値型を定義しなくてもコンパイルエラーにならない
Vuex Moduleとバインドするクラスプロパティの型チェックが行われるかが課題
propsについて考える
https://docs.google.com/presentation/d/1SIe3MJInup5hIJosTG4EgchEcJckpJBGYPqh5V2CE5c/edit?usp=sharing
SatohJohn
フリュー株式会社
サーバサイド、フロントエンド、インフラ
propsってどこまで書いてる?という疑問
propsってどんなもの?
前提
コンポーネントに渡る値を明示する
Required
必須かどうかを検証
nullやundefinedは検証しない
Type
型の検証
複数指定できる
TypeScriptで一番恩恵が得られそう
違う方が入るとwarnがでる
Validator
コンポーネントに渡る値の検証
falseを返すとwarnが出る
TypeでエラーならValidatorでの検証は動かない
Default
入力値がなかった場合のデフォルト値
Default値があったらRequiredは動かない
ただし検証も対象にする
引数=TypeScriptの検証と似ている
Vue.jsで実装していて感じた設計部分
メリット
コンポーネントを「具体的な」実装で表せる
具体的=コードがドキュメントである
ドキュメントで説明ではなく実装で説明する
Whyなどを完全に書くのは難しいので、完全なドキュメントにはならない
Required=必須
Validator=条件
Type=型
インタフェースとして定義できる
依存関係逆転の法則
上位モジュールは下位のモジュールに依存してはならない
抽象(インターフェース)に対して依存する
インターフェース=propsと捉えている
結合が減らせるので修正が容易に
親=>子
子コンポーネントが自分propsに依存する
できるだけStatelessなコンポーネントを作成できる
propsの値を変更するとエラー
Vuexとの共存
props VS getters
propsで渡されると親子間でのデータ渡ししかができない
storeをかませると依存が増える
なるべくpropsで済ませて完結にする
Validatorのロジックをどこに書くか
ViewModelに書く
Validatorに直接書くと流入しにくい
LogicとViewを分割して考える
MVVM
ガッチリやりすぎると固くなるので程々に
まとめ
propsはとても良い機構
TypeScriptがきちんと使える人はTypeを使うとよさげ
Statelessで依存の少ないコンポーネントを作ろう
SSRのはなし
https://slides.com/kahirokunn/vuex-class-based-13-15/
kahirokunn
今のSPA
モダンフロントライブラリを利用
リッチUIを1ファイルのJSで表現
静的なhtmlとセットで簡単に配信できる
よくある質問
Vuex使っとけばいいの?
どうコードを書くのが正解なの?
せっかくなのでVuexがあると明確に助かるケースを紹介
Vuexの特徴
単一状態木のメンテが可能
単一状態木状態を自動でVue.jsに反映してくれる
mutationsからしか変更できないように保護してくれる
SSR
サーバー側でHTMLを生成して返す
vue-server-renderer
JSを埋め込んでリッチなUIを表現
ページを変えるたびにサーバーに新たなHTMLを要求
代表例
Laravel
Ruby on Rails
Django など
ファーストペイントを早くする方法の1つを紹介
従来のSSRのようにサーバー側で生成して返す
利点
ネットワーク的に近い距離からAPIが叩ける
比較的安定しているコンピューター上で初期描画が行える
サーバー利用に制限されたAPIを叩ける
仕組み
結果が同じなので生成された要素をフロントのVueが引き継げる
https://gyazo.com/4a2ada76a9a16ed78aaec0f989fe6a46
構造が違うとhydrationに失敗する
課題
サーバーからフロントにコンポーネントの状態を正しく復元する必要性
Vuexのstate treeが便利
状態をjson化してwindowのstateに突っ込むなど
https://ssr.vuejs.org/ja/guide/data.html#最終状態注入
ライフサイクルまとめ
サーバー
serverPrefetch
beforeCreate
created
フロント
replaceState
ライフサイクルではない
beforeCreate
created
beforeMount
まとめ
SPAとSSRでコードの書き方は全然違うので気をつけよう
SSRする場合はcreatedの扱いは細心の注意が必要
serverで実行したいコードはserverPrefetchを使おう
nuxtの場合はasyncData等
フロントでmount後にやりたい事はmountedでやろう
シングルトンは危ない
参考 GitHub.icon https://github.com/kahirokunn/book-management/
Nuxt.js(SPA)でもOGPしたい
果物リン
株式会社ゆめみ
ページ個別にOGPを設定するには?
SSR
Universalモード
headでメタタグ設定
SPAモード
expressの常駐が不要
Universalモードに切り替える場合
fetchでのwindow object操作が全滅
一部設計やりなおし
検証コストが増える
Nuxt.jsにわたす前にexpressでHTMLを改ざんしたらどうか?
できそうな感じらしい
方針
nuxt startしないプロジェクトを目指す
サーバーが起動するので改ざんの余地なし
expressを起動するapp.js的なものを作る
node app.jsで動かす
備考:create-nuxt-appでexpressを選択できる
HTMLを取得したい
nuxt.renderRoute()
実質テンプレートが取得できる
返り値のオブジェクトに含まれるHTMLにレンダリングしようとしたHTMLが入ってる
特定のルーティングの場合
expressのapp.get()を使用する
特定のときだけエンドポイントが動く
axiosで必要なデータを持ってくる
改ざんしてレンダリング
String.replace()でゴリゴリ変換
置換したものをres.send()でレンダリング
メリット
以降に比べれば検証コストが軽い
サーバーでDOMの計算をしなくていい
デメリット
UniversalモードでいいならUniversalで
Expressの知識が必要
ページコンポーネントのルーティングと改ざん処理のルーティングが一致しない
自動ルーティングの恩恵が得られない
1ページの処理が2箇所になる