Menambahkan Fungsi Dinamis Dan Async Ke Situs JAMstack

Diterbitkan: 2022-03-10
Ringkasan cepat Melewati server dan menggunakan JAMstack untuk membangun dan mengirimkan situs web dan aplikasi dapat menghemat waktu, uang, dan sakit kepala dengan mengizinkan kami mengirimkan hanya aset statis pada CDN. Tetapi pertukaran dari membuang penerapan berbasis server tradisional berarti bahwa pendekatan standar untuk interaksi dinamis dan asinkron di situs dan aplikasi kami tidak tersedia lagi.

Apakah itu berarti bahwa situs JAMstack tidak dapat menangani interaksi dinamis? Tentu saja tidak!

Situs JAMstack sangat bagus untuk membuat interaksi asinkron yang sangat dinamis. Dengan beberapa penyesuaian kecil pada cara kita berpikir tentang kode kita, kita dapat membuat interaksi yang menyenangkan dan mendalam hanya dengan menggunakan aset statis!

Semakin umum melihat situs web yang dibuat menggunakan JAMstack — yaitu, situs web yang dapat disajikan sebagai file HTML statis yang dibuat dari JavaScript, Markup, dan API. Perusahaan menyukai JAMstack karena mengurangi biaya infrastruktur, mempercepat pengiriman, dan menurunkan hambatan untuk peningkatan kinerja dan keamanan karena pengiriman aset statis menghilangkan kebutuhan untuk penskalaan server atau menjaga agar basis data tetap tersedia (yang juga berarti tidak ada server atau basis data yang dapat diretas). Pengembang menyukai JAMstack karena mengurangi kerumitan membuat situs web aktif di internet: tidak ada server untuk dikelola atau disebarkan; kita dapat menulis kode front-end dan itu hanya ditayangkan , seperti sulap .

(“Sihir” dalam hal ini adalah penerapan statis otomatis, yang tersedia secara gratis dari sejumlah perusahaan, termasuk Netlify, tempat saya bekerja.)

Tetapi jika Anda menghabiskan banyak waktu berbicara dengan pengembang tentang JAMstack, pertanyaan apakah JAMstack dapat menangani Aplikasi Web Serius atau tidak akan muncul. Lagi pula, situs JAMstack adalah situs statis, bukan? Dan bukankah situs statis sangat terbatas dalam apa yang dapat mereka lakukan?

Ini adalah kesalahpahaman yang sangat umum, dan dalam artikel ini kita akan menyelami dari mana kesalahpahaman itu berasal, melihat kemampuan JAMstack, dan menelusuri beberapa contoh penggunaan JAMstack untuk membangun Aplikasi Web Serius.

Dasar-dasar JAMstack

Phil Hawksworth menjelaskan apa sebenarnya arti JAMStack dan kapan masuk akal untuk menggunakannya dalam proyek Anda, serta bagaimana hal itu memengaruhi perkakas dan arsitektur front-end. Baca artikel terkait →

Lebih banyak setelah melompat! Lanjutkan membaca di bawah ini

Apa yang Membuat Situs JAMstack “Statis”?

Peramban web saat ini memuat file HTML, CSS, dan JavaScript, seperti yang mereka lakukan di tahun 90-an.

Situs JAMstack, pada intinya, adalah folder yang penuh dengan file HTML, CSS, dan JavaScript.

Ini adalah "aset statis", artinya kita tidak memerlukan langkah perantara untuk membuatnya (misalnya, proyek PHP seperti WordPress memerlukan server untuk menghasilkan HTML pada setiap permintaan).

Itulah kekuatan sebenarnya dari JAMstack: tidak memerlukan infrastruktur khusus untuk bekerja. Anda dapat menjalankan situs JAMstack di komputer lokal Anda, dengan meletakkannya di jaringan pengiriman konten (CDN) pilihan Anda, menghostingnya dengan layanan seperti GitHub Pages — Anda bahkan dapat menarik dan melepas folder ke klien FTP favorit Anda untuk mengunggahnya ke hosting bersama.

Aset Statis Tidak Selalu Berarti Pengalaman Statis

Karena situs JAMstack terbuat dari file statis, mudah untuk mengasumsikan bahwa pengalaman di situs tersebut, Anda tahu, static . Tapi bukan itu masalahnya!

JavaScript mampu melakukan banyak hal dinamis. Bagaimanapun, kerangka kerja JavaScript modern adalah file statis setelah kita melewati langkah pembuatan — dan ada ratusan contoh pengalaman situs web yang sangat dinamis yang didukung olehnya.

Ada kesalahpahaman umum bahwa "statis" berarti tidak fleksibel atau tetap. Tapi semua yang "statis" benar-benar berarti dalam konteks "situs statis" adalah bahwa browser tidak memerlukan bantuan apa pun untuk mengirimkan konten mereka — mereka dapat menggunakannya secara asli tanpa server yang menangani langkah pemrosesan terlebih dahulu.

Atau, dengan kata lain:

“Aset statis” tidak berarti aplikasi statis; itu berarti tidak ada server yang diperlukan.

Bisakah JAMstack Melakukan Itu?

Jika seseorang bertanya tentang membangun aplikasi baru, biasanya akan melihat saran untuk pendekatan JAMstack seperti Gatsby, Eleventy, Nuxt, dan alat serupa lainnya. Keberatan yang muncul sama-sama umum: "generator situs statis tidak dapat melakukan _______", di mana _______ adalah sesuatu yang dinamis.

Namun — seperti yang telah kita bahas di bagian sebelumnya — situs JAMstack dapat menangani konten dan interaksi dinamis!

Berikut daftar lengkap hal-hal yang saya telah berulang kali mendengar orang mengklaim JAMstack tidak dapat menangani bahwa itu pasti bisa:

  • Muat data secara asinkron
  • Menangani pemrosesan file, seperti memanipulasi gambar
  • Membaca dari dan menulis ke database
  • Tangani otentikasi pengguna dan lindungi konten di balik login

Di bagian berikut, kita akan melihat cara mengimplementasikan setiap alur kerja ini di situs JAMstack.

Jika Anda tidak sabar untuk melihat JAMstack dinamis beraksi, Anda dapat melihat demonya terlebih dahulu, lalu kembali dan pelajari cara kerjanya.

Catatan tentang demo :

Demo ini ditulis tanpa kerangka kerja apa pun. Mereka hanya HTML, CSS, dan JavaScript standar. Mereka dibuat dengan mempertimbangkan browser modern (misalnya Chrome, Firefox, Safari, Edge) dan memanfaatkan fitur yang lebih baru seperti modul JavaScript, template HTML, dan Fetch API. Tidak ada polyfill yang ditambahkan, jadi jika Anda menggunakan browser yang tidak didukung, demo mungkin akan gagal.

Muat Data Dari API Pihak Ketiga Secara Asinkron

“Bagaimana jika saya perlu mendapatkan data baru setelah file statis saya dibuat?”

Di JAMstack, kita dapat memanfaatkan banyak pustaka permintaan asinkron, termasuk Fetch API bawaan, untuk memuat data menggunakan JavaScript di titik mana pun.

Demo: Cari API Pihak Ketiga Dari Situs JAMstack

Skenario umum yang memerlukan pemuatan asinkron adalah ketika konten yang kita butuhkan bergantung pada input pengguna. Misalnya, jika kita membuat halaman pencarian untuk Rick & Morty API , kita tidak tahu konten apa yang akan ditampilkan sampai seseorang memasukkan istilah pencarian.

Untuk mengatasinya, kita perlu:

  1. Buat formulir di mana orang dapat mengetikkan istilah pencarian mereka,
  2. Dengarkan pengiriman formulir,
  3. Dapatkan istilah pencarian dari pengiriman formulir,
  4. Kirim permintaan asinkron ke Rick & Morty API menggunakan istilah pencarian,
  5. Menampilkan hasil permintaan pada halaman.

Pertama, kita perlu membuat formulir dan elemen kosong yang akan berisi hasil pencarian kita, yang terlihat seperti ini:

 <form> <label for="name">Find characters by name</label> <input type="text" name="name" required /> <button type="submit">Search</button> </form> <ul></ul>

Selanjutnya, kita perlu menulis fungsi yang menangani pengiriman formulir. Fungsi ini akan:

  • Cegah perilaku pengiriman formulir default
  • Dapatkan istilah pencarian dari input formulir
  • Gunakan Fetch API untuk mengirim permintaan ke Rick & Morty API menggunakan istilah pencarian
  • Panggil fungsi pembantu yang menampilkan hasil pencarian di halaman

Kita juga perlu menambahkan event listener pada formulir untuk event submit yang memanggil fungsi handler kita.

Berikut tampilan kode tersebut secara keseluruhan:

 <script type="module"> import showResults from './show-results.js'; const form = document.querySelector('form'); const handleSubmit = async event => { event.preventDefault(); // get the search term from the form input const name = form.elements['name'].value; // send a request to the Rick & Morty API based on the user input const characters = await fetch( `https://rickandmortyapi.com/api/character/?name=${name}`, ) .then(response => response.json()) .catch(error => console.error(error)); // add the search results to the DOM showResults(characters.results); }; form.addEventListener('submit', handleSubmit); </script>

Catatan: untuk tetap fokus pada perilaku JAMstack dinamis, kita tidak akan membahas bagaimana fungsi utilitas seperti showResults ditulis. Namun, kode tersebut dikomentari secara menyeluruh, jadi periksa sumbernya untuk mempelajari cara kerjanya!

Dengan kode ini, kami dapat memuat situs kami di browser dan kami akan melihat formulir kosong tanpa hasil yang menunjukkan:

Formulir pencarian kosong
Formulir pencarian kosong (Pratinjau besar)

Jika kita memasukkan nama karakter (misalnya "rick") dan klik "search", kita melihat daftar karakter yang namanya mengandung "rick" ditampilkan:

Formulir pencarian diisi dengan "rick" dengan karakter bernama "Rick" ditampilkan di bawah ini.
Kami melihat hasil pencarian setelah formulir diisi. (Pratinjau besar)

Hai! Apakah situs statis itu hanya memuat data secara dinamis? Ember suci!

Anda dapat mencobanya sendiri di demo langsung, atau lihat kode sumber lengkap untuk detail lebih lanjut.

Tangani Tugas Komputasi Mahal dari Perangkat Pengguna

Di banyak aplikasi, kita perlu melakukan hal-hal yang cukup menguras sumber daya, seperti memproses gambar. Meskipun beberapa dari jenis operasi ini hanya mungkin menggunakan JavaScript sisi klien, itu tidak selalu merupakan ide yang bagus untuk membuat perangkat pengguna Anda melakukan semua itu. Jika mereka menggunakan perangkat berdaya rendah atau mencoba untuk memperpanjang 5% masa pakai baterai terakhir mereka, membuat perangkat mereka melakukan banyak pekerjaan mungkin akan menjadi pengalaman yang membuat mereka frustrasi.

Jadi, apakah itu berarti aplikasi JAMstack kurang beruntung? Tidak semuanya!

"A" di JAMstack adalah singkatan dari API. Ini berarti kami dapat mengirimkan pekerjaan itu ke API dan menghindari memutar kipas komputer pengguna kami ke pengaturan "arahkan".

"Tapi tunggu," Anda mungkin berkata. “Jika aplikasi kita perlu melakukan pekerjaan kustom, dan pekerjaan itu membutuhkan API, bukankah itu berarti kita sedang membangun server?”

Berkat kekuatan fungsi tanpa server, kami tidak perlu melakukannya!

Fungsi tanpa server (juga disebut "fungsi lambda") adalah semacam API tanpa memerlukan boilerplate server. Kami dapat menulis fungsi JavaScript lama yang sederhana, dan semua pekerjaan penerapan, penskalaan, perutean, dan sebagainya diturunkan ke penyedia pilihan tanpa server kami.

Menggunakan fungsi tanpa server tidak berarti tidak ada server; itu hanya berarti bahwa kita tidak perlu memikirkan server.

Fungsi tanpa server adalah selai kacang bagi JAMstack kami: mereka membuka seluruh dunia fungsionalitas dinamis bertenaga tinggi tanpa pernah meminta kami untuk berurusan dengan kode server atau devops.

Demo: Mengonversi Gambar Menjadi Skala Abu-abu

Mari kita asumsikan kita memiliki aplikasi yang perlu:

  • Unduh gambar dari URL
  • Ubah gambar itu menjadi skala abu-abu
  • Unggah gambar yang dikonversi ke repo GitHub

Sejauh yang saya tahu, tidak ada cara untuk melakukan konversi gambar seperti itu sepenuhnya di browser — dan bahkan jika ada, itu adalah hal yang cukup intensif sumber daya untuk dilakukan, jadi kami mungkin tidak ingin membebani pengguna kami ' perangkat.

Sebagai gantinya, kami dapat mengirimkan URL untuk dikonversi ke fungsi tanpa server, yang akan melakukan pekerjaan berat bagi kami dan mengirim kembali URL ke gambar yang dikonversi.

Untuk fungsi tanpa server kami, kami akan menggunakan Fungsi Netlify. Dalam kode situs kami, kami menambahkan folder di tingkat root yang disebut "fungsi" dan membuat file baru bernama "convert-image.js" di dalamnya. Kemudian kita menulis apa yang disebut handler, yang menerima dan — seperti yang mungkin sudah Anda duga — menangani permintaan ke fungsi tanpa server kami.

Untuk mengonversi gambar, tampilannya seperti ini:

 exports.handler = async event => { // only try to handle POST requests if (event.httpMethod !== 'POST') { return { statusCode: 404, body: '404 Not Found' }; } try { // get the image URL from the POST submission const { imageURL } = JSON.parse(event.body); // use a temporary directory to avoid intermediate file cruft // see https://www.npmjs.com/package/tmp const tmpDir = tmp.dirSync(); const convertedPath = await convertToGrayscale(imageURL, tmpDir); // upload the processed image to GitHub const response = await uploadToGitHub(convertedPath, tmpDir.name); return { statusCode: 200, body: JSON.stringify({ url: response.data.content.download_url, }), }; } catch (error) { return { statusCode: 500, body: JSON.stringify(error.message), }; } };

Fungsi ini melakukan hal berikut:

  1. Memeriksa untuk memastikan permintaan dikirim menggunakan metode HTTP POST
  2. Ambil URL gambar dari badan POST
  3. Membuat direktori sementara untuk menyimpan file yang akan dibersihkan setelah fungsi selesai dijalankan
  4. Memanggil fungsi pembantu yang mengubah gambar menjadi skala abu-abu
  5. Memanggil fungsi pembantu yang mengunggah gambar yang dikonversi ke GitHub
  6. Mengembalikan objek respons dengan kode status HTTP 200 dan URL gambar yang baru diunggah

Catatan : Kami tidak akan membahas cara kerja helper untuk konversi gambar atau mengunggah ke GitHub, tetapi kode sumber dikomentari dengan baik sehingga Anda dapat melihat cara kerjanya.

Selanjutnya, kita perlu menambahkan formulir yang akan digunakan untuk mengirimkan URL untuk diproses dan tempat untuk menampilkan sebelum dan sesudah:

 <form action="/.netlify/functions/convert-image" method="POST" > <label for="imageURL">URL of an image to convert</label> <input type="url" name="imageURL" required /> <button type="submit">Convert</button> </form> <div></div>

Terakhir, kita perlu menambahkan pendengar acara ke formulir sehingga kita dapat mengirimkan URL ke fungsi tanpa server untuk diproses:

 <script type="module"> import showResults from './show-results.js'; const form = document.querySelector('form'); form.addEventListener('submit', event => { event.preventDefault(); // get the image URL from the form const imageURL = form.elements['imageURL'].value; // send the image off for processing const promise = fetch('/.netlify/functions/convert-image', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ imageURL }), }) .then(result => result.json()) .catch(error => console.error(error)); // do the work to show the result on the page showResults(imageURL, promise); }); </script>

Setelah menyebarkan situs (bersama dengan folder "fungsi" barunya) ke Netlify dan/atau memulai Netlify Dev di CLI kami, kami dapat melihat formulir di browser kami:

Formulir konversi gambar kosong
Formulir kosong yang menerima URL gambar (Pratinjau besar)

Jika kita menambahkan URL gambar ke formulir dan mengklik "konversi", kita akan melihat "memproses..." sejenak saat konversi terjadi, kemudian kita akan melihat gambar asli dan rekan skala abu-abunya yang baru dibuat:

Formulir diisi dengan URL gambar, menunjukkan gambar asli di bawah di sebelah kiri dan gambar yang dikonversi ke kanan
Gambar diubah dari warna penuh menjadi skala abu-abu. (Pratinjau besar)

Oh dan! Situs JAMstack kami baru saja menangani beberapa bisnis yang cukup serius dan kami tidak perlu memikirkan server sekali pun atau menguras baterai pengguna kami!

Gunakan Database Untuk Menyimpan Dan Mengambil Entri

Di banyak aplikasi, kita pasti akan membutuhkan kemampuan untuk menyimpan input pengguna. Dan itu berarti kita membutuhkan database.

Anda mungkin berpikir, “Jadi begitu, kan? Jignya naik? Tentunya situs JAMstack — yang Anda beri tahu kami hanyalah kumpulan file dalam folder — tidak dapat terhubung ke database!”

Au kontrair.

Seperti yang kita lihat di bagian sebelumnya, fungsi tanpa server memberi kita kemampuan untuk melakukan segala macam hal hebat tanpa perlu membuat server sendiri.

Demikian pula, kita dapat menggunakan alat database-as-a-service (DBaaS) (seperti Fauna) untuk membaca dan menulis ke database tanpa harus menyiapkan atau menghostingnya sendiri.

Alat DBaaS secara besar-besaran menyederhanakan proses pengaturan database untuk situs web: membuat database baru semudah menentukan jenis data yang ingin kita simpan. Alat-alat tersebut secara otomatis menghasilkan semua kode untuk mengelola operasi buat, baca, perbarui, dan hapus (CRUD) dan membuatnya tersedia untuk kita gunakan melalui API, jadi kita tidak harus benar-benar mengelola database; kita tinggal menggunakannya .

Demo: Buat Halaman Petisi

Jika kita ingin membuat aplikasi kecil untuk mengumpulkan tanda tangan digital untuk petisi, kita perlu menyiapkan database untuk menyimpan tanda tangan tersebut dan mengizinkan halaman membacanya untuk ditampilkan.

Untuk demo ini kami akan menggunakan Fauna sebagai penyedia DBaaS kami. Kami tidak akan membahas lebih dalam tentang cara kerja Fauna, tetapi untuk menunjukkan sedikit upaya yang diperlukan untuk menyiapkan basis data, mari buat daftar setiap langkah dan klik untuk mendapatkan basis data yang siap digunakan:

  1. Buat akun Fauna di https://fauna.com
  2. Klik "buat database baru"
  3. Beri nama database (misalnya "dynamic-jamstack-demos")
  4. Klik "buat"
  5. Klik "keamanan" di menu sebelah kiri di halaman berikutnya
  6. Klik "kunci baru"
  7. Ubah dropdown peran menjadi "Server"
  8. Tambahkan nama untuk kunci (misalnya "Demo JAMstack Dinamis")
  9. Simpan kunci di tempat yang aman untuk digunakan dengan aplikasi
  10. Klik "simpan"
  11. Klik "GraphQL" di menu sebelah kiri
  12. Klik "impor skema"
  13. Unggah file bernama db-schema.gql yang berisi kode berikut:
 type Signature { name: String! } type Query { signatures: [Signature!]! }

Setelah kami mengunggah skema, basis data kami siap digunakan. (Dengan serius.)

Tiga belas langkah itu banyak, tetapi dengan tiga belas langkah itu, kami baru saja mendapatkan database, GraphQL API, manajemen kapasitas otomatis, penskalaan, penerapan, keamanan, dan banyak lagi — semuanya ditangani oleh pakar database. Gratis. Apa waktu untuk hidup!

Untuk mencobanya, opsi "GraphQL" di menu sebelah kiri memberi kita penjelajah GraphQL dengan dokumentasi tentang kueri dan mutasi yang tersedia yang memungkinkan kita melakukan operasi CRUD.

Catatan : Kami tidak akan membahas detail tentang kueri dan mutasi GraphQL dalam posting ini, tetapi Eve Porcello menulis pengantar yang sangat baik untuk mengirim kueri dan mutasi GraphQL jika Anda menginginkan primer tentang cara kerjanya.

Dengan database siap digunakan, kita dapat membuat fungsi tanpa server yang menyimpan tanda tangan baru dalam database:

 const qs = require('querystring'); const graphql = require('./util/graphql'); exports.handler = async event => { try { // get the signature from the POST data const { signature } = qs.parse(event.body); const ADD_SIGNATURE = ` mutation($signature: String!) { createSignature(data: { name: $signature }) { _id } } `; // store the signature in the database await graphql(ADD_SIGNATURE, { signature }); // send people back to the petition page return { statusCode: 302, headers: { Location: '/03-store-data/', }, // body is unused in 3xx codes, but required in all function responses body: 'redirecting...', }; } catch (error) { return { statusCode: 500, body: JSON.stringify(error.message), }; } };

Fungsi ini melakukan hal berikut:

  1. Ambil nilai tanda tangan dari formulir POST data
  2. Memanggil fungsi pembantu yang menyimpan tanda tangan di database
  3. Mendefinisikan mutasi GraphQL untuk menulis ke database
  4. Mengirimkan mutasi menggunakan fungsi pembantu GraphQL
  5. Mengarahkan kembali ke halaman yang mengirimkan data

Selanjutnya, kita memerlukan fungsi tanpa server untuk membaca semua tanda tangan dari database sehingga kita dapat menunjukkan berapa banyak orang yang mendukung petisi kita:

 const graphql = require('./util/graphql'); exports.handler = async () => { const { signatures } = await graphql(` query { signatures { data { name } } } `); return { statusCode: 200, body: JSON.stringify(signatures.data), }; };

Fungsi ini mengirimkan kueri dan mengembalikannya.

Catatan penting tentang kunci sensitif dan aplikasi JAMstack :

Satu hal yang perlu diperhatikan tentang aplikasi ini adalah kami menggunakan fungsi tanpa server untuk melakukan panggilan ini karena kami harus memberikan kunci server pribadi ke Fauna yang membuktikan bahwa kami telah membaca dan menulis akses ke database ini. Kami tidak dapat memasukkan kunci ini ke dalam kode sisi klien, karena itu berarti siapa pun dapat menemukannya di kode sumber dan menggunakannya untuk melakukan operasi CRUD terhadap database kami. Fungsi tanpa server sangat penting untuk menjaga kerahasiaan kunci pribadi di aplikasi JAMstack.

Setelah fungsi tanpa server kami diatur, kami dapat menambahkan formulir yang mengirimkan ke fungsi untuk menambahkan tanda tangan, elemen untuk menunjukkan tanda tangan yang ada, dan sedikit JS untuk memanggil fungsi untuk mendapatkan tanda tangan dan memasukkannya ke tampilan kami elemen:

 <form action="/.netlify/functions/add-signature" method="POST"> <label for="signature">Your name</label> <input type="text" name="signature" required /> <button type="submit">Sign</button> </form> <ul class="signatures"></ul> <script> fetch('/.netlify/functions/get-signatures') .then(res => res.json()) .then(names => { const signatures = document.querySelector('.signatures'); names.forEach(({ name }) => { const li = document.createElement('li'); li.innerText = name; signatures.appendChild(li); }); }); </script>

Jika kita memuat ini di browser, kita akan melihat formulir petisi kita dengan tanda tangan di bawahnya:

Formulir petisi kosong dengan daftar tanda tangan di bawah ini
Formulir kosong yang menerima tanda tangan digital (Pratinjau besar)

Lalu, jika kita menambahkan tanda tangan kita…

Formulir petisi dengan nama di lapangan, tetapi belum diserahkan
Formulir petisi dengan nama yang diisi (Pratinjau besar)

…dan mengirimkannya, kita akan melihat nama kita ditambahkan ke bagian bawah daftar:

Formulir petisi kosong dengan tanda tangan baru di bagian bawah daftar
Formulir petisi dihapus dan tanda tangan baru ditambahkan ke bagian bawah daftar. (Pratinjau besar)

Anjing hot diggity! Kami baru saja menulis aplikasi JAMstack yang didukung basis data lengkap dengan sekitar 75 baris kode dan 7 baris skema basis data!

Lindungi Konten Dengan Otentikasi Pengguna

“Oke, kali ini kamu pasti terjebak,” Anda mungkin berpikir. “Tidak mungkin situs JAMstack dapat menangani otentikasi pengguna. Bagaimana itu bisa berhasil, bahkan ?! ”

Saya akan memberi tahu Anda cara kerjanya, teman saya: dengan fungsi tanpa server dan OAuth kami yang tepercaya.

OAuth adalah standar yang diadopsi secara luas untuk memungkinkan orang memberi aplikasi akses terbatas ke info akun mereka daripada membagikan kata sandi mereka. Jika Anda pernah masuk ke layanan menggunakan layanan lain (misalnya, "masuk dengan akun Google Anda"), Anda pernah menggunakan OAuth sebelumnya.

Catatan: Kami tidak akan membahas lebih dalam tentang cara kerja OAuth, tetapi Aaron Parecki menulis ikhtisar yang solid tentang OAuth yang mencakup detail dan alur kerja.

Di aplikasi JAMstack, kami dapat memanfaatkan OAuth, dan JSON Web Tokens (JWTs) yang diberikannya kepada kami untuk mengidentifikasi pengguna, untuk melindungi konten, dan hanya mengizinkan pengguna yang masuk untuk melihatnya.

Demo: Perlu Login untuk Melihat Konten yang Dilindungi

Jika kami perlu membuat situs yang hanya menampilkan konten kepada pengguna yang masuk, kami memerlukan beberapa hal:

  1. Penyedia identitas yang mengelola pengguna dan alur masuk
  2. Elemen UI untuk mengelola masuk dan keluar
  3. Fungsi tanpa server yang memeriksa pengguna yang masuk menggunakan JWT dan mengembalikan konten yang dilindungi jika tersedia

Untuk contoh ini, kami akan menggunakan Netlify Identity, yang memberi kami pengalaman pengembang yang sangat menyenangkan untuk menambahkan otentikasi dan menyediakan widget drop-in untuk mengelola tindakan login dan logout.

Untuk mengaktifkannya:

  • Kunjungi dasbor Netlify Anda
  • Pilih situs yang memerlukan autentikasi dari daftar situs Anda
  • Klik "identitas" di navigasi atas
  • Klik tombol "Aktifkan Identitas"

Kami dapat menambahkan Netlify Identity ke situs kami dengan menambahkan markup yang menunjukkan konten yang keluar dan menambahkan elemen untuk menampilkan konten yang dilindungi setelah masuk:

 <div class="content logged-out"> <h1>Super Secret Stuff!</h1> <p> only my bestest friends can see this content</p> <button class="login">log in / sign up to be my best friend</button> </div> <div class="content logged-in"> <div class="secret-stuff"></div> <button class="logout">log out</button> </div>

Markup ini bergantung pada CSS untuk menampilkan konten berdasarkan apakah pengguna masuk atau tidak. Namun, kami tidak dapat mengandalkan itu untuk benar-benar melindungi konten — siapa pun dapat melihat kode sumber dan mencuri rahasia kami!

Sebagai gantinya, kami membuat div kosong yang akan berisi konten kami yang dilindungi, tetapi kami harus membuat permintaan ke fungsi tanpa server untuk benar-benar mendapatkan konten itu. Kami akan menggali cara kerjanya segera.

Selanjutnya, kita perlu menambahkan kode untuk membuat tombol login kita berfungsi, memuat konten yang dilindungi, dan menampilkannya di layar:

 <script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script> <script> const login = document.querySelector('.login'); login.addEventListener('click', () => { netlifyIdentity.open(); }); const logout = document.querySelector('.logout'); logout.addEventListener('click', () => { netlifyIdentity.logout(); }); netlifyIdentity.on('logout', () => { document.querySelector('body').classList.remove('authenticated'); }); netlifyIdentity.on('login', async () => { document.querySelector('body').classList.add('authenticated'); const token = await netlifyIdentity.currentUser().jwt(); const response = await fetch('/.netlify/functions/get-secret-content', { headers: { Authorization: `Bearer ${token}`, }, }).then(res => res.text()); document.querySelector('.secret-stuff').innerHTML = response; }); </script>

Inilah yang dilakukan kode ini:

  1. Memuat widget Netlify Identity, yang merupakan pustaka pembantu yang membuat modal masuk, menangani alur kerja OAuth dengan Netlify Identity, dan memberi aplikasi kami akses ke info pengguna yang masuk
  2. Menambahkan pendengar acara ke tombol login yang memicu modal login Netlify Identity untuk membuka
  3. Menambahkan event listener ke tombol logout yang memanggil metode logout Netlify Identity
  4. Menambahkan event handler untuk logout guna menghapus kelas yang diautentikasi saat logout, yang menyembunyikan konten login dan menampilkan konten logout
  5. Menambahkan pengendali acara untuk masuk itu:
    1. Menambahkan kelas yang diautentikasi untuk menampilkan konten yang masuk dan menyembunyikan konten yang keluar
    2. Meraih JWT pengguna yang masuk
    3. Memanggil fungsi tanpa server untuk memuat konten yang dilindungi, mengirimkan JWT di header Otorisasi
    4. Menempatkan konten rahasia di div barang rahasia sehingga pengguna yang masuk dapat melihatnya

Saat ini fungsi tanpa server yang kami panggil dalam kode itu tidak ada. Mari kita buat dengan kode berikut:

 exports.handler = async (_event, context) => { try { const { user } = context.clientContext; if (!user) throw new Error('Not Authorized'); return { statusCode: 200, headers: { 'Content-Type': 'text/html', }, body: `

Anda Diundang, ${user.user_metadata.full_name}!

Jika Anda dapat membaca ini berarti kita adalah teman baik.

Berikut adalah detail rahasia untuk pesta ulang tahun saya:
jason.af/party

`, }; } tangkap (kesalahan) { kembali { kode status: 401, badan: 'Tidak Diotorisasi', }; } };

Fungsi ini melakukan hal berikut:

  1. Memeriksa pengguna dalam argumen konteks fungsi tanpa server
  2. Melempar kesalahan jika tidak ada pengguna yang ditemukan
  3. Mengembalikan konten rahasia setelah memastikan bahwa pengguna yang masuk memintanya

Fungsi Netlify akan mendeteksi JWT Identitas Netlify di header Otorisasi dan secara otomatis memasukkan informasi itu ke dalam konteks — ini berarti kita dapat memeriksa JWT yang valid tanpa perlu menulis kode untuk memvalidasi JWT!

Saat kita memuat halaman ini di browser kita, kita akan melihat halaman logout terlebih dahulu:

Tampilan logout yang menampilkan informasi tentang login atau membuat akun
Saat logout, kami hanya dapat melihat informasi tentang login. (Pratinjau besar)

Jika kita mengklik tombol untuk login, kita akan melihat widget Netlify Identity:

Jendela modal yang menampilkan tab daftar dan masuk dengan formulir masuk ditampilkan
Netlify Identity Widget menyediakan seluruh pengalaman login/mendaftar. (Pratinjau besar)

Setelah masuk (atau mendaftar), kita dapat melihat konten yang dilindungi:

Tampilan masuk yang menampilkan informasi tentang pesta ulang tahun
Setelah masuk, kita dapat melihat konten yang dilindungi. (Pratinjau besar)

Wow! Kami baru saja menambahkan login pengguna dan konten yang dilindungi ke aplikasi JAMstack!

Apa yang Harus Dilakukan Selanjutnya?

JAMstack lebih dari sekadar "situs statis" — kami dapat merespons interaksi pengguna, menyimpan data, menangani otentikasi pengguna, dan hampir semua hal lain yang ingin kami lakukan di situs web modern. Dan semuanya tanpa perlu menyediakan, mengonfigurasi, atau menyebarkan server!

Apa yang ingin Anda bangun dengan JAMstack? Apakah ada sesuatu yang Anda masih belum yakin dapat ditangani oleh JAMstack? Saya ingin mendengarnya — hubungi saya di Twitter atau di komentar!