Membuat Aplikasi Vue.js yang Dirender Sisi Server Menggunakan Nuxt.js

Diterbitkan: 2022-03-11

Kerangka kerja/pustaka JavaScript seperti Vue dapat menawarkan pengalaman pengguna yang fantastis saat menjelajahi situs Anda. Sebagian besar menawarkan cara mengubah konten halaman secara dinamis tanpa harus mengirim permintaan ke server setiap kali.

Namun, ada masalah dengan pendekatan ini. Saat pertama kali memuat situs web Anda, browser Anda tidak menerima halaman lengkap untuk ditampilkan. Sebagai gantinya, ia dikirimi banyak bagian untuk membuat halaman (HTML, CSS, file lain) dan instruksi tentang cara menggabungkan semuanya (kerangka/perpustakaan JavaScript) Dibutuhkan waktu yang dapat diukur untuk menyatukan semua informasi ini sebelum browser Anda benar-benar memiliki sesuatu untuk ditampilkan. Ini seperti dikirimi banyak buku bersama dengan rak buku flat-pack. Anda harus membuat rak buku terlebih dahulu dan kemudian mengisinya dengan buku.

Solusi untuk ini adalah cerdas: Miliki versi kerangka kerja/pustaka di server yang dapat membangun halaman yang siap ditampilkan. Kemudian kirimkan halaman lengkap ini ke browser bersama dengan kemampuan untuk melakukan perubahan lebih lanjut dan masih memiliki konten halaman dinamis (kerangka/pustaka), seperti halnya mengirim rak buku yang sudah jadi bersama dengan beberapa buku. Tentu, Anda masih harus meletakkan buku-buku di rak buku, tetapi Anda segera mendapatkan sesuatu yang dapat digunakan.

Perbandingan visual rendering sisi klien dan sisi server

Di luar analogi konyol, ada juga banyak keuntungan lainnya. Misalnya, halaman yang jarang berubah, seperti halaman Tentang Kami, tidak perlu dibuat ulang setiap kali pengguna memintanya. Jadi server dapat membuatnya sekali dan kemudian menyimpannya di cache atau menyimpannya di suatu tempat untuk digunakan di masa mendatang. Peningkatan kecepatan semacam ini mungkin tampak kecil, tetapi dalam lingkungan di mana waktu hingga responsivitas diukur dalam milidetik (atau kurang), setiap hal kecil sangat berarti.

Jika Anda ingin informasi lebih lanjut tentang keuntungan SSR di lingkungan Vue, Anda harus membaca artikel Vue sendiri tentang SSR. Ada berbagai opsi untuk mencapai hasil ini, tetapi yang paling populer, yang juga direkomendasikan oleh tim Vue, adalah Nuxt.

Mengapa Nuxt.js

Nuxt.js didasarkan pada implementasi SSR untuk library React populer yang disebut Next. Setelah melihat kelebihan dari desain ini, implementasi serupa dirancang untuk Vue yang disebut Nuxt. Mereka yang akrab dengan kombinasi React+Next akan melihat banyak kesamaan dalam desain dan tata letak aplikasi. Namun, Nuxt menawarkan fitur khusus Vue untuk menciptakan solusi SSR yang kuat namun fleksibel untuk Vue.

Nuxt telah diperbarui ke versi 1.0 siap produksi pada Januari 2018 dan merupakan bagian dari komunitas yang aktif dan didukung dengan baik. Salah satu hal hebatnya adalah membangun proyek menggunakan Nuxt tidak jauh berbeda dengan membangun proyek Vue lainnya. Faktanya, ini menyediakan banyak fitur yang memungkinkan Anda membuat basis kode yang terstruktur dengan baik dalam waktu yang lebih singkat.

Hal penting lainnya yang perlu diperhatikan adalah Nuxt tidak harus digunakan untuk SSR . Ini dipromosikan sebagai kerangka kerja untuk membuat aplikasi Vue.js universal dan menyertakan perintah ( nuxt generate ) untuk membuat aplikasi Vue yang dihasilkan statis menggunakan basis kode yang sama. Jadi, jika Anda khawatir tentang menyelam jauh ke dalam RSK, jangan panik. Anda selalu dapat membuat situs statis sambil tetap memanfaatkan fitur Nuxt.

Untuk memahami potensi Nuxt, mari buat proyek sederhana. Kode sumber terakhir untuk proyek ini dihosting di GitHub jika Anda ingin melihatnya, atau Anda dapat melihat versi langsung yang dibuat menggunakan nuxt generate dan dihosting di Netlify.

Membuat Proyek Nuxt

Untuk memulai, mari gunakan generator proyek Vue yang disebut vue-cli untuk membuat proyek sampel dengan cepat:

 # install vue-cli globally npm install -g vue-cli # create a project using a nuxt template vue init nuxt-community/starter-template my-nuxt-project

Setelah melalui beberapa opsi, ini akan membuat proyek di dalam folder my-nuxt-project atau apa pun yang Anda tentukan. Maka kita hanya perlu menginstal dependensi dan menjalankan server:

 cd my-nuxt-project npm install # Or yarn npm run dev

Di sana kita pergi. Buka browser Anda ke localhost:3000 dan proyek Anda akan berjalan. Tidak jauh berbeda dengan membuat proyek Vue Webpack. Namun, ketika kita melihat struktur aplikasi yang sebenarnya, tidak ada banyak hal, terutama jika dibandingkan dengan sesuatu seperti template Vue Webpack.

Diagram direktori proyek dan hubungannya dengan file konfigurasi Nuxt

Melihat di package.json juga menunjukkan bahwa kita hanya memiliki satu ketergantungan, Nuxt itu sendiri. Ini karena setiap versi Nuxt dirancang untuk bekerja dengan versi Vue, Vue-router, dan Vuex tertentu dan menggabungkan semuanya untuk Anda.

Ada juga file nuxt.config.js di root proyek. Ini memungkinkan Anda untuk menyesuaikan banyak fitur yang disediakan Nuxt. Secara default, ini menetapkan tag header, warna bilah pemuatan, dan aturan ESLint untuk Anda. Jika Anda ingin melihat apa yang dapat Anda konfigurasi, inilah dokumentasinya; kami akan membahas beberapa opsi dalam artikel ini.

Jadi apa yang istimewa dari direktori itu?

Tata Letak Proyek

Jika Anda menelusuri direktori yang dibuat, semuanya memiliki Readme yang menyertai yang menyatakan ringkasan singkat tentang apa yang ada di direktori itu dan sering kali tautan ke dokumen.

Ini adalah salah satu manfaat menggunakan Nuxt: struktur default untuk aplikasi Anda. Setiap pengembang front-end yang baik akan menyusun aplikasi yang serupa dengan ini, tetapi ada banyak ide berbeda tentang struktur, dan ketika bekerja dalam tim, beberapa waktu pasti akan membahas atau memilih struktur ini. Nuxt menyediakan satu untuk Anda.

Nuxt akan mencari direktori tertentu dan membangun aplikasi Anda untuk Anda tergantung pada apa yang ditemukannya. Mari kita periksa direktori ini satu per satu.

halaman

Ini adalah satu-satunya direktori yang diperlukan . Setiap komponen Vue dalam direktori ini secara otomatis ditambahkan ke vue-router berdasarkan nama file dan struktur direktorinya. Ini sangat nyaman. Biasanya saya akan memiliki direktori Pages yang terpisah dan harus secara manual mendaftarkan masing-masing komponen tersebut di file router lain. File router ini dapat menjadi kompleks untuk proyek yang lebih besar dan mungkin perlu dipisah untuk menjaga keterbacaan. Sebagai gantinya, Nuxt akan menangani semua logika ini untuk Anda.

Untuk mendemonstrasikan, kita dapat membuat komponen Vue bernama about.vue di dalam direktori Pages. Mari kita tambahkan template sederhana seperti:

 <template> <h1>About Page</h1> </template>

Saat Anda menyimpan, Nuxt akan membuat ulang rute untuk Anda. Karena kami memanggil komponen kami about.vue , jika Anda menavigasi ke /about , Anda akan melihat komponen itu. Sederhana.

Ada satu nama file yang spesial. Memberi nama file index.vue akan membuat rute root untuk direktori tersebut. Saat proyek dibuat, sudah ada komponen index.vue di direktori halaman yang berhubungan dengan beranda atau halaman arahan situs Anda. (Dalam contoh pengembangan, ini hanya akan menjadi localhost:3000 .)

Nuxt memindai file Vue di direktori halaman dan menampilkan halaman yang sesuai.

Bagaimana dengan rute yang lebih dalam? Sub-direktori di direktori Pages membantu menyusun rute Anda. Jadi jika kita menginginkan halaman Lihat Produk, kita dapat menyusun direktori Halaman kita seperti ini:

 /pages --| /products ----| index.vue ----| view.vue

Sekarang, jika kita menavigasi ke /products/view , kita akan melihat komponen view.vue di dalam direktori products. Jika kita menavigasi ke /products , kita akan melihat komponen index.vue di dalam direktori products.

Anda mungkin bertanya mengapa kami tidak membuat komponen products.vue di direktori pages saja seperti yang kami lakukan untuk halaman /about . Anda mungkin berpikir hasilnya akan sama, tetapi ada perbedaan antara kedua struktur tersebut. Mari kita tunjukkan ini dengan menambahkan halaman baru lainnya.

Katakanlah kami menginginkan halaman Tentang terpisah untuk setiap karyawan. Misalnya, mari buat halaman Tentang untuk saya. Itu harus ditempatkan di /about/ben-jones . Awalnya, kami dapat mencoba menyusun direktori Pages seperti ini:

 /pages --| about.vue --| /about ----| ben-jones.vue

Ketika kami mencoba mengakses /about/ben-jones , kami malah mendapatkan komponen about.vue , sama seperti /about . Apa yang terjadi di sini?

Menariknya, apa yang dilakukan Nuxt di sini adalah menghasilkan nested route . Struktur ini menyarankan bahwa Anda menginginkan rute /about permanen dan apa pun di dalam rute itu harus bersarang di area tampilannya sendiri. Dalam vue-router, ini akan ditandai dengan menetapkan komponen <router-view /> di dalam komponen about.vue . Di Nuxt, ini adalah konsep yang sama kecuali, sebagai ganti <router-view /> , kita cukup menggunakan <nuxt /> . Jadi mari perbarui komponen about.vue kita untuk memungkinkan rute bersarang:

 <template> <div> <h1>About Page</h1> <nuxt /> </div> </template>

Sekarang, ketika kita menavigasi ke /about , kita mendapatkan komponen about.vue yang kita miliki sebelumnya, hanya dengan sebuah judul. Namun, ketika kita menavigasi ke /about/ben-jones , kita malah memiliki judul dan komponen ben-jones.vue yang dirender di tempat <nuxt/> placeholder berada.

Ini bukanlah apa yang kami inginkan pada awalnya, tetapi gagasan memiliki halaman Tentang dengan daftar orang-orang yang, ketika diklik, mengisi bagian halaman dengan informasi mereka adalah konsep yang menarik, jadi mari kita biarkan apa adanya untuk saat ini . Jika Anda memang menginginkan opsi lain, maka yang akan kami lakukan hanyalah menyusun ulang direktori kami. Kita hanya perlu memindahkan komponen about.vue ke dalam direktori /about dan index.vue , sehingga struktur yang dihasilkan adalah:

 /pages --| /about ----| index.vue ----| ben-jones.vue

Terakhir, katakanlah kami ingin menggunakan parameter rute untuk mengambil produk tertentu. Misalnya, kami ingin dapat mengedit produk dengan menavigasi ke /products/edit/64 di mana 64 adalah product_id . Kita dapat melakukannya dengan cara berikut:

 /pages --| /products ----| /edit ------| _product_id.vue

Perhatikan garis bawah di awal komponen _product_id.vue —ini menandakan param rute yang kemudian dapat diakses pada objek $route.params atau pada objek params di Nuxt's Context (lebih lanjut tentang itu nanti). Perhatikan bahwa kunci untuk param akan menjadi nama komponen tanpa garis bawah awal—dalam hal ini, product_id —jadi cobalah untuk membuatnya unik di dalam proyek. Akibatnya, di _product_id.vue , kami mungkin memiliki sesuatu seperti:

 <template> <h1>Editing Product {{ $route.params.product_id }}</h1> </template>

Anda dapat mulai membayangkan tata letak yang lebih kompleks, yang akan merepotkan jika diatur menggunakan vue-router. Misalnya, kita dapat menggabungkan semua hal di atas menjadi rute seperti:

 /pages --| /categories ----| /_category_id ------| products.vue ------| /products --------| _product_id.vue

Tidak terlalu sulit untuk mempertimbangkan apa yang akan ditampilkan /categories/2/products/3 . Kami akan memiliki komponen products.vue dengan komponen _product_id.vue bersarang , dengan dua parameter rute: category_id dan product_id . Ini jauh lebih mudah untuk dipikirkan daripada konfigurasi router yang setara.

Sementara kita membahas topik ini, satu hal yang cenderung saya lakukan dalam konfigurasi router adalah menyiapkan pelindung router. Karena Nuxt sedang membangun router untuk kita, ini dapat dilakukan pada komponen itu sendiri dengan beforeRouteEnter . Jika Anda ingin memvalidasi parameter rute, Nuxt menyediakan metode komponen yang disebut validate . Jadi, jika Anda ingin memeriksa apakah product_id adalah angka sebelum mencoba merender komponen, Anda dapat menambahkan kode berikut ke tag skrip _product_id.vue :

 export default { validate ({ params }) { // Must be a number return /^\d+$/.test(params.product_id) } }

Sekarang, menavigasi ke /categories/2/products/someproduct menghasilkan 404 karena someproduct bukan angka yang valid.

Itu saja untuk direktori Pages. Mempelajari cara menyusun rute Anda dengan benar di direktori ini sangat penting, jadi menghabiskan sedikit waktu pada awalnya penting untuk mendapatkan hasil maksimal dari Nuxt. Jika Anda mencari ikhtisar singkat, selalu membantu untuk merujuk ke dokumen untuk perutean.

Jika Anda khawatir tidak bisa mengendalikan router, jangan khawatir. Pengaturan default ini berfungsi dengan baik untuk berbagai macam proyek, asalkan terstruktur dengan baik. Namun, ada beberapa kasus di mana Anda mungkin perlu menambahkan lebih banyak rute ke router daripada yang dihasilkan Nuxt secara otomatis untuk Anda atau merestrukturisasinya. Nuxt menyediakan cara untuk menyesuaikan instance router dalam konfigurasi, memungkinkan Anda untuk menambahkan rute baru dan menyesuaikan rute yang dihasilkan. Anda juga dapat mengedit fungsionalitas inti instans router, termasuk opsi tambahan yang ditambahkan oleh Nuxt. Jadi, jika Anda menemukan kasus tepi, Anda masih memiliki fleksibilitas untuk menemukan solusi yang tepat.

Toko

Nuxt dapat membangun toko Vuex Anda berdasarkan struktur direktori toko, mirip dengan direktori Pages. Jika Anda tidak membutuhkan toko, hapus saja direktorinya. Ada dua mode untuk toko, Klasik dan Modul.

Klasik mengharuskan Anda memiliki file index.js di direktori toko. Di sana Anda perlu mengekspor fungsi yang mengembalikan instance Vuex:

 import Vuex from 'vuex' const createStore = () => { return new Vuex.Store({ state: ..., mutations: ..., actions: ... }) } export default createStore

Ini memungkinkan Anda untuk membuat toko sesuka Anda, seperti menggunakan Vuex dalam proyek Vue normal.

Mode modul juga mengharuskan Anda membuat file index.js di direktori toko. Namun, file ini hanya perlu mengekspor status/mutasi/tindakan root untuk toko Vuex Anda. Contoh di bawah ini menentukan status root kosong:

 export const state = () => ({})

Kemudian, setiap file di direktori toko akan ditambahkan ke toko di namespace atau modulnya sendiri. Misalnya, mari kita buat tempat untuk menyimpan produk saat ini. Jika kita membuat file bernama product.js di direktori toko, maka bagian toko dengan namespace akan tersedia di $store.product . Berikut adalah contoh sederhana dari tampilan file tersebut:

 export const state = () => ({ _id: 0, title: 'Unknown', price: 0 }) export const actions = { load ({ commit }) { setTimeout( commit, 1000, 'update', { _id: 1, title: 'Product', price: 99.99 } ) } } export const mutations = { update (state, product) { Object.assign(state, product) } }

setTimeout dalam tindakan memuat mensimulasikan semacam panggilan API, yang akan memperbarui penyimpanan dengan respons; dalam hal ini, dibutuhkan satu detik. Sekarang, mari kita gunakan di halaman products/view :

 <template> <div> <h1>View Product {{ product._id }}</h1> <p>{{ product.title }}</p> <p>Price: {{ product.price }}</p> </div> </template> <script> import { mapState } from 'vuex' export default { created () { this.$store.dispatch('product/load') }, computed: { ...mapState(['product']) } } </script>

Beberapa hal yang perlu diperhatikan: Di sini, kami memanggil API palsu kami saat komponen dibuat. Anda dapat melihat bahwa tindakan product/load yang kami kirimkan diberi spasi nama di bawah Produk. Ini memperjelas dengan tepat bagian toko mana yang sedang kita tangani. Kemudian, dengan memetakan status ke properti komputasi lokal, kita dapat dengan mudah menggunakannya di template kita.

Ada masalah: Kami melihat status asli sebentar saat API berjalan. Nanti, kami akan menggunakan solusi yang disediakan oleh Nuxt untuk memperbaikinya (dikenal sebagai fetch ).

Untuk menekankan hal ini lagi, kami tidak pernah harus npm install vuex , karena sudah disertakan dalam paket Nuxt. Saat Anda menambahkan file index.js ke direktori toko, semua metode tersebut kemudian dibuka untuk Anda secara otomatis .

Itulah dua direktori utama yang dijelaskan; sisanya jauh lebih sederhana.

Komponen

Direktori Components berisi komponen yang dapat digunakan kembali seperti bilah navigasi, galeri gambar, pagination, tabel data, dll. Melihat komponen dalam direktori Pages diubah menjadi rute, Anda perlu tempat lain untuk menyimpan jenis komponen ini. Komponen ini dapat diakses di halaman atau komponen lain dengan mengimpornya:

 import ComponentName from ~/components/ComponentName.vue

Aktiva

Ini berisi aset yang tidak dikompilasi dan lebih berkaitan dengan cara Webpack memuat dan memproses file, bukan dengan cara kerja Nuxt. Jika Anda tertarik, saya sarankan membaca panduan di Readme.

Statis

Ini berisi file statis yang dipetakan ke direktori root situs Anda. Misalnya, menempatkan gambar bernama logo.png di direktori ini akan membuatnya tersedia di /logo.png . Ini bagus untuk file meta seperti robots.txt, favicon.ico, dan file lain yang Anda butuhkan tersedia.

Tata letak

Biasanya, dalam proyek Vue, Anda memiliki semacam komponen root, biasanya disebut App.vue . Di sinilah Anda dapat mengatur tata letak aplikasi (biasanya statis), yang mungkin menyertakan navbar, footer, dan kemudian area konten untuk vue-router Anda. Tata letak default melakukan hal itu dan disediakan untuk Anda di folder tata letak. Awalnya, yang dimilikinya hanyalah div dengan komponen <nuxt /> (yang setara dengan <router-view /> ) tetapi dapat ditata sesuka Anda. Misalnya, saya telah menambahkan bilah navigasi sederhana ke proyek contoh untuk navigasi di sekitar berbagai halaman demonstrasi.

Tata letak dapat diterapkan ke beberapa halaman.

Anda mungkin ingin memiliki tata letak yang berbeda untuk bagian tertentu dari aplikasi Anda. Mungkin Anda memiliki semacam CMS atau panel admin yang terlihat berbeda. Untuk mengatasi ini, buat tata letak baru di direktori Tata Letak. Sebagai contoh, mari buat tata letak admin-layout.vue yang hanya memiliki tag header tambahan dan tanpa navbar:

 <template> <div> <h1>Admin Layout</h1> <nuxt /> </div> </template>

Kemudian, kita dapat membuat halaman admin.vue di direktori Pages dan menggunakan properti yang disediakan oleh Nuxt bernama layout untuk menentukan nama (sebagai string) dari layout yang ingin kita gunakan untuk komponen tersebut:

 <template> <h1>Admin Page</h1> </template> <script> export default { layout: 'admin-layout' } </script>

Itu saja. Komponen halaman akan menggunakan tata letak default kecuali ditentukan, tetapi ketika Anda menavigasi ke /admin , sekarang menggunakan tata letak admin-layout.vue . Tentu saja, tata letak ini dapat dibagikan di beberapa layar admin jika Anda mau. Satu hal penting untuk diingat adalah layout harus mengandung elemen <nuxt /> .

Ada satu hal terakhir yang perlu diperhatikan tentang tata letak. Anda mungkin telah memperhatikan saat bereksperimen bahwa jika Anda mengetik URL yang tidak valid, Anda akan diperlihatkan halaman kesalahan. Halaman kesalahan ini sebenarnya adalah tata letak lain. Nuxt memiliki tata letak kesalahannya sendiri (kode sumber di sini), tetapi jika Anda ingin mengeditnya, buat saja tata letak error.vue dan itu akan digunakan sebagai gantinya. Peringatan di sini adalah bahwa tata letak kesalahan tidak boleh memiliki elemen <nuxt /> . Anda juga akan memiliki akses ke objek error pada komponen dengan beberapa informasi dasar untuk ditampilkan. (Ini dicetak di terminal yang menjalankan Nuxt jika Anda ingin memeriksanya.)

perangkat tengah

Middleware adalah fungsi yang dapat dijalankan sebelum merender halaman atau tata letak. Ada berbagai alasan Anda mungkin ingin melakukannya. Penjagaan rute adalah penggunaan yang populer di mana Anda dapat memeriksa toko Vuex untuk login yang valid atau memvalidasi beberapa parameter (alih-alih menggunakan metode validate pada komponen itu sendiri). Satu proyek yang saya kerjakan baru-baru ini menggunakan middleware untuk menghasilkan remah roti dinamis berdasarkan rute dan params.

Fungsi-fungsi ini bisa asinkron; hanya berhati-hatilah, karena tidak ada yang akan ditampilkan kepada pengguna sampai middleware diselesaikan. Mereka juga memiliki akses ke Nuxt's Context, yang akan saya jelaskan nanti.

Plugin

Direktori ini memungkinkan Anda untuk mendaftarkan plugin Vue sebelum aplikasi dibuat. Ini memungkinkan plugin untuk dibagikan ke seluruh aplikasi Anda pada instance Vue dan dapat diakses di komponen apa pun.

Sebagian besar plugin utama memiliki versi Nuxt yang dapat dengan mudah didaftarkan ke instance Vue dengan mengikuti dokumen mereka. Namun, akan ada keadaan ketika Anda akan mengembangkan plugin atau perlu mengadaptasi plugin yang ada untuk tujuan ini. Contoh yang saya pinjam dari dokumen menunjukkan bagaimana melakukan ini untuk vue-notifications . Pertama, kita perlu menginstal paket:

 npm install vue-notifications --save

Kemudian buat file di direktori plugins bernama vue-notifications.js dan sertakan yang berikut ini:

 import Vue from 'vue' import VueNotifications from 'vue-notifications' Vue.use(VueNotifications)

Sangat mirip dengan cara Anda mendaftarkan plugin di lingkungan Vue normal. Kemudian edit file nuxt.config.js di root proyek Anda dan tambahkan entri berikut ke objek module.exports:

 plugins: ['~/plugins/vue-notifications']

Itu dia. Sekarang Anda dapat menggunakan vue-notifications di seluruh aplikasi Anda. Contohnya ada di /plugin dalam contoh proyek.

Jadi itu melengkapi ikhtisar struktur direktori. Tampaknya banyak yang harus dipelajari, tetapi jika Anda mengembangkan aplikasi Vue, Anda sudah menyiapkan logika yang sama. Nuxt membantu mengabstraksikan penyiapan dan membantu Anda fokus pada pembangunan.

Nuxt melakukan lebih dari sekadar membantu dalam pengembangan. Ini melengkapi komponen Anda dengan menyediakan fungsionalitas ekstra.

Komponen Supercharged Nuxt

Ketika saya pertama kali mulai meneliti Nuxt , saya terus membaca tentang bagaimana komponen Halaman diisi ulang . Kedengarannya bagus, tetapi tidak segera jelas apa artinya dan apa manfaatnya.

Artinya, semua komponen Halaman memiliki metode tambahan yang dapat digunakan Nuxt untuk menyediakan fungsionalitas tambahan. Faktanya, kami telah melihat salah satu dari ini sebelumnya ketika kami menggunakan metode validate untuk memeriksa parameter dan mengarahkan ulang pengguna jika mereka tidak valid.

Dua yang utama yang digunakan dalam proyek Nuxt adalah metode asyncData dan fetch . Keduanya sangat mirip dalam konsep, dijalankan secara asinkron sebelum komponen dibuat, dan dapat digunakan untuk mengisi data komponen dan penyimpanan. Mereka juga memungkinkan halaman untuk sepenuhnya dirender di server sebelum mengirimkannya ke klien bahkan ketika kita harus menunggu beberapa database atau panggilan API.

Apa perbedaan antara asyncData dan fetch ?

  • asyncData digunakan untuk mengisi data komponen Halaman. Saat Anda mengembalikan objek, objek tersebut kemudian digabungkan dengan output data sebelum dirender.
  • fetch digunakan untuk mengisi Vuex Store. Jika Anda mengembalikan janji, Nuxt akan menunggu hingga diselesaikan sebelum rendering.

Jadi mari kita gunakan ini dengan baik. Ingat sebelumnya pada halaman /products/view kami memiliki masalah di mana status awal toko ditampilkan sebentar saat panggilan API palsu kami sedang dilakukan? Salah satu cara untuk memperbaikinya adalah memiliki boolean yang disimpan di komponen atau di Store seperti loading = true dan kemudian menampilkan komponen pemuatan saat panggilan API selesai. Setelah itu, kita akan mengatur loading = false dan menampilkan datanya.

Sebagai gantinya, mari gunakan fetch untuk mengisi Store sebelum rendering. Di halaman baru bernama /products/view-async , mari ubah metode yang created menjadi fetch ; yang harus bekerja, kan?

 export default { fetch () { // Unfortunately the below line throws an error // because 'this.$store' is undefined... this.$store.dispatch('product/load') }, computed: {...} }

Berikut tangkapannya: Metode "supercharged" ini berjalan sebelum komponen dibuat, jadi this tidak menunjuk ke komponen dan tidak ada apa pun di dalamnya yang dapat diakses. Jadi bagaimana kita mengakses Toko di sini?

API Konteks

Tentu saja, ada solusi. Pada semua metode Nuxt, Anda diberikan argumen (biasanya yang pertama) berisi objek yang sangat berguna yang disebut Context. Ini adalah semua yang Anda perlukan referensi di seluruh aplikasi, artinya kita tidak perlu menunggu Vue untuk membuat referensi tersebut pada komponen terlebih dahulu.

Saya akan sangat menyarankan untuk memeriksa dokumen Konteks untuk melihat apa yang tersedia. Beberapa yang berguna adalah app , di mana Anda dapat mengakses semua plugin Anda, redirect , yang dapat digunakan untuk mengubah rute, error untuk menampilkan halaman kesalahan, dan beberapa yang cukup jelas seperti route , query , dan store .

Jadi, untuk mengakses Store, kita dapat merusak Context dan mengekstrak Store darinya. Kami juga perlu memastikan bahwa kami mengembalikan janji sehingga Nuxt dapat menunggu untuk diselesaikan sebelum merender komponen, jadi kami juga perlu membuat sedikit penyesuaian pada tindakan Store kami.

 // Component export default { fetch ({ store }) { return store.dispatch('product/load') }, computed: {...} } // Store Action load ({ commit }) { return new Promise(resolve => { setTimeout(() => { commit('update', { _id: 1, title: 'Product', price: 99.99 }) resolve() }, 1000) }) }

Anda bisa menggunakan async/await atau metode lain tergantung pada gaya pengkodean Anda, tetapi konsepnya sama—kami memberi tahu Nuxt untuk memastikan panggilan API selesai dan Store diperbarui dengan hasilnya sebelum mencoba merender komponen. Jika Anda mencoba menavigasi ke /products/view-async , Anda tidak akan melihat kilatan konten di mana produk berada dalam keadaan awalnya.

Anda dapat membayangkan betapa bergunanya ini di aplikasi Vue apa pun bahkan tanpa SSR. Context juga tersedia untuk semua middlewares serta metode Nuxt lainnya seperti NuxtServerInit yang merupakan tindakan penyimpanan khusus yang berjalan sebelum Store diinisialisasi (contohnya ada di bagian berikutnya)

Pertimbangan Saat Menggunakan SSR

Saya yakin banyak (termasuk saya sendiri) yang mulai menggunakan teknologi seperti Nuxt sambil memperlakukannya seperti proyek Vue lainnya akhirnya menemui jalan buntu di mana sesuatu yang kita tahu biasanya berfungsi tampaknya mustahil di Nuxt. Karena lebih banyak peringatan ini didokumentasikan, akan lebih mudah untuk diatasi, tetapi hal utama yang perlu dipertimbangkan ketika memulai debug adalah bahwa klien dan server adalah dua entitas yang terpisah.

Saat Anda mengakses halaman pada awalnya, permintaan dikirim ke Nuxt, server membangun sebanyak mungkin halaman itu dan aplikasi lainnya, lalu server mengirimkannya kepada Anda. Kemudian tanggung jawab ada pada klien untuk melanjutkan navigasi dan memuat potongan sesuai kebutuhan.

Kami ingin server melakukan sebanyak mungkin terlebih dahulu, tetapi terkadang server tidak memiliki akses ke informasi yang dibutuhkan, yang mengakibatkan pekerjaan dilakukan di sisi klien. Atau lebih buruk lagi, ketika konten akhir yang disajikan oleh klien berbeda dari yang diharapkan server, klien diminta untuk membangunnya kembali dari awal. Ini adalah indikasi besar bahwa ada sesuatu yang salah dengan logika aplikasi. Untungnya, kesalahan akan dibuat di konsol browser Anda (dalam mode pengembangan) jika ini mulai terjadi.

Mari kita ambil contoh bagaimana memecahkan masalah umum, manajemen sesi. Bayangkan Anda memiliki aplikasi Vue tempat Anda dapat masuk ke akun, dan sesi Anda disimpan menggunakan token (JWT, misalnya) yang Anda putuskan untuk disimpan di localStorage . Saat pertama kali mengakses situs, Anda ingin mengautentikasi token tersebut terhadap API, yang mengembalikan beberapa info pengguna dasar jika valid dan menyimpan informasi tersebut di Store.

Setelah membaca dokumen Nuxt, Anda melihat bahwa ada metode praktis yang disebut NuxtServerInit yang memungkinkan Anda untuk mengisi Store secara asinkron sekali pada pemuatan awal. Itu terdengar sempurna! Jadi, Anda membuat modul pengguna di Store dan menambahkan tindakan yang sesuai di file index.js di direktori Store:

 export const actions = { nuxtServerInit ({ dispatch }) { // localStorage should work, right? const token = localStorage.getItem('token') if (token) return dispatch('user/load', token) } }

Saat Anda menyegarkan halaman, Anda mendapatkan kesalahan, localStorage is not defined . Memikirkan di mana ini terjadi, masuk akal. Metode ini dijalankan di server, tidak tahu apa yang disimpan di localStorage pada klien; sebenarnya, ia bahkan tidak tahu apa itu "localStorage"! Jadi itu bukan pilihan.

Server mencoba mengeksekusi localStorage.getItem('token') tetapi memunculkan kesalahan, lalu keterangan di bawah menjelaskan masalahnya.

Jadi apa solusinya? Ada beberapa, sebenarnya. Anda bisa meminta klien untuk menginisialisasi Store tetapi akhirnya kehilangan manfaat SSR karena klien akhirnya melakukan semua pekerjaan. Anda dapat mengatur sesi di server dan kemudian menggunakannya untuk mengautentikasi pengguna, tetapi itu adalah lapisan lain yang harus disiapkan. Apa yang paling mirip dengan metode localStorage adalah menggunakan cookie sebagai gantinya.

Nuxt memiliki akses ke cookie karena cookie dikirim dengan permintaan dari klien ke server. Seperti metode Nuxt lainnya, nuxtServerInit memiliki akses ke Konteks, kali ini sebagai argumen kedua karena yang pertama dicadangkan untuk penyimpanan. Pada Context, kita dapat mengakses objek req , yang menyimpan semua header dan informasi lain dari permintaan klien. (Ini akan sangat familiar jika Anda pernah menggunakan Node.js.)

Jadi setelah menyimpan token dalam cookie (disebut "token", dalam hal ini), mari kita akses di server.

 import Cookie from 'cookie' export const actions = { nuxtServerInit ({ dispatch }, { req }) { const cookies = Cookie.parse(req.headers.cookie || '') const token = cookies['token'] || '' if (token) return dispatch('user/load', token) } }

Solusi sederhana, tetapi solusi yang mungkin tidak langsung terlihat. Belajar memikirkan di mana tindakan tertentu terjadi (klien, server, atau keduanya) dan apa yang mereka akses membutuhkan waktu, tetapi manfaatnya sepadan.

Penyebaran

Penerapan dengan Nuxt sangat sederhana. Menggunakan basis kode yang sama, Anda dapat membuat aplikasi SSR, aplikasi satu halaman, atau halaman statis.

Aplikasi Render sisi server (Aplikasi SSR)

Ini mungkin yang Anda tuju saat menggunakan Nuxt. Konsep dasar untuk penerapan di sini adalah menjalankan proses build pada platform apa pun yang Anda pilih dan mengatur beberapa konfigurasi. Saya akan menggunakan contoh Heroku dari dokumen:

Pertama, siapkan skrip untuk Heroku di package.json :

 "scripts": { "dev": "nuxt", "build": "nuxt build", "start": "nuxt start", "heroku-postbuild": "npm run build" }

Kemudian atur lingkungan Heroku menggunakan heroku-cli (petunjuk pengaturan di sini:

 # set Heroku variables heroku config:set NPM_CONFIG_PRODUCTION=false heroku config:set HOST=0.0.0.0 heroku config:set NODE_ENV=production # deploy git push heroku master

Itu dia. Sekarang aplikasi SSR Vue Anda siap untuk dilihat dunia. Platform lain memiliki pengaturan yang berbeda, tetapi prosesnya serupa. Metode penyebaran resmi yang saat ini terdaftar adalah:

  • Sekarang
  • Dokku (Lautan Digital)
  • Nginx

Aplikasi satu halaman (SPA)

Jika Anda ingin memanfaatkan beberapa fitur tambahan yang disediakan Nuxt tetapi menghindari server mencoba merender halaman, Anda dapat menggunakan sebagai SPA sebagai gantinya.

Pertama, yang terbaik adalah menguji aplikasi Anda tanpa SSR karena secara default npm run dev berjalan dengan SSR aktif. Untuk mengubahnya, edit file nuxt.config.js dan tambahkan opsi berikut:

 mode: 'spa',

Sekarang, ketika Anda menjalankan npm run dev , SSR akan dimatikan dan aplikasi akan berjalan sebagai SPA untuk Anda uji. Pengaturan ini juga memastikan tidak ada build mendatang yang menyertakan SSR.

Jika semuanya terlihat baik-baik saja, maka penerapannya sama persis dengan aplikasi SSR. Ingatlah bahwa Anda perlu mengatur mode: 'spa' terlebih dahulu agar proses pembuatan tahu bahwa Anda menginginkan SPA.

Halaman Statis

Jika Anda tidak ingin berurusan dengan server sama sekali dan ingin membuat halaman untuk digunakan dengan layanan hosting statis seperti Surge atau Netlify, maka ini adalah opsi untuk dipilih. Ingatlah bahwa, tanpa server, Anda tidak akan dapat mengakses req dan res dalam Konteks, jadi jika kode Anda bergantung padanya, pastikan untuk mengakomodasinya. Misalnya, saat membuat proyek contoh, fungsi nuxtServerInit kesalahan karena mencoba mengambil token dari cookie di header permintaan. Dalam proyek ini, tidak masalah, karena data itu tidak digunakan di mana pun, tetapi dalam aplikasi nyata, perlu ada cara alternatif untuk mengakses data itu.

Setelah itu diurutkan, penyebaran menjadi mudah. Satu hal yang mungkin perlu Anda ubah terlebih dahulu adalah menambahkan opsi sehingga perintah nuxt generate juga akan membuat file fallback. File ini akan meminta layanan hosting untuk membiarkan Nuxt menangani perutean daripada layanan hosting, sehingga menimbulkan kesalahan 404. Untuk melakukannya, tambahkan baris berikut ke nuxt.config.js :

 generate: { fallback: true },

Berikut adalah contoh menggunakan Netlify, yang saat ini tidak ada dalam dokumen Nuxt. Ingatlah bahwa jika ini adalah pertama kalinya Anda menggunakan netlify-cli , Anda akan diminta untuk mengautentikasi:

 # install netlify-cli globally npm install netlify-cli -g # generate the application (outputs to dist/ folder) npm run generate # deploy netlify deploy dist

Ini sesederhana itu! Seperti yang disebutkan di awal artikel, ada versi proyek ini di sini. Ada juga dokumentasi penerapan resmi untuk layanan berikut di bawah ini:

  • Lonjakan
  • Halaman GitHub

Belajarlah lagi

Nuxt memperbarui dengan cepat, dan ini hanya sebagian kecil dari fitur yang ditawarkannya. Saya harap artikel ini mendorong Anda untuk mencobanya dan melihat apakah artikel ini dapat membantu meningkatkan kemampuan aplikasi Vue Anda, memungkinkan Anda untuk berkembang lebih cepat dan memanfaatkan fitur-fitur canggihnya.

Jika Anda mencari informasi lebih lanjut, silakan lihat tautan resmi Nuxt:

  • Dokumentasi
  • Tempat bermain
  • GitHub
  • FAQ

Looking to up your JavaScript game? Try reading The Comprehensive Guide to JavaScript Design Patterns by fellow Toptaler Marko Mišura.