# Treeshaking API Global
breaking

# Sintaks Vue versi 2.x

Apabila Anda pernah melakukan manipulasi DOM secara manual pada Vue, mungkin Anda pernah menggunakan pola berikut:

import Vue from 'vue'

Vue.nextTick(() => {
  // sesuatu yang berhubungan dengan DOM
})
1
2
3
4
5

Atau, apabila Anda pernah melakukan unit testing pada sebuah aplikasi yang melibatakan komponen asinkron, kemungkinan Anda pernah menulis kode program seperti berikut:

import { shallowMount } from '@vue/test-utils'
import { MyComponent } from './MyComponent.vue'

test('sebuah fitur asinkron', async () => {
  const wrapper = shallowMount(MyComponent)

  // lakukan beberapa hal yang berkaitan dengan DOM

  await wrapper.vm.$nextTick()

  // jalankan tuntutan Anda
})
1
2
3
4
5
6
7
8
9
10
11
12

Vue.nextTick() merupakan sebuah API global yang diekspos secara langsung pada sebuah objek Vue – nyatanya, method $nextTick merupakan sebuah wrapper untuk fungsi Vue.nextTick() dengan konteks this pada callback yang diikat secara otomatis pada objek tempat fungsi tersebut dipanggil untuk mempermudah proses pengembangan.

Tapi bagaimana bila Anda tidak pernah berurusan dengan manipulasi DOM secara manual, atau Anda tidak menggunakan atau menguji komponen asinkron pada aplikasi Anda? Atau bagaimana bila, dengan alasan tertentu, Anda lebih suka menggunakan window.setTimeout()? Dalam kasus tersebut, kode nextTick() akan menjadi kode mati – yang merupakan kode yang sudah ditulis namun tidak pernah dipakai. Ingat bahwa kode mati bukanlah sesuaty yang baik, khususnya dalam konteks sisi klien dimana setiap kilobyte penting.

Module bundler seperti webpack (opens new window) mendukung fitur tree-shaking (opens new window), yang merupakan sebuah istilah untuk pemangkasan kode mati. Sayangnya, karena cara kode Vue ditulis pada versi sebelumnya, API global seperti Vue.nextTick() tidak dapat dipangkas dan tetap diikutsertakan pada kode akhir terlepas API tersebut digunakan atau tidak.

# Sintaks Vue versi 3.x

Pada Vue versi 3, API global dan internal telah ditrusktur ulang supaya mendukung fitur tree-shaking. Sehingga, API global sekarang dapat diakses melalui named export untuk pembangunan modul ES. Sebagai contoh, kode program di atas dapat ditulis ulang menjadi seperti berikut:

import { nextTick } from 'vue'

nextTick(() => {
  // sesuatu yang berkaitan dengan DOM
})
1
2
3
4
5

dan

import { shallowMount } from '@vue/test-utils'
import { MyComponent } from './MyComponent.vue'
import { nextTick } from 'vue'

test('sebuah fitur asinkron', async () => {
  const wrapper = shallowMount(MyComponent)

  // lakukan beberapa hal yang berkaitan dengan DOM

  await wrapper.vm.$nextTick()

  // jalankan tuntutan Anda
})
1
2
3
4
5
6
7
8
9
10
11
12
13

Memanggil Vue.nextTick() secara langsung sekarang akan menghasilkan galat undefined is not a function.

Dengan perubahan tersebut, dengan catatan bahwa bundler modul mendukung fitur tree-shaking, API global yang tidak digunakan pada aplikasi Vue akan dipangkas dari kode akhir, menghasilkan ukuran berkas yang optimal.

# API yang Terdampak

Berikut merupakan API global pada Vue versi 2.x yang terdampak oleh perubahan tersebut:

  • Vue.nextTick
  • Vue.observable (diganti dengan Vue.reactive)
  • Vue.version
  • Vue.compile (hanya pada distribusi Vue yang lengkap)
  • Vue.set (hanya pada distribusi Vue yang ringkas)
  • Vue.delete (hanya pada distribusi Vue yang ringkas)

# Bantuan INternal

Selain API publik, banyak komponen atau fungsi bantuan internal yang sekarang diekspor sebagai named export. Hal tersebut memungkinkan kompilator untuk menghasilkan kode program yang hanya mengimpor fitur yang dibutuhkan. Sebagai contoh, pada template berikut:

<transition>
  <div v-show="ok">halo</div>
</transition>
1
2
3

akan dikompilasi menjadi kode berikut:

import { h, Transition, withDirectives, vShow } from 'vue'

export function render() {
  return h(Transition, [withDirectives(h('div', 'halo'), [[vShow, this.ok]])])
}
1
2
3
4
5

Hal tersebut menandakan bahwa komponen Transition hanya akan diimpor apabila aplikasi yang Anda buat menggunakan komponen tersebut. Dengan kata lain, apabila aplikasi yang Anda buat tidak menggunakan komponen Transition, kode yang mendukung fitur tersebut tidak akan ada pada kode akhir.

Dengan tree-shaking global, pengguna hanya akan "membayar" untuk fitur yang benar-benar mereka gunakan. Selain itu, karena fitur yang tidak wajib tidak akan menambah ukuran kode program pada aplikasi yang tidak menggunakan fitur tersebut, ukuran framework tidak lagi menjadi masalah apabila terdapat penambahan fitur utama baru pada versi-versi selanjutnya.

Penting

Keuntungan di atas hanya berlaku bagi kode program yang memanfaatkan modul ES yang dibangun menggunakan bundler yang mendukung fitur tree-shaking - kode program yang dibangun menggunakan modul UMD tetap memasukkan seluruh fitur dan mengekspos seluruh variabel global dari Vue (dan kompilator tetap akan menghasilkan kode program yang sebisa mungkin menggunakan API global dibandingkan mengimpor API).

# Penggunaan pada Plugin

Apabila plugin Anda bergantung pada API global yang terdampak pada Vue versi 2.x, seperti:

const plugin = {
  install: Vue => {
    Vue.nextTick(() => {
      // ...
    })
  }
}
1
2
3
4
5
6
7

Pada Vue versi 3, Anda harus mengimpor fitur tersebut secara eksplisit:

import { nextTick } from 'vue'

const plugin = {
  install: app => {
    nextTick(() => {
      // ...
    })
  }
}
1
2
3
4
5
6
7
8
9

Apabila Anda menggunakan bundler modul seperti webpack, bundler tersebut dapat menyebabkan kode sumber Vue diikutsertakan pada plugin tersebut, dimana seringkali Anda tidak mengharapkan perilaku tersebut. Cara yang umum digunakan untuk mencegah perilaku tersebut adalah dengan mengatur bundler untuk tidak mengikutsertakan Vue pada kode akhir. Pada webpack, Anda dapat menggunakna opsi externals (opens new window):

// webpack.config.js
module.exports = {
  /*...*/
  externals: {
    vue: 'Vue'
  }
}
1
2
3
4
5
6
7

Konfigurasi tersebut akan menyebabkan webpack mengenali modul Vue sebagai pustaka eksternal dan tidak mengikutsertakannya.

Apabila Anda menggunakan Rollup (opens new window) sebagai bundler modul Anda, Anda dapat mendapatkan fitur yang sama seperti webpack, karena secara bawaan Rollup akan menganggap ID dari modul absolut ('vue' dalam kasus ini) sebagai dependency eksternal dan tidak mengikutsertakannya pada kode akhir. Dalam proses pembentukan kode program, Rollup mungkin akan mengeluarkan peringatan “Treating vue as external dependency” (opens new window), yang dapat diabaikan menggunakan opsi external:

// rollup.config.js
export default {
  /*...*/
  external: ['vue']
}
1
2
3
4
5

Deployed on Netlify.
Pembaruan terakhir: 12/2/2020, 9:56:53 PM