Upgrade to Pro — share decks privately, control downloads, hide ads and more …

十数万レコードに耐えうるVue.jsプロジェクトを実現するためのパフォーマンスチューニング

tbashiyy
October 17, 2022
3k

 十数万レコードに耐えうるVue.jsプロジェクトを実現するためのパフォーマンスチューニング

Vue Fes Japan Online 2022 での登壇資料です。
https://vuefes.jp/2022/sessions/tbashiyy

tbashiyy

October 17, 2022
Tweet

Transcript

  1. YESODの技術スタック Frontend Vue.js / TypeScript / Vuex / vue-property-decorator (現在2.7でCompositionAPIへ絶賛移行中)

    Backend Kotlin / Ktor / Exposed / Node.js / Express Infrastructure Kubernetes(GKE) / PostgreSQL(CloudSQL) 6
  2. 扱うデータ 人の情報 氏名、メールアドレス、生年月日など グループの情報 名称 グループの所属メンバーリスト グループの階層構造 メタデータ(データ構築に使う) 4000名 x

    40属性が入ってくると約16万件のデータを扱う必要が出てくる ※ ここに時系列分の断面が増えるので実際はもっと増える 12
  3. 3-2. 大きなデータをリアクティブにするのに数秒かかっ ていた defineReactive という処理が原因 オブジェクトをリアクティブにするための処理 export function defineReactive( obj:

    object, key: string, val?: any, customSetter?: Function | null, shallow?: boolean, mock?: boolean ) https://github.com/vuejs/vue/blob/ee57d9fd1d51abe245c6c37e6f8f2d45977b929e/src/ core/observer/index.ts#L131 31
  4. なぜこれでリアクティブにならなくなるか defineReactice を呼び出すObserverのコンストラクタ export class Observer { dep: Dep vmCount:

    number // number of vms that have this object as root $data constructor(public value: any, public shallow = false, public mock = false) { // 省略 if (isArray(value)) { // 省略 } else { // 省略 const keys = Object.keys(value) for (let i = 0; i < keys.length; i++) { const key = keys[i] defineReactive(value, key, NO_INIITIAL_VALUE, undefined, shallow, mock) // defineReactive を呼び出している } } } } https://github.com/vuejs/vue/blob/ee57d9fd1d51abe245c6c37e6f8f2d45977b929e/src/ core/observer/index.ts#L83 34
  5. なぜこれでリアクティブにならなくなるか Observerを生成するmethod export function observe(value: any, shallow?: boolean,  ssrMockReactivity?: boolean):

    Observer | void { // 省略 if { // 省略 } else if ( shouldObserve && (ssrMockReactivity || !isServerRendering()) && (isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && // <- ここで Object.isExtensible で判定している !value.__v_skip /* ReactiveFlags.SKIP */ ) { ob = new Observer(value, shallow, ssrMockReactivity) } return ob } https://github.com/vuejs/vue/blob/ee57d9fd1d51abe245c6c37e6f8f2d45977b929e/src/ core/observer/index.ts#L120 35
  6. Object.freeze してリアクティブにされないようにする before moutedでstoreから全組織のデータを取得している data: () { return { organizations:

    [], } }, mounted: () { // store にある組織を全部取得してSet している this.organizations = store.getOrganizations(); } 46
  7. after moutedでstoreから全組織のデータを取得しているのは変わらず dataにsetする時に Object.freeze する data: () { return {

    organizations: [], } }, mounted: () { this.organizations = Object.freeze(store.getOrganizations()); } 47
  8. after data: () { return { organizations: [], } },

    mounted: () { const organizations = store.getOrganizations() for (const organization of organizations) { // 一気に全部セットするのではなく、1 個ずつセットしていく this.organizations = Object.freeze([...this.organizations, organization]); await new Promise((resolve) => setTimeout(resolve, 0)); // セットが終わったら描画を走らせるため } } 51
  9. Intersection Observer API とは 交差オブザーバー API (Intersection Observer API) は、ターゲットとなる要素が、祖先

    要素または文書の最上位のビューポートと交差する変化を非同期的に監視する方法を提 供します。 交差オブザーバー API では、監視したい要素が他の要素(またはビューポート)に入っ たり出たりしたとき、あるいは両者が交差する量が要求された量だけ変化したときに実 行されるコールバック関数をコードに登録することができます。 https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API これを利用して、組織図の各組織が画面内に入ってきた時のみ、中身のメンバーのコンポー ネントを描画するように制御する 55
  10. 64