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

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

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for tbashiyy tbashiyy
October 17, 2022
4.4k

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

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

Avatar for 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