Bagaimana dan mengapa menyiapkan build yang memungkinkan Anda menulis komponen .vue di TypeScript.

Oke, mungkin tidak sehari penuh, tapi masih butuh waktu lama untuk menyiapkan peralatan untuk proyek baru. Dan beberapa hal masih terlalu sulit untuk selera saya. Bukan yang baik 'sulit' seperti dalam menantang. Lebih tepatnya sangat membosankan. Ya, yang saya bicarakan adalah tentang webpack, TypeScript, dan file .vue. Di sini, saya ingin menunjukkan apa yang saya lakukan, dan mengapa saya tetap melakukannya.

Jika Anda hanya mencari perbaikan TypeScript yang cepat, itu relatif mudah. Ambil webpack-blocks, dan atur dalam waktu kurang dari 5 menit. Apa yang saya coba lakukan adalah sedikit lebih eksotis jika Anda mau. Saya ingin menggunakan Vue, dan khususnya, file .vue, dengan TypeScript. Informasi tersebar di seluruh web, jadi menurut saya mungkin bukan ide yang buruk untuk mengumpulkan semuanya di sini sebagai referensi cepat.

PEMBARUAN 8 Mei 2017:Sejak saya menulis artikel ini, webpack-blocks 1.0.0 hampir dirilis. Ini sudah tersedia di NPM, jadi saya meluangkan waktu untuk merilis beberapa kode yang dibahas di artikel ini. Saya akan menerbitkan postingan terpisah yang menguraikan perubahannya dibandingkan artikel aslinya.

Sebelum kita mulai, lupakan apa yang Anda ketahui tentang cara menulis komponen Vue. Jika Anda ingin menggunakan file .vue dengan TypeScript, Anda harus membuat kode dengan cara TypeScript. Anda bisa membuat kode dengan cara lama, tentu saja, namun Anda tidak mendapat manfaat dari pengecekan tipe, sehingga hanya membuang-buang waktu Anda. Anda telah diperingatkan.

Mengapa file .vue?

Pertama, izinkan saya menjelaskan mengapa saya ingin memulai dengan .vue file (jika Anda tidak tahu apa itu, lihat di sini). Paket-paket file-tunggal-multi-bahasa ini bukan hanya sarana untuk mengelompokkan apa yang seharusnya menjadi kumpulan file-file yang lepas. Tidak, mereka memiliki fitur tersendiri yang lebih dari sekadar menggabungkan kode.

Misalnya, templat HTML dikodekan dalam HTML, sehingga Anda mendapatkan penyorotan sintaksis, pelengkapan otomatis sadar konteks, dan/atau dukungan emmet. Pengembang JavaScript yang hebat sangatlah langka, jadi pengkodean HTML biasa (sebagai lawan dari JSX dan, lebih buruk lagi, hiperskrip) bisa sangat bermanfaat. Ya, saya sadar bahwa ada cerita tentang desainer dan pemula yang mempelajari hyperscript dan sejenisnya, dan benar-benar menyukainya, tetapi Anda harus ingat bahwa bahkan pengembang JavaScript berpengalaman pun terkadang tidak menyerah tanpa perlawanan.

Kedua, CSS tercakup. Jika Anda masih berpikir bahwa "BEM" memiliki tempat dalam kerangka front-end yang dilengkapi dengan baik, maka Anda memahami pentingnya dan tantangan CSS yang terorganisir dengan baik. Anda mungkin akan menyukai CSS yang tercakup. Saya tidak akan mencoba dan menjual cakupan CSS kepada Anda. Ini seperti narkoba: ia menjual dirinya sendiri. Coba saja. Saya tantang kamu.

Semua ini, dan fakta bahwa saya berurusan dengan satu file, bukan tiga atau empat, merupakan argumen yang cukup baik untuk menghabiskan waktu ekstra agar .vue file berfungsi dengan TypeScript.

Mengapa TypeScript?

Ini adalah sesuatu yang harus Anda capai sendiri, jika pernah. Orang-orang pernah menggunakan JavaScript yang belum diketik, dan ini benar-benar berfungsi. Faktanya, saya mencoba untuk memutuskan antara TypeScript dan LiveScript, yang merupakan versi fungsional dari CoffeeScript, dengan sintaksis yang singkat dan agak aneh.

Pada akhirnya, hal ini bermuara pada produktivitas. LiveScript menyediakan sintaks dan pintasan yang lebih sedikit untuk banyak hal yang saya gunakan sehari-hari. TypeScript akan menangkap banyak kesalahan pengkodean yang mungkin saya buat, dan mungkin memberikan informasi tambahan tentang kode yang membuat bekerja dengan perpustakaan dan kerangka kerja asing menjadi lebih mudah. Saya memilih yang terakhir daripada yang pertama karena alasan firasat.

Jika Anda harus meminta penjelasan grafis tentang bagaimana rasanya menggunakan TypeScript dalam produksi, ada “artikel bagus dari tim Slack”.

Cukup bicara, mari membuat kode… atau mungkin tidak

Sebelum kita dapat membuat kode, kita perlu menyiapkan peralatannya.

Pertama, ambil blok webpack. Itulah cara termudah untuk mengkonfigurasi webpack yang saya tahu. Ya, paling mudah setelah hanya menyalin dan menempelkan konfigurasi yang ada, tetapi Anda mengerti maksud saya.

Sekarang, langsung saja, webpack-blocks tidak mendukung file .vue. Ada dua paket pihak ketiga yang memungkinkan penggunaan file .vue.

Konfigurasi TypeScript bawaan di blok webpack menggunakan awesome-typescript-loader. Ini merupakan loader yang bagus, namun tidak berfungsi baik dengan .vue file. (Namanya juga aneh, tapi itulah masalah saya.) Selain paket untuk mengonfigurasi vue-loader, oleh karena itu kita juga memerlukan paket yang akan mengonfigurasi ts-loader yang memiliki beberapa ketentuan untuk bekerja dengan format kontainer seperti .vue.

npm i -D webpack-blocks-vue webpack-blocks-ts

Anda akhirnya mendapatkan sesuatu seperti file webpack.config.js ini. Hal-hal penting yang perlu diperhatikan:

  • Kami meneruskan opsi { appendTsSuffixTo: [/\.vue$/] } ke ts-loader karena jika tidak, kompiler TypeScript tidak mau bekerja sama. Hal ini menyebabkan file .vue diperlakukan sebagai .vue.ts, seperti yang disukai kompiler TypeScript.
  • Kami tidak menggunakan Babel. Jika Anda ingin menggunakan JSX, Anda mungkin ingin menggunakannya, tapi saya tidak.
  • Kami meneruskan { esModule: true } ke vue-loader. Opsi ini memberitahu pemuat untuk memancarkan modul ES2015, bukan modul CommonJS. Rupanya, TypeScript tidak menyukai modul CommonJS.

Anda juga perlu memberi tahu TypeScript apa itu file .vue dan cara menanganinya. Untuk tujuan ini, kami menambahkan vue.d.ts file di pohon sumber. Definisi ini memberi tahu TypeScript seperti apa jenis ekspor default dari file .vue nantinya.

Bisakah kita membuat kode sekarang?

Ya kita bisa. Seperti yang saya sebutkan di pendahuluan, Anda tidak bisa hanya membuat kode seperti dulu dan mengharapkan semuanya berfungsi. Mengkodekan file .vue untuk TypeScript memerlukan pendekatan yang berbeda. Namun jangan takut. Sintaks alternatifnya sangat masuk akal, dan, menurut pendapat saya, membuat kode lebih mudah dibaca (belum lagi jenis pemeriksaan yang baik).

Pertama-tama Anda perlu menambahkan ketergantungan tambahan: vue-property-decorator.

Komponen Anda kemudian akan terlihat seperti ini:

<template>
  <div class="hello">Hello, {{ name }}</div>
</template>
<script lang="ts">
import Vue from 'vue'
import { Component, Prop } from 'vue-property-decorator'
@Component
export default class Hello extends Vue {
  @Prop
  name: string
}
</script>
<style scoped>
.hello {
  font-size: 200px;
  font-family: sans-serif;
}
</style>

Saya tidak akan membahas terlalu banyak detail di sini karena vue-property-decorator dan vue-class-component, yang menjadi dasarnya, didokumentasikan dengan cukup baik dan mudah digunakan.

Hal utama yang harus diperhatikan adalah bahwa gaya ini menghilangkan banyak keajaiban/boilerplate (atau tetap menyembunyikannya). Alih-alih mendefinisikan pengamat dan metode di bawah objek bersarang dan kemudian menggunakan this sebagai objek luar (yang berhak mematikan pemeriksa tipe TypeScript), semua metode didefinisikan pada objek yang terikat this. Itu membuat segalanya lebih mudah untuk dipahami dan diikuti, membuat segalanya lebih dekat dengan cara kerja JavaScript biasanya.

Anda akan menemukan contoh lengkapnya di vue-ts-sandbox repo saya.

Sebagai catatan tambahan, meskipun Anda tidak peduli dengan TypeScript, Anda dapat menggunakan dekorator ini dengan Babel.

Apakah itu layak?

Seperti yang Anda lihat, sangat merepotkan untuk membuatnya berfungsi. Bahkan sekarang, jika ditilik ke belakang, dengan memanfaatkan pengetahuan kumulatif yang terdokumentasi, masih diperlukan waktu untuk menyiapkan segalanya. Pertanyaannya kemudian adalah apakah itu layak dilakukan.

Seperti yang saya katakan di bagian Mengapa TypeScript, ini adalah sesuatu yang harus Anda pahami sendiri.

Saya percaya bahwa semua kerumitan anotasi tipe dan konfigurasi build sangat bermanfaat ketika pemeriksa tipe memberi tahu Anda bahwa Anda telah memberikan argumen yang salah, atau lupa menetapkan sesuatu ke properti, atau bahwa tipe kembalian dari beberapa fungsi tidak apa yang Anda pikir akan terjadi. Anda mengerti idenya. Keharusan mendeklarasikan antarmuka secara eksplisit juga membantu saya memahami basis kode sedikit lebih baik, dan cukup memperlambat saya untuk menghindari kesalahan yang terburu-buru.

Saat ini memang dibutuhkan sedikit usaha ekstra untuk mencapainya, tapi pikirkanlah: pengujian unit membutuhkan sedikit usaha ekstra (jauh lebih dari ini!) dan tidak ada yang akan berpendapat bahwa pengujian unit tidak sepadan. Sejalan dengan itu, ini hanyalah lapisan lain yang berkontribusi terhadap kualitas kode. Begitulah cara saya melihatnya.