Skip to content

Latest commit

 

History

History
1579 lines (935 loc) · 139 KB

README.indonesian.md

File metadata and controls

1579 lines (935 loc) · 139 KB

Praktik Terbaik Node.js

Praktik Terbaik Node.js


102 item Pembaruan terakhir: November, 2020 Diperbarui untuk Node 14.0.0

nodepractices Ikuti kami di Twitter! @nodepractices


Baca dalam bahasa yang berbeda: CNCN, BRBR, RURU, PLPL, EUEU (ESES, FRFR, HEHE, KRKR dan TRTR dalam proses!)


Dibuat dan dijaga oleh Komite Pengarah dan kolaborator

Praktik Terbaik Terbaru dan Berita

  • ✅ Praktik terbaik baru: Poin 2.12 oleh Alexsey menunjukkan bagaimana melakukan return tanpa await ke fungsi asinkron dapat mengarah ke stacktraces parsial. Ini dapat menjadi masalah besar saat melakukan pemecahan masalah exception di produksi yang kekurangan beberapa bingkai eksekusi

  • ✅ Praktik terbaik baru: Poin 6.8 oleh Josh Hemphill menyarankan "Protect Users' Passwords/Secrets using BCrypt or Script". Ini mengandung penjelasan secara mendalam tentang kapan dan kenapa setiap opsi sesuai untuk proyek tertentu. Jangan lewatkan panduan singkat ini dengan gambaran singkat tentang berbagai opsi hashing

  • 🐳 Praktik terbaik Node.js + Docker: Kami baru saja merilis seksi Docker dengan Node.js yang mengandung 15 poin tentang teknik pengkodean yang lebih baik dengan Docker



Selamat Datang! 3 Hal Yang Harus Anda Ketahui

1. Anda sedang membaca berbagai artikel Node.js terbaik - repositori ini adalah ringkasan dan kurasi dari konten peringkat teratas dalam praktik terbaik Node.js, serta konten yang ditulis oleh kolaborator

2. Ini adalah kompilasi terbesar, dan berkembang tiap minggu - saat ini, lebih dari 80 praktik terbaik, panduan gaya, dan tips arsitektural tersajikan. Issue baru dan pull request dibuat setiap hari agar kontennya tetap diperbarui. Kami senang melihat Anda berkontribusi di sini, maupun itu memperbaiki kesalahan kode, membantu dalam terjemahan, atau menyarankan ide cemerlang yang baru. Lihat pedoman menulis kami

3. Praktik terbaik mempunyai informasi tambahan - kebanyakan poin mempunyai tautan 🔗Baca selengkapnya yang memperluas praktiknya dengan contoh kode, kutipan dari blog terpilih, dan informasi lebih lanjut



Daftar Isi

  1. Praktik Struktur Proyek (5)
  2. Praktik Penanganan Kesalahan (11)
  3. Praktik Gaya Kode (12)
  4. Praktik Pengujian dan Kualitas Secara Keseluruhan (13)
  5. Praktik Dalam Produksi(19)
  6. Praktik Keamanan (25)
  7. Praktik Performa (2) (Pekerjaan Dalam Proses ✍️)
  8. Praktik Docker (15)



1. Praktik Struktur Proyek

✔ 1.1 Susun solusi Anda berdasarkan komponen

TL;DR: Masalah terburuk pada aplikasi besar adalah mengurus basis kode yang sangat besar dengan ratusan dependensi - monolit seperti itu memperlambat pengembang saat mereka mencoba untuk menambahkan fitur baru. Sebaiknya, partisi kode Anda menjadi beberapa komponen, setiap komponen mendapatkan foldernya sendiri atau basis kode tersendiri, dan pastikan setiap unit untuk tetap kecil dan sederhana. Kunjungi 'Baca selengkapnya' di bawah ini untuk melihat contoh struktur proyek yang benar

Jika tidak: Saat pengembang yang menambahkan fitur baru kesusahan untuk melihat dampak dari perubahan mereka dan takut akan merusak komponen lain yang bergantung - deployment menjadi lebih lambat dan berisiko. Kode juga dianggap lebih sulit untuk dikembangkan ketika semua unit bisnis tidak dipisahkan

🔗 Baca selengkapnya: structure by components



✔ 1.2 Lapisi komponen Anda, pastikan lapisan web tetap dalam batasannya

TL;DR: Setiap komponen harus mengandung 'lapisan' - objek khusus untuk web, logika, dan kode akses data. Hal ini tidak hanya menggambarkan separation of concerns dengan jelas namun juga memudahkan mocking dan pengujian sistem. Meskipun ini adalah pola yang sangan umum, pengembang API cenderung mencampur lapisan dengan meneruskan objek lapisan web (misalnya Express req, res) ke logika bisnis dan lapisan data - ini membuat aplikasi Anda bergantung dan hanya bisa diakses oleh framework web tertentu

Jika tidak: Aplikasi yang menggabungkan objek web dengan lapisan lain tidak dapat diakses oleh kode pengujian, pekerjaan CRON, triggers dari message queues, dll.

🔗 Baca selengkapnya: layer your app



✔ 1.3 Bungkus utilitas umum sebagai paket npm

TL;DR: Pada aplikasi besar yang memiliki basis kode yang besar, utilitas cross-cutting-concern seperti logger, enkripsi dan yang serupa, harus dibungkus oleh kode Anda dan terekspos sebagai paket npm tersendiri. Ini memungkinkan untuk membagikan utilitas tersebut di antara beberapa basis kode dan proyek

Jika tidak: Anda harus membuat cara deployment dan dependency Anda sendiri

🔗 Baca selengkapnya: Structure by feature



✔ 1.4 Pisahkan 'app' dan 'server' Express

TL;DR: Hindari kebiasaan buruk dalam mendefinisikan seluruh aplikasi Express dalam satu file besar - pisahkan definisi 'Express' Anda menjadi setidaknya dua file: deklarasi untuk API (app.js) dan untuk jaringan (WWW). Untuk struktur yang lebih baik lagi, letak deklarasi API Anda di dalam komponen

Jika tidak: API Anda hanya dapat diakses untuk pengujian melalui panggilan HTTP (lebih lambat and lebih susah untuk membuat laporan cakupan pengujian). Mengurus ratusan baris kode dalam satu file mungkin bukanlah hal yang menyenangkan

🔗 Baca selengkapnya: separate Express 'app' and 'server'



✔ 1.5 Gunakan konfigurasi yang sadar atas lingkungan, aman dan hierarkis

TL;DR: Pengaturan konfigurasi yang sempurna harus memastikan (a) kunci dapat dibaca dari file DAN dari variabel lingkungan (b) rahasia disimpan di luar kode (c) konfigurasi bersifat hierarkis agar mudah ditemukan. Ada beberapa paket yang dapat mempermudah pengaturan tersebut seperti rc, nconf, config, dan convict.

Jika tidak: Gagal untuk memenuhi salah satu persyaratan konfigurasi hanya akan menghambat tim pengembang atau DevOps. Mungkin keduanya

🔗 Baca selengkapnya: configuration best practices




⬆ Kembali ke atas

2. Praktik Penanganan Kesalahan

✔ 2.1 Gunakan Async-Await atau promise untuk penanganan kesalahan asinkron

TL;DR: Menangani kesalahan asinkron dalam panggilan balik mungkin adalah cara terburuk (a.k.a the pyramid of doom). Hal terbaik yang dapat Anda berikan ke kode Anda adalah dengan menggunakan pustaka promise dengan reputasi yang baik atau gunakan async-await yang membuat sintaks kode menjadi lebih ringkas dan familier seperti try-catch

Jika tidak: Gaya panggilan balik Node.js, function(err, response), adalah cara yang menjanjikan untuk kode yang tidak dapat dipelihara karena campuran dari penanganan kesalahan dengan kode kasual, bersarang yang berlebihan, dan pola pengkodean yang canggung

🔗 Baca selengkapnya: avoiding callbacks



✔ 2.2 Gunakan hanya objek Error bawaan

TL;DR: Banyak pengembang melempar error sebagai string atau tipe khusus – ini mempersulit logika penanganan kesalahan dan interoperabilitas antar modul. Maupun Anda menolak sebuah promise, melontarkan sebuah pengecualian atau mengeluarkan error – dengan hanya menggunakan objek Error bawaan (atau objek yang memperluas objek Error bawaan) dapat meningkatkan keseragaman dan mencegah hilangnya informasi

Jika tidak: Saat menjalankan beberapa komponen, karena tidak yakin jenis kesalahan yang akan di lempar – ini membuat penanganan kesalahan yang benar jauh lebih sulit. Lebih buruk lagi, menggunakan tipe khusus untuk mendeskripsikan kesalahan dapat menyebabkan hilangnya informasi kesalahan kritis seperti stack trace!

🔗 Baca selengkapnya: using the built-in error object



✔ 2.3 Membedakan kesalahan operasional dan kesalahan pengembang

TL;DR: Kesalahan operasional (contohnya API menerima masukan yang tidak valid) merupakan kasus kesalahan yang diketahui di mana dampak dari kesalahannya dapat dipahami sepenuhnya dan dapat ditangani dengan cermat. Di sisi lain, kesalahan pengembang (contohnya mencoba membaca variabel yang tidak ditentukan) merupakan kegagalan kode yang tidak diketahui yang menentukan untuk memulai ulang aplikasi dengan baik

Jika tidak: Anda selalu dapat memulai ulang aplikasi Anda ketika kesalahan muncul, namun kenapa mengecewakan ~5000 pengguna hanya karena kesalahan operasional yang kecil dan dapat diprediksi? hal sebaliknya juga tidak ideal – membiarkan aplikasi tetap berjalan ketika terdapat kesalahan yang tidak diketahui (kesalahan oleh pengembang) dapat menyebabkan perilaku yang tidak terduga. Membedakan kedua kesalahan tersebut memungkinkan untuk melakukan tindakan yang benar dan menerapkan cara penyelesaian masalah yang sesuai dengan konteks yang diberikan

🔗 Baca selengkapnya: operational vs programmer error



✔ 2.4 Tangani kesalahan secara terpusat, bukan dalam middleware

TL;DR: Logika penanganan kesalahan seperti pengiriman pesan ke admin dan pencatatan harus dikemas dalam objek khusus dan terpusat yang dipanggil oleh semua endpoint (contohnya middleware Express, pekerjaan cron, pengujian unit) ketika ada kesalahan

Jika tidak: Tidak menangani kesalahan dalam satu tempat akan menyebabkan duplikasi kode dan mungkin kesalahan yang tidak ditangani dengan tepat

🔗 Baca selengkapnya: handling errors in a centralized place



✔ 2.5 Mendokumentasikan kesalahan API menggunakan Swagger atau GraphQL

TL;DR: Beri tahu pemanggil API Anda kesalahan apa yang mungkin dapat diterima sehingga mereka dapat menanganinya dengan baik tanpa merusak aplikasinya. Untuk API RESTful, hal ini biasanya dilakukan dengan framework dokumentasi seperti Swagger. Jika Anda menggunakan GraphQL, Anda juga dapat memanfaatkan skema dan komentar.

Jika tidak: Klien API mungkin memutuskan untuk memberhentikan aplikasi dan memulai ulang hanya karena menerima kesalahan yang tidak dapat dipahami. Catatan: pemanggil API mungkin adalah Anda (sangat umum dalam lingkungan microservice)

🔗 Baca selengkapnya: documenting API errors in Swagger or GraphQL



✔ 2.6 Hentikan proses dengan benar ketika orang asing datang ke kota

TL;DR: Ketika terjadi kesalahan yang tidak diketahui (kesalahan pengembang, lihat praktik terbaik 2.3) - ada ketidakpastian tentang kesehatan aplikasi. Praktik umum menyarankan untuk memulai kembali proses dengan hati-hati menggunakan alat manajemen proses seperti Forever atau PM2

Jika tidak: Ketika pengecualian yang tidak dikenal terjadi, beberapa objek mungkin dalam keadaan rusak (contohnya event emitter yang digunakan secara global dan tidak dapat mengaktifkan event lagi karena kesalahan internal) dan semua panggilan yang akan datang mungkin akan gagal atau tidak berperilaku dengan normal

🔗 Baca selengkapnya: shutting the process



✔ 2.7 Gunakan alat pencatat yang baik untuk meningkatkan visibilitas kesehatan

TL;DR: Satu set alat pencatat yang baik seperti Pino atau Log4js, akan mempercepat penemuan dan pemahaman suatu kesalahan. Jadi tinggalkan console.log

Jika tidak: Melihat beberapa console.log atau secara manual melalui file teks yang berantakan tanpa alat kueri atau penampil catatan yang baik dapat membuat Anda sibuk di tempat kerja hingga larut

🔗 Baca selengkapnya: using a mature logger



✔ 2.8 Uji aliran kesalahan menggunakan framework pengujian favorit Anda

TL;DR: Maupun itu QA otomatis profesional ataupun pengujian manual oleh pengembang – Pastikan bahwa kode Anda tidak hanya memenuhi skenario positif namun juga menangani dan mengembalikan jenis kesalahan yang tepat. Framework testing seperti Mocha & Chai dapat menangani ini dengan mudah (lihat contoh kode dalam "Gist popup")

Jika tidak: Tanpa testing, maupun secara otomatis ataupun manual, Anda tidak dapat mengandalkan kode Anda untuk mengembalikan jenis kesalahan yang tepat. Tanpa jenis kesalahan yang berarti – tidak ada penanganan kesalahan

🔗 Baca selengkapnya: testing error flows



✔ 2.9 Temukan kesalahan dan waktu henti menggunakan produk APM

TL;DR: Produk pemantauan dan kinerja (a.k.a APM) secara proaktif mengukur basis kode atau API sehingga mereka dapat secara otomatis menyorot kesalahan, kerusakan, dan bagian lambat yang Anda lewatkan

Jika tidak: Anda mungkin menghabiskan banyak usaha untuk mengukur kinerja dan waktu henti API, mungkin Anda tidak akan menyadari bagian kode mana yang paling lambat dalam skenario dunia nyata dan bagaimana hal ini dapat memengaruhi pengalaman pengguna

🔗 Baca selengkapnya: using APM products



✔ 2.10 Tangkap penolakan promise yang tidak tertangani

TL;DR: Semua pengecualian yang dilemparkan ke dalam promise akan ditelan dan dibuang kecuali pengembang tidak lupa untuk menanganinya secara eksplisit. Meskipun kode Anda berlangganan ke process.uncaughtException! Atasi ini dengan mendaftarkan ke event process.unhandledRejection

Jika tidak: Kesalahan dari kode Anda akan ditelan dan hilang tanpa jejak. Tidak ada yang perlu dikhawatirkan

🔗 Baca selengkapnya: catching unhandled promise rejection



✔ 2.11 Gagal lebih dini, validasi argumen menggunakan pustaka khusus

TL;DR: Tegaskan masukan API untuk menghindari bug yang lebih sulit dilacak nantinya. Kode untuk validasi biasanya berantakan kecuali Anda menggunakan pustaka pembantu yang keren seperti ajv dan Joi

Jika tidak: Anggap seperti ini – jika fungsi Anda mengharapkan argumen numerik “Diskon” yang lupa diletak oleh pemanggil, kemudian, kode Anda memeriksa jika Diskon!=0 (jumlah diskon yang diizinkan lebih besar dari nol), maka itu akan memungkinkan pengguna untuk menikmati diskon. OMG, bug yang sangat buruk. Bisakah Anda melihatnya?

🔗 Baca selengkapnya: failing fast



✔ 2.12 Selalu await promise sebelum mengembalikan nilai untuk menghindari stacktrace yang tidak lengkap

TL;DR: Selalu lakukan return await ketika mengembalikan sebuah promise untuk memanfaatkan stacktrace kesalahan yang lengkap. Jika sebuah fungsi mengembalikan promise, fungsi tersebut harus dideklarasikan sebagai fungsi async dan await fungsi tersebut secara eksplisit sebelum mengembalikannya

Jika tidak: Fungsi yang mengembalikan promise tanpa await tidak akan muncul di stacktrace. Kerangka yang hilang seperti itu mungkin akan mempersulit pemahaman tentang aliran yang mengarah ke kesalahan, terutama jika penyebab perilaku yang tidak normal ada di dalam fungsi yang hilang itu

🔗 Baca selengkapnya: returning promises




⬆ Kembali ke atas

3. Praktik Gaya Kode

✔ 3.1 Gunakan ESLint

TL;DR: ESLint adalah standar de-facto untuk memeriksa kemungkinan kesalahan kode dan memperbaiki gaya kode, bukan hanya untuk mengidentifikasi masalah spasi tetapi juga untuk mendeteksi kode anti-pola yang serius seperti pengembang melemparkan kesalahan tanpa klasifikasi. Meskipun ESLint dapat memperbaiki gaya kode secara otomatis, alat lain seperti prettier dan beautify lebih baik dalam memformat perbaikan kodenya dan dapat bekerja sama dengan ESLint

Jika tidak: Pengembang akan fokus pada masalah spasi dan lebar garis dan waktu mungkin akan terbuang hanya untuk memikirkan gaya kode pada proyek

🔗 Baca selengkapnya: Using ESLint and Prettier



✔ 3.2 Plugin khusus Node.js

TL;DR: Selain aturan standar ESLint yang mencakup vanilla JavaScript, tambahkan plugin khusus Node.js seperti eslint-plugin-node, eslint-plugin-mocha dan eslint-plugin-node-security

Jika tidak: Banyak pola kode Node.js yang salah dapat lolos dari radar. Contohnya, pengembang mungkin melakukan require(variableAsPath) pada file dengan variabel sebagai path yang memungkinkan penyerang untuk mengeksekusi skrip JS apa pun. Linters Node.js dapat mendeteksi pola tersebut dan memberikan peringatan lebih awal



✔ 3.3 Mulai kurung kurawal pada blok kode pada baris yang sama

TL;DR: Tanda kurung kurawal pembuka blok kode harus di baris yang sama dengan statement pembuka

Contoh Kode

// Lakukan
function someFunction() {
  // blok kode
}

// Hindari
function someFunction() {
  // blok kode
}

Jika tidak: Tidak mengikuti praktik terbaik ini dapat menyebabkan hasil yang tidak terduga, seperti yang terlihat pada thread StackOverflow di bawah ini:

🔗 Baca selengkapnya: "Why do results vary based on curly brace placement?" (StackOverflow)



✔ 3.4 Pisahkan statement Anda dengan benar

Tidak peduli jika Anda menggunakan titik koma atau tidak untuk memisahkan statement Anda, mengetahui akibat umum dari pemutusan baris yang tidak tepat atau penyisipan titik koma otomatis, akan membantu Anda mengurangi kesalahan sintaks biasa.

TL;DR: Gunakan ESLint untuk mendapatkan perhatian tentang masalah pemisahan. Prettier atau Standardjs dapat menyelesaikan masalah ini secara otomatis.

Jika tidak: Seperti yang terlihat di bagian sebelumnya, penerjemah JavaScript secara otomatis menambah titik koma pada akhir statement jika tidak ada, atau anggap sebuah statement tidak diakhiri di tempat yang seharusnya, yang dapat mengarah pada hasil yang tidak diinginkan. Anda dapat menggunakan penetapan dan hindari penggunaan ekspresi fungsi yang langsung dipanggil untuk mencegah sebagian besar masalah yang tidak terduga.

Contoh kode

// Lakukan
function doThing() {
    // ...
}

doThing()

// Lakukan

const items = [1, 2, 3]
items.forEach(console.log)

// Hindari — melempar pengecualian
const m = new Map()
const a = [1,2,3]
[...m.values()].forEach(console.log)
> [...m.values()].forEach(console.log)
>  ^^^
> SyntaxError: Unexpected token ...

// Hindari — melempar pengecualian
const count = 2 // mencoba menjalankan 2(), tapi 2 bukanlah sebuah fungsi
(function doSomething() {
  // lakukan sesuatu
}())
// letakkan titik koma sebelum fungsi yang langsung dipanggil, setelah pendefinisian const, simpan nilai kembali dari fungsi anonim ke sebuah variabel atau hindari IIFE (ekspresi fungsi yang langsung dipanggil) sepenuhnya

🔗 Baca selengkapnya: "Semi ESLint rule" 🔗 Baca selengkapnya: "No unexpected multiline ESLint rule"



✔ 3.5 Namakan fungsi Anda

TL;DR: Namakan semua fungsi, termasuk closure dan panggilan balik. Hindari fungsi anonim. Ini sangat berguna saat mengukur sebuah aplikasi node. Menamakan semua fungsi memungkinkan Anda untuk memahami dengan mudah apa yang Anda lihat saat memeriksa snapshot memori

Jika tidak: Men-debug masalah produksi menggunakan core dump (snapshot memori) dapat menjadi tantangan karena Anda melihat konsumsi memori yang signifikan dari fungsi anonim



✔ 3.6 Gunakan konvensi penamaan untuk variabel, konstanta, fungsi dan kelas

TL;DR: Gunakan lowerCamelCase saat memberi nama konstanta, variabel dan fungsi dan UpperCamelCase (huruf besar pada huruf pertama) saat memberi nama kelas. Ini akan membantu Anda dengan mudah untuk membedakan variabel/fungsi biasa, dan kelas yang membutuhkan instansiasi. Gunakan nama yang deskriptif, tetapi usahakan untuk tetap pendek

Jiak tidak: Javascript adalah satu-satunya bahasa di dunia yang memungkinkan pemanggilan konstruktor kelas ("Class") secara langsung tanpa membuat instansinya terlebih dahulu. Akibatnya, kelas dan fungsi-konstruktor dibedakan dimulai dengan UpperCamelCase

3.6 Contoh Kode

// untuk nama kelas kita gunakan UpperCamelCase
class SomeClassExample {}

// untuk nama const kita gunakan kata kunci const dan lowerCamelCase
const config = {
  key: "value",
};

// untuk nama variabel dan fungsi kita gunakan lowerCamelCase
let someVariableExample = "value";
function doSomething() {}



✔ 3.7 Utamakan penggunaan const daripada let. Singkirkan var

TL;DR: Menggunakan const berarti bahwa setelah nilai variabel itu ditetapkan, nilainya tidak dapat ditetapkan kembali. Menggunakan const akan membantu Anda untuk tidak tergoda untuk menggunakan variabel yang sama untuk penggunaan yang berbeda, dan membuat kode Anda lebih jelas. Jika sebuah variabel perlu ditetapkan kembali nilainya, di dalam perulangan for, misalnya, deklarasikan menggunakan let. Aspek penting lainnya dari let adalah variabel yang dideklarasikan menggunakan let hanya tersedia di dalam cakupan blok di mana variabel itu didefinisikan. var memiliki cakupan dalam fungsi, bukan dalam blok, dan tidak boleh digunakan di ES6 setelah Anda mempunyai const dan let

Jika tidak: Men-debug menjadi lebih rumit saat mengikuti variabel yang sering berubah

🔗 Baca selengkapnya: JavaScript ES6+: var, let, or const?



✔ 3.8 Require modul terlebih dahulu, bukan di dalam fungsi

TL;DR: Require modul di awal setiap file, sebelum dan di luar semua fungsi. Praktik terbaik sederhana ini tidak hanya membantu Anda dengan mudah dan cepat untuk mengetahui dependensi file di awal sebuah file tetapi juga menghindari beberapa potensi masalah

Jika tidak: Require dijalankan secara sinkron oleh Node.js. Jika mereka dipanggil dalam sebuah fungsi, ini mungkin dapat memblokir permintaan lain untuk ditangani pada waktu yang lebih kritis. Selain itu, jika modul yang diperlukan atau salah satu dependensinya menimbulkan kesalahan dan merusak server, akan lebih baik untuk mengetahuinya sesegera mungkin, yang mungkin tidak akan terjadi jika modul itu dipanggil dalam sebuah fungsi



✔ 3.9 Require modul berdasarkan folder, bukan file secara langsung

TL;DR: Saat mengembangkan sebuah modul/pustaka dalam sebuah folder, letak file index.js yang mengekspos modul internal sehingga setiap konsumen akan melewatinya. Ini berfungsi sebagai 'antarmuka' ke modul Anda dan memudahkan perubahan di masa mendatang tanpa merusak kontrak

Jika tidak: Mengubah struktur internal sebuah file atau tanda tangannya dapat merusak antarmuka dengan klien

3.9 Contoh kode

// Lakukan
module.exports.SMSProvider = require("./SMSProvider");
module.exports.SMSNumberResolver = require("./SMSNumberResolver");

// Hindari
module.exports.SMSProvider = require("./SMSProvider/SMSProvider.js");
module.exports.SMSNumberResolver = require("./SMSNumberResolver/SMSNumberResolver.js");



✔ 3.10 Gunakan operator ===

TL;DR: Utamakan operator persamaan ketat === daripada operator persamaan abstrak == yang lebih lemah. == akan membandingkan dua variabel setelah mengubahnya ke tipe umum. Tidak ada konversi tipe di ===, dan kedua variabel harus sejenis agar sama

Jika tidak: Variabel yang tidak sama dapat mengembalikan true ketika dibandingkan dengan operator ==

3.10 Contoh kode

"" == "0"; // false
0 == ""; // true
0 == "0"; // true

false == "false"; // false
false == "0"; // true

false == undefined; // false
false == null; // false
null == undefined; // true

" \t\r\n " == 0; // true

Semua pernyataan di atas akan mengembalikan nilai false jika menggunakan ===



✔ 3.11 Gunakan Async Await, hindari panggilan balik

TL;DR: Node 8 LTS sekarang memiliki dukungan penuh untuk Async-await. Ini adalah cara baru untuk menangani kode asinkron yang menggantikan panggilan balik dan promise. Async-await bersifat tidak memblokir, dan ini membuat kode asinkron terlihat seperti sinkron. Hadiah terbaik yang dapat Anda berikan untuk kode Anda adalah menggunakan async-await yang menyediakan sintaks yang lebih ringkas dan akrab seperti try-catch

Jika tidak: Menangani kesalahan asinkron dalam gaya panggilan balik mungkin adalah cara terburuk - gaya ini memeriksa kesalahan secara menyeluruh, menangani tumpukan kode yang canggung, dan menyulitkan untuk menjelaskan aliran kode

🔗Baca selengkapnya: Guide to async-await 1.0



✔ 3.12 Gunakan ekspresi fungsi panah (=>)

TL;DR: Meskipun disarankan untuk menggunakan async-await dan menghindari parameter fungsi saat berurusan dengan API lama yang menerima promise atau panggilan balik - fungsi panah membuat struktur kode lebih ringkas dan menjaga konteks leksikal dari akar fungsi (contohnya this)

Jika tidak: Kode yang lebih panjang (dalam fungsi ES5) lebih rentan terhadap masalah dan rumit untuk dibaca

🔗 Baca selengkapnya: It’s Time to Embrace Arrow Functions




⬆ Kembali ke atas

4. Praktik Pengujian dan Kualitas Secara Keseluruhan

✔ 4.1 Paling tidak, buat pengujian API (komponen)

TL;DR: Sebagian besar proyek tidak memiliki pengujian otomatis karena jadwal yang singkat atau 'proyek pengujian' sering tidak terkendali dan ditinggalkan. Oleh karena itu, prioritaskan dan mulailah dengan pengujian API yang merupakan cara termudah untuk menulis dan memberikan cakupan yang lebih dari pengujian unit (Anda bahkan dapat membuat pengujian API tanpa kode menggunakan alat seperti Postman. Setelah itu, jika Anda mempunyai waktu dan sumber daya yang lebih, lanjutkan dengan pengujian yang lebih tinggi seperti pengujian unit, pengujian DB, pengujian performa, dll.

Jika tidak: Anda mungkin menghabiskan waktu yang lama untuk menulis pengujian unit untuk mengetahui bahwa Anda hanya mencakup 20% dari sistem



✔ 4.2 Sertakan 3 bagian di setiap nama pengujian

TL;DR: Buatlah pengujian yang setara dengan tingkat persyaratan sehingga cukup jelas untuk Engineer QA dan pengembang yang tidak terbiasa dengan kode internal. Sebutkan dalam nama pengujian apa yang akan diuji (unit dalam pengujian), dalam keadaan apa, dan apa hasil yang diharapkan

Jika tidak: Deployment baru saja gagal, sebuah pengujian bernama “Tambah produk” gagal. Apakah ini memberi tahu Anda dengan tepat apa yang tidak berfungsi?

🔗 Baca selengkapnya: Include 3 parts in each test name



✔ 4.3 Strukturkan pengujian Anda dengan pola AAA

TL;DR: Strukturkan pengujian dengan 3 bagian yang terpisah dengan baik: Arrange, Act & Assert (AAA). Bagian pertama mencakup penyiapan untuk pengujian, kemudian eksekusi unit yang akan diuji, dan yang terakhir fase assertion. Mengikuti struktur ini menjamin bahwa pembaca tidak menghabiskan tenaga otak untuk memahami rencana pengujian

Jika tidak: Tidak hanya Anda menghabiskan waktu yang lama untuk memahami kode utama, tetapi sekarang hal paling mudah dari hari Anda (melakukan pengujian) dapat meregangkan otak Anda

🔗 Baca selengkapnya: Structure tests by the AAA pattern



✔ 4.4 Deteksi masalah kode dengan linter

TL;DR: Gunakan linter kode untuk memeriksa kualitas dasar dan mendeteksi anti-pola sejak dini. Jalankan linter sebelum pengujian dan tambahkan linter sebagai pra-commit git-hook untuk meminimalkan waktu yang dibutuhkan untuk meninjau dan memperbaiki masalah apa pun. Periksa juga Bagian 3 tentang Praktik Gaya Kode

Jika Tidak: Anda dapat membiarkan beberapa kode dengan anti-pola dan mungkin kode yang tidak aman masuk ke lingkungan produksi Anda.



✔ 4.5 Hindari perlengkapan dan benih global pada pengujian, tambah data pada setiap pengujian

TL;DR: Untuk mencegah pengujian yang tersambung dan memudahkan untuk memahami alur pengujian, setiap pengujian harus menambah dan bertindak pada kumpulan data di DB-nya sendiri. Setiap kali pengujian perlu menarik atau mengasumsikan keberadaan suatu data pada DB - pengujian tersebut harus menambah data tersebut secara eksplisit dan hindari memutasi kumpulan data lainnya

Jika tidak: Anggap sebuah skenario di mana deployment gagal karena pengujian yang gagal, tim sekarang akan menghabiskan waktu yang berharga untuk melakukan investigasi yang berakhir dengan kesimpulan yang menyedihkan: sistem berfungsi dengan baik, namun pengujian saling mengganggu dan merusak build-nya

🔗 Baca selengkapnya: Avoid global test fixtures



✔ 4.6 Periksa terus menerus dependensi yang rentan

TL;DR: Bahkan dependensi yang paling terkemuka seperti Express memiliki kerentanan yang diketahui. Hal ini dapat dimitigasi dengan mudah menggunakan alat dari komunitas atau komersial seperti 🔗 npm audit dan 🔗 snyk.io yang dapat dipanggil dari CI Anda pada setiap build

Jika tidak: Menjaga kode Anda bersih dari kerentanan tanpa alat khusus mengharuskan Anda untuk mengikuti publikasi online tentang ancaman baru. Cukup membosankan



✔ 4.7 Tandai pengujian Anda

TL;DR: Pengujian yang berbeda harus dijalankan pada skenario yang berbeda: quick smoke, IO-less, pengujian harus dijalankan ketika pengembang menyimpan atau melakukan commit pada file, pengujian end-to-end biasanya dijalankan saat pull request baru dikirimkan, dst. Hal ini dapat dicapai dengan menandai pengujian dengan kata kunci seperti #cold #api #sanity sehingga Anda dapat melakukan grep pada pengujian Anda dan menjalankan subset yang diinginkan. Contohnya, ini adalah cara untuk memanggil pengujian pada kelompok sanity dengan Mocha: mocha --grep 'sanity'

Jika tidak: Menjalankan semua pengujian, termasuk pengujian yang menjalankan banyak kueri DB, setiap kali pengembang membuat perubahan kecil bisa sangat lambat dan menjauhkan pengembang dari menjalankan pengujian



✔ 4.8 Periksa cakupan pengujian Anda, ini membantu untuk mengidentifikasikan pola pengujian yang salah

TL;DR: Alat cakupan kode seperti Istanbul/NYC sangat bagus karena 3 alasan: gratis (sangat mudah untuk memanfaatkan laporan ini), alat ini membantu mengidentifikasikan pengurangan cakupan pengujian, dan yang terakhir, alat ini menyoroti ketidakcocokan pengujian: dengan melihat kode warna pada laporan cakupan Anda dapat melihat, misalnya, area kode yang tidak pernah diuji seperti klausa catch (artinya pengujian hanya mengambil jalur yang benar dan bukan bagaimana aplikasi akan berperilaku jika ada kesalahan). Setel agar build-nya gagal jika cakupannya berada di bawah batas tertentu

Jika tidak: Tidak akan ada metrik otomatis yang memberi tahu Anda saat sebagian besar kode Anda tidak tercakup dalam pengujian



✔ 4.9 Periksa paket yang kedaluwarsa

TL;DR: Gunakan alat pilihan Anda (misalnya 'npm outdated' atau npm-check-updates untuk mendeteksi paket yang kedaluwarsa, masukkan pemeriksaan ini ke pipeline CI dan bahkan gagalkan build-nya dalam skenario yang buruk. Contohnya, skenario yang buruk mungkin terjadi ketika paket yang digunakan tertinggal 5 patch commit (misalnya versi lokal adalah 1.3.1 dan versi repositori adalah 1.3.8) atau paketnya ditandai deprecated oleh pembuatnya - matikan build-nya dan cegah deployment pada versi ini

Jika tidak: Produksi Anda akan menggunakan paket yang ditandai berisiko oleh pembuatnya secara eksplisit



✔ 4.10 Gunakan lingkungan yang mirip dengan produksi untuk pengujian e2e

TL;DR: Pengujian End to end (e2e) yang mencakup data asli dulunya merupakan titik terlemah pada proses CI karena pengujian itu bergantung pada beberapa layanan berat seperti DB. Gunakan lingkungan yang semirip mungkin dengan lingkungan pada produksi Anda seperti a-seterusnya (-seterusnya hilang, konten dibutuhkan. Dilihat dari klausa Jika tidak, hal ini seharusnya menyebutkan tentang docker-compose)

Jika tidak: Tanpa docker-compose, tim harus mengurus DB pengujian untuk setiap lingkungan pengujian termasuk mesin yang dimiliki oleh pengembang, pastikan semua DB tersebut tetap sinkron sehingga hasil pengujian tidak akan berbeda di lingkungan yang berbeda



✔ 4.11 Sering lakukan refactor menggunakan alat analisis statis

TL;DR: Menggunakan alat analisis statis membantu dengan memberikan cara yang obyektif untuk meningkatkan kualitas kode dan tetap menjaga kode Anda. Anda dapat menambahkan alat analisis statis ke build CI untuk menggagalkan build-nya jika alat itu menemukan kode yang jelek. Nilai jual utamanya dibandingkan dengan linting biasa adalah kemampuan untuk memeriksa kualitas dalam konteks beberapa file (contohnya mendeteksi duplikasi), melakukan analisis lanjutan (contohnya kompleksitas kode), dan mengikuti riwayat dan perkembangan masalah kode. Dua contoh alat yang dapat Anda gunakan adalah Sonarqube (2,600+ bintang) dan Code Climate (1,500+ bintang).

Jika tidak: Dengan kualitas kode yang buruk, bug dan performa selalu akan selalu menjadi masalah yang tidak dapat diperbaiki oleh pustaka baru atau fitur-fitur canggih

🔗 Baca selengkapnya: Refactoring!



✔ 4.12 Pilih platform CI Anda dengan hati-hati (Jenkins vs CircleCI vs Travis vs yang lainnya)

TL;DR: Platform continuous integration (CICD) Anda akan mempunyai semua alat berkualitas (seperti test, lint) sehingga seharusnya dilengkapi dengan ekosistem plugin yang dinamis. Jenkins dulunya merupakan aplikasi default untuk banyak proyek karena mempunyai komunitas terbesar bersama dengan platform yang sangat kuat dengan kekurangan persiapan yang rumit yang menuntut kurva pembelajaran yang tajam. Saat ini, persiapan solusi CI jauh lebih mudah menggunakan alat SaaS seperti CircleCI dan lainnya. Alat ini memungkinkan pembuatan pipeline CI yang fleksibel tanpa beban untuk mengelola seluruh infrastruktur. Pada akhirnya, ini merupakan keseimbangan antara kecepatan dan kekuatan - pilih dengan hati-hati

Jika tidak: Memilih vendor khusus mungkin akan membatasi Anda ketika Anda membutuhkan penyesuaian tingkat lanjut. Di sisi lain, menggunakan Jenkins dapat menghabiskan waktu berharga dalam penyiapan infrastruktur

🔗 Baca selengkapnya: Choosing CI platform

✔ 4.13 Uji middleware Anda secara terpisah

TL;DR: Ketika middleware mempunyai beberapa logika besar yang mencakup banyak permintaan, ada baiknya untuk mengujinya secara terpisah tanpa membangun seluruh framework web. Hal ini dapat dicapai dengan mudah dengan melakukan stubbing dan spying pada objek {req, res, next}

Otherwise: Sebuah bug di middleware Express === sebuah bug di semua atau banyak request

🔗 Baca selengkapnya: Test middlewares in isolation




⬆ Kembali ke atas

5. Praktik Dalam Produksi

✔ 5.1. Pemantauan

TL;DR: Pemantauan adalah permainan mencari suatu masalah sebelum pelanggan menemukannya terlebih dahulu – yang jelas masalah itu merupakan masalah yang belum pernah terjadi sebelumnya. Pasar kewalahan dengan penawaran sehingga mempertimbangkan untuk memulai dengan menentukan metrik dasar yang harus Anda ikuti (saran saya di dalam), kemudian pertimbangkan fitur-fitur mewah tambahan dan pilih solusi yang mencentang semua kotak. Klik ‘Intinya’ di bawah untuk ringkasan dari berbagai solusi

Jika tidak: Kegagalan === pelanggan kecewa. Sederhana

🔗 Baca selengkapnya: Monitoring!



✔ 5.2. Tingkatkan transparansi dengan menggunakan logging yang cerdas

TL;DR: Log dapat menjadi gudang statement debug yang bodoh atau papan cantik yang menceritakan kisah aplikasi Anda. Rencanakan platform logging Anda dari hari pertama: bagaimana log dikumpulkan, disimpan dan dianalisis untuk memastikan bahwa informasi yang diinginkan (misalnya tingkat kesalahan, mengikuti seluruh transaksi melalui layanan dan server, dst.) benar-benar dapat diekstrak

Jika tidak: Anda berakhir dengan kotak hitam yang sulit dimengerti, kemudian Anda mulai menulis ulang semua statement log untuk menambahkan informasi tambahan

🔗 Baca selengkapnya: Increase transparency using smart logging



✔ 5.3. Delegasikan apa pun yang mungkin (misalnya gzip, SSL) ke sebuah reverse proxy

TL;DR: Node sangat buruk dalam melakukan pekerjaan yang intensif CPU seperti melakukan gzip, penghentian SSL, dll. Anda harus menggunakan layanan middleware yang ‘asli’ seperti nginx, HAproxy atau layanan vendor cloud

Jika tidak: Thread utama Anda akan tetap sibuk melakukan tugas infrastruktur alih-alih menangani inti aplikasi Anda dan performa akan menurun karenanya

🔗 Baca selengkapnya: Delegate anything possible (e.g. gzip, SSL) to a reverse proxy



✔ 5.4. Kunci dependensi

TL;DR: Kode Anda harus identik di semua lingkungan, namun npm dapat membiarkan dependensi berubah di lingkungan yang berbeda – saat Anda menginstal paket di lingkungan lain npm mencoba menginstal versi terbaru dari paket tersebut. Atasi ini dengan menggunakan file konfigurasi , .npmrc, yang memberi tahu setiap lingkungan untuk menyimpan versi yang tepat (bukan yang terbaru) dari setiap paket. Alternatifnya, untuk kontrol yang lebih baik, gunakan npm shrinkwrap. *Pembaruan: pada NPM5, dependensi dikunci secara default. Manajer paket yang baru, Yarn, juga melakukan hal ini

Jika tidak: QA akan menguji kode secara menyeluruh dan menyetujui versi yang kemudian akan berperilaku berbeda dalam produksi. Lebih buruk lagi, server yang berbeda dalam kelompok produksi mungkin menjalankan kode yang berbeda

🔗 Baca selengkapnya: Lock dependencies



✔ 5.5. Jaga uptime proses menggunakan alat yang tepat

TL;DR: Proses harus tetap berjalan dan dimulai ulang jika terjadi kegagalan. Untuk skenario simpel, alat manajemen proses seperti PM2 mungkin sudah cukup namun di era ‘dockerized’, alat management cluster juga harus dipertimbangkan

Jika tidak: Menjalankan banyak instansi tanpa strategi yang jelas dan terlalu banyak alat (manajemen cluster, docker, PM2) dapat menyebabkan kekacauan DevOps

🔗 Baca selengkapnya: Guard process uptime using the right tool



✔ 5.6. Manfaatkan semua core CPU

TL;DR: Pada dasarnya, aplikasi Node berjalan pada satu core CPU sementara core lainnya tidak digunakan. Ini merupakan tugas Anda untuk mereplika proses Node dan menggunakan semua CPU – Untuk aplikasi kecil-menengah Anda dapat menggunakan Node Cluster atau PM2. Untuk aplikasi yang lebih besar pertimbangkan untuk mereplika proses menggunakan beberapa Docker cluster (misalnya K8S, ECS) atau skrip deployment yang didasarkan pada sistem Linux init (misalnya systemd)

Jika tidak: Aplikasi Anda kemungkinan hanya menggunakan 25% dari sumber daya yang tersedia(!) atau bahkan kurang. Ingat bahwa server tipikal memiliki 4 core CPU atau lebih, deployment Node.js yang naif hanya menggunakan 1 (bahkan jika menggunakan layanan PaaS seperti AWS beanstalk!)

🔗 Baca selengkapnya: Utilize all CPU cores



✔ 5.7. Buat ‘endpoint pemeliharaan’

TL;DR: Sediakan sekumpulan informasi terkait sistem, seperti penggunaan memori dan REPL, dll. dalam API yang aman. Meskipun sangat disarankan untuk mengandalkan alat standar dan battle-test, beberapa informasi penting dan operasi lebih mudah dilakukan melalui kode

Jika tidak: Anda akan melakukan banyak “deploy diagnostik” – mendeploy kode ke produksi hanya untuk mengekstrak beberapa informasi untuk keperluan diagnostik

🔗 Baca selengkapnya: Create a ‘maintenance endpoint’



✔ 5.8. Temukan kesalahan dan downtime menggunakan produk APM

TL;DR: Application monitoring and performance products (a.k.a APM) secara proaktif mengukur basis kode dan API sehingga mereka dapat secara otomatis melampaui pemantauan tradisional dan mengukur pengalaman pengguna secara keseluruhan di semua layanan dan tingkatan. Misalnya, beberapa produk APM dapat menyoroti transaksi yang terlalu lambat di sisi pengguna sambil menyarankan penyebab utamanya

Jika tidak: Anda mungkin menghabiskan banyak tenaga untuk mengukur kinerja dan downtime API, mungkin Anda tidak akan pernah tau bagian kode mana yang paling lambat dalam skenario dunia nyata dan bagaimana hal ini dapat memengaruhi pengalaman pengguna

🔗 Baca selengkapnya: Discover errors and downtime using APM products



✔ 5.9. Buat kode Anda siap produksi

TL;DR: Buat kode dengan tujuan akhir ada dalam pikiran Anda, rencanakan untuk produksi dari hari pertama. Ini terdengar kurang jelas jadi saya telah mengumpulkan beberapa tips pengembangan yang berkaitan erat dengan perawatan produksi (klik intinya di bawah)

Jika tidak: Seorang juara dunia IT/DevOps tidak akan memperbaiki sistem yang ditulis dengan buruk

🔗 Baca selengkapnya: Make your code production-ready



✔ 5.10. Ukur dan jaga penggunaan memori

TL;DR: Node.js memiliki hubungan yang kontroversial dengan memori: mesin v8 memiliki batas memori yang rendah (1.4GB) dan terdapat cara yang diketahui untuk terjadinya kebocoran memori dalam kode Node – sehingga mengamati memori proses Node adalah suatu keharusan. Pada aplikasi kecil, Anda dapat mengukur memori Anda secara berkala menggunakan perintah shell namun di aplikasi menengah-besar pertimbangkan untuk membuat sistem pemantauan yang kuat untuk mengamati memori

Jika tidak: Memori proses Anda mungkin bocor ratusan megabyte sehari seperti yang terjadi pada Walmart

🔗 Baca selengkapnya: Measure and guard the memory usage



✔ 5.11. Keluarkan aset frontend Anda dari Node

TL;DR: Sajikan konten frontend menggunakan middleware khusus (nginx, S3, CDN) karena performa Node dapat berkurang ketika menangani banyak file statis karena model thread tunggalnya

Jika tidak: Thread tunggal Node Anda akan sibuk mengirimkan ratusan file html/gambar/angular/react alih-alih mengalokasikan semua sumber dayanya untuk tugas yang seharusnya – menyajikan konten dinamis

🔗 Baca selengkapnya: Get your frontend assets out of Node



✔ 5.12. Buat aplikasi yang stateless, matikan server Anda hampir setiap hari

TL;DR: Simpan semua jenis data (misalnya sesi pengguna, cache, file yang diunggah) ke tempat penyimpanan eksternal. Pertimbangkan untuk ‘mematikan’ server Anda secara berkala atau gunakan platform ‘serverless’ (misalnya AWS Lambda) yang secara eksplisit mengharuskan sifat stateless

Jika tidak: Kegagalan di server tertentu akan mengakibatkan downtime aplikasi, bukannya hanya mematikan mesin yang rusak. Selain itu, elastisitas penskalaan akan menjadi lebih sulit karena ketergantungan pada server tertentu

🔗 Baca selengkapnya: Be stateless, kill your Servers almost every day



✔ 5.13. Gunakan alat yang pendeteksi kerentanan secara otomatis

TL;DR: Bahkan dependensi yang paling terkemuka seperti Express memiliki kerentanan yang diketahui (dari waktu ke waktu) yang dapat membahayakan sistem. Hal ini dapat dimitigasi dengan mudah menggunakan alat dari komunitas atau komersial yang terus-menerus memeriksa kerentanan dan memberi peringatan (secara lokal atau di GitHub), beberapa bahkan dapat langsung memperbaikinya

Jika tidak: Menjaga kode Anda bersih dari kerentanan tanpa alat khusus mengharuskan Anda untuk mengikuti publikasi online tentang ancaman baru. Cukup membosankan

🔗 Baca selengkapnya: Use tools that automatically detect vulnerabilities



✔ 5.14. Tetapkan id transaksi di seetiap statement catatan

TL;DR: Tetapkan pengenal yang sama, transaksi-id: {sebuah nilai}, ke setiap entri catatan dalam satu permintaan. Kemudian saat memeriksa kesalahan di dalam catatan, simpulkan dengan mudah apa yang terjadi sebelum dan sesudahnya. Sayangnya, hal ini tidak mudah untuk dicapai di Node karena sifat asinkron-nya, lihat contoh kode di dalam

Jika tidak: Melihat catatan kesalahan produksi tanpa konteks – apa yang terjadi sebelumnya – membuat Anda lebih sulit untuk memahami penyebab kesalahannya

🔗 Baca selengkapnya: Assign ‘TransactionId’ to each log statement



✔ 5.16. Atur NODE_ENV=production

TL;DR: Atur variabel lingkungan NODE_ENV ke ‘production’ or ‘development’ untuk menandai apakah pengoptimalan produksi harus diaktifkan – banyak paket npm melihat lingkungan yang digunakan dan mengoptimalkan kodenya untuk produksi

Jika tidak: Mengabaikan properti sederhana ini dapat menurunkan performa. Contohnya, pada saat menggunakan Express untuk rendering sisi server menghilangkan NODE_ENV membuat proses render lebih lambat hingga 3 kali lipat!

🔗 Baca selengkapnya: Set NODE_ENV=production



✔ 5.16. Rancang deployment otomatis, atomic dan tanpa downtime

TL;DR: Penelitian menunjukkan bahwa tim yang melakukan banyak deployment menurunkan kemungkinan masalah produksi yang buruk. Deployment yang otomatis dan cepat tidak memerlukan langkah manual yang berisiko dan waktu downtime layanan meningkatkan proses deployment. Anda mungkin harus melakukan ini menggunakan Docker yang dikombinasikan dengan alat CI karena mereka menjadi standar industri untuk deployment yang efisien

Jika tidak: Deployment yang lama -> downtime produksi & kesalahan oleh manusia -> tim ragu dalam melakukan deployment -> lebih sedikit deployment dan fitur



✔ 5.17. Gunakan versi LTS pada Node.js

TL;DR: Pastikan Anda menggunakan versi LTS pada Node.js untuk menerima perbaikan bug yang kritis, pembaruan keamanan dan peningkatan performa

Otherwise: Bug atau kerentanan yang baru ditemukan dapat digunakan untuk mengeksploitasi aplikasi yang sedang berjalan dalam produksi, dan aplikasi Anda mungkin menjadi tidak didukung oleh berbagai modul dan lebih sulit untuk di dipelihara

🔗 Baca selengkapnya: Use an LTS release of Node.js



✔ 5.18. Jangan rutekan catatan di dalam aplikasi

TL;DR: Tempat catatan tidak boleh dibuat oleh pengembang dalam kode aplikasi, tetapi harus ditentukan oleh lingkungan eksekusi dimana aplikasi itu dijalankan. Pengembang harus menuliskan catatan ke stdout menggunakan utilitas logger dan membiarkan lingkungan eksekusi (container, server, dll.) menyalurkan stdout ke tujuan yang sesuai (misalnya Splunk, Graylog, ElasticSearch, dll.).

Jika tidak: Aplikasi menangani rute catatan === sulit untuk dikembangkan, kehilangan catatan, dan separation of concerns yang buruk

🔗 Baca selengkapnya: Log Routing



✔ 5.19. Install paket menggunakan npm ci

TL;DR: Anda harus memastikan bahwa kode produksi menggunakan versi paket yang sama dengan yang Anda gunakan pada saat pengujian. Jalankan npm ci untuk melakukan instalasi bersih dari dependensi di dalam package.json dan package-lock.json. Penggunaan perintah ini sangat direkomendasikan dalam lingkungan otomatis seperti pipeline continuous integration.

Jika tidak: QA akan menguji kode secara menyeluruh dan menyetujui versi yang kemudian akan berperilaku berbeda dalam produksi. Lebih buruk lagi, server yang berbeda dalam kelompok produksi mungkin menjalankan kode yang berbeda.

🔗 Baca selengkapnya: Use npm ci




⬆ Kembali ke atas

6. Praktik Terbaik Keamanan

54 items

✔ 6.1. Terapkan aturan keamanan linter

TL;DR: Manfaatkan plugin linter yang berhubungan dengan keamanan seperti eslint-plugin-security untuk menangkap kerentanan dan masalah keamanan sedini mungkin, lebih baik lagi jika dalam proses pembuatan kode. Hal ini dapat membantu menangkap keamanan yang lemah seperti penggunaan eval, menjalankan child process atau memanggil modul menggunakan literal string (misalnya masukan pengguna). Klik 'Baca selengkapnya' di bawah ini untuk melihat contoh kode yang akan dideteksi oleh linter keamanan

Jika tidak: Kelemahan keamanan yang jelas selama masa pengembangan malah menjadi masalah besar dalam produksi. Selain itu, proyek mungkin tidak mengikuti praktik kode keamanan yang konsisten, yang mengarah ke kerentanan baru, atau rahasia sensitif yang ter-commit ke dalam repositori remote

🔗 Baca selengkapnya: Lint rules



✔ 6.2. Batasi request serentak dengan menggunakan middleware

TL;DR: Serangan DOS sangat populer dan relatif mudah untuk dilakukan. Terapkan pembatasan rate menggunakan layanan eksternal seperti cloud load balancers, cloud firewalls, nginx, paket rate-limiter-flexible, atau (untuk aplikasi yang lebih kecil dan kurang penting) sebuah middleware rate-limiting (misalnya express-rate-limit)

Jika tidak: Aplikasi dapat terkena serangan denial of service sementara pengguna asli menggunakan layanan yang terdegradasi atau tidak tersedia.

🔗 Baca selengkapnya: Implement rate limiting



✔ 6.3 Keluarkan rahasia dari file konfigurasi atau gunakan paket untuk mengenkripsinya

TL;DR: Jangan pernah menyimpan rahasia dalam bentuk teks biasa dalam file konfigurasi atau kode sumber. Sebagai gantinya, gunakan sistem manajemen rahasia seperti produk Vault, Kubernetes/Docker Secrets, atau gunakan variabel lingkungan. Sebagai cara terakhir, rahasia yang disimpan di kontrol kode harus terenkripsi dan teratur (kunci bergulir, kedaluwarsa, audit, dll.). Manfaatkan hook pra-commit/push untuk mencegah agar rahasia tidak ter-commit secara tidak sengaja

Jika tidak: Kontrol sumber, bahkan untuk repositori pribadi, dapat di buat publik secara tidak sengaja, di mana semua rahasia dapat terungkap. Akses kontrol sumber dari pihak eksternal dapat memberikan akses ke sistem terkait (database, api, layanan, dll.) secara tidak sengaja.

🔗 Baca selengkapnya: Secret management



✔ 6.4. Cegah injeksi kueri dengan menggunakan pustaka ORM/ODM

TL;DR: Untuk mencegah injeksi SQL/NoSQL dan serangan buruk lainnya, selalu gunakan ORM/ODM atau pustaka database yang melakukan escape pada data atau mendukung kueri berparameter yang bernama atau diindeks, dan tangani validasi masukan pengguna agar sesuai dengan tipe yang diharapkan. Jangan pernah hanya menggunakan template string JavaScript atau penggabungan string untuk memasukkan nilai ke dalam kueri karena ini membuka aplikasi Anda ke spektrum kerentanan yang luas. Semua pustaka akses data pada Node.js (misalnya Sequelize, Knex, mongoose) memiliki perlindungan bawaan untuk menghindari serangan injeksi.

Jika tidak: Masukan pengguna yang tidak divalidasi atau tidak disanitasi dapat menyebabkan injeksi operator saat menggunakan MongoDB untuk NoSQL, dan dengan tidak menggunakan sistem sanitasi atau ORM dapat memungkinkan serangan injeksi SQL, membuat suatu kerentanan yang besar.

🔗 Baca selengkapnya: Query injection prevention using ORM/ODM libraries



✔ 6.5. Kumpulan praktik terbaik keamanan umum

TL;DR: Ini adalah kumpulan saran keamanan yang tidak berhubungan langsung dengan Node.js - implementasi pada Node tidak jauh berbeda dengan implementasi pada bahasa lain. Klik 'Baca selengkapnya' untuk membaca sekilas.

🔗 Baca selengkapnya: Common security best practices



✔ 6.6. Sesuaikan header response HTTP untuk meningkatkan keamanan

TL;DR: Aplikasi Anda harus menggunakan header yang aman untuk mencegah penyerang dari serangan umum seperti cross-site scripting (XSS), clickjacking dan serangan berbahaya lainnya. Hal ini dapat dikonfigurasikan dengan mudah menggunakan modul seperti helmet.

Jika tidak: Penyerang dapat melakukan serangan langsung pada pengguna aplikasi, yang menyebabkan kerentanan keamanan yang sangat besar

🔗 Baca selengkapnya: Using secure headers in your application



✔ 6.7. Selalu periksa dependensi dari kerentanan secara otomatis

TL;DR: Dengan ekosistem npm, sangat umum pada suatu proyek untuk memiliki banyak dependensi. Dependensi harus selalu diperiksa ketika kerentanan baru ditemukan. Gunakan alat seperti npm audit atau snyk untuk melacak, memantau dan memperbaiki dependensi yang rentan. Integrasikan alat-alat ini dengan setup CI Anda sehingga Anda dapat menemukan dependensi yang rentan sebelum masuk ke produksi.

Jika tidak: Penyerang dapat mendeteksi framework web Anda dan menyerang semua kerentanan yang diketahui.

🔗 Baca selengkapnya: Dependency security



✔ 6.8. Lindungi kata sandi/rahasia pengguna menggunakan bcrypt atau scrypt

TL;DR: Kata sandi atau rahasia (seperti API keys) harus disimpan menggunakan fungsi hash + salt yang aman seperti bcrypt,scrypt, atau setidaknya pbkdf2.

Jika tidak: Kata sandi dan rahasia yang disimpan tanpa fungsi yang aman akan rentan terhadap brute force dan penyerangan kamus yang pada akhirnya akan mengarah pada data rahasia yang terekspos.

🔗 Baca selengkapnya: User Passwords



✔ 6.9. Escape keluaran HTML, JS dan CSS

TL;DR: Data yang tidak terpercaya yang dikirim ke browser mungkin akan tereksekusi alih-alih hanya ditampilkan, hal ini biasanya disebut dengan serangan cross-site-scripting (XSS). Hindari hal ini dengan menggunakan pustaka khusus yang secara eksplisit menandai data sebagai konten yang tidak boleh dieksekusi (misalnya encoding, escaping)

Jika tidak: Penyerang mungkin menyimpan kode JavaScript yang berbahaya di DB Anda yang kemudian akan dikirim apa adanya ke pengguna

🔗 Baca selengkapnya: Escape output



✔ 6.10. Validasi skema JSON yang diterima

TL;DR: Validasi muatan body pada request dan pastikan agar muatan memenuhi ekspektasi, gagalkan dengan cepat jika muatan tidak memenuhi ekspektasi. Untuk menghindari kode validasi yang berantakan dalam setiap rute Anda dapat menggunakan validasi skema berbasis JSON yang ringan seperti jsonschema atau joi

Jika tidak: Kemurahan hati dan cara permisif Anda dapat meningkatkan kemungkinan penyerangan dan mendorong penyerang untuk mencoba banyak masukan sampai mereka menemukan beberapa kombinasi untuk merusak aplikasi

🔗 Baca selengkapnya: Validate incoming JSON schemas



✔ 6.11. Dukung daftar hitam JWT

TL;DR: Ketika menggunakan JSON Web Tokens (misalnya, dengan Passport.js), secara default tidak ada cara untuk mencabut akses dari token yang dibuat. Setelah Anda menemukan beberapa aktifitas pengguna yang berbahaya, tidak ada cara untuk mengentikan mereka dari mengakses sistem selama mereka mempunyai token yang valid. Hindari ini dengan menerapkan daftar hitam untuk token yang tidak tepercaya yang divalidasi pada setiap request.

Jika tidak: Token yang kedaluwarsa atau salah ditempatkan dapat digunakan secara jahat oleh pihak ketiga untuk mengakses aplikasi dan menyamar sebagai pemilik token.

🔗 Baca selengkapnya: Blacklist JSON Web Tokens



✔ 6.12. Cegah serangan brute-force terhadap otorisasi

TL;DR: Teknik sederhana dan kuat adalah membatasi upaya otorisasi menggunakan dua metrik:

  1. Pertama adalah upaya gagal berturut-turut oleh ID / nama unik dan alamat IP yang sama.
  2. Kedua adalah jumlah upaya gagal dari sebuah alamat IP selama jangka waktu yang lama. Misalnya, blokir alamat IP jika IP tersebut melakukan 100 upaya gagal dalam satu hari.

Jika tidak: Penyerang dapat melakukan percobaan kata sandi otomatis tanpa batas untuk mendapatkan akses ke akun yang memiliki hak istimewa pada suatu aplikasi

🔗 Baca selengkapnya: Login rate limiting



✔ 6.13. Jalankan Node.js sebagai pengguna yang bukan root

TL;DR: Ada skenario umum di mana Node.js dijalankan sebagai pengguna root dengan izin tanpa batas. Misalnya, ini adalah perilaku default di kontainer Docker. Direkomendasikan untuk membuat pengguna yang bukan root dan bake pengguna itu ke dalam Docker image (contoh ada di bawah) atau jalankan proses atas nama pengguna ini dengan menjalankan kontainer dengan flag "-u username"

Jika tidak: Penyerang yang berhasil menjalankan skrip di server mendapatkan kekuatan tak terbatas atas mesin lokal (misalnya mengganti iptable dan merutekan ulang traffic ke servernya)

🔗 Baca selengkapnya: Run Node.js as non-root user



✔ 6.14. Batasi ukuran payload menggunakan reverse-proxy atau middleware

TL;DR: Semakin besar ukuran payload-nya, semakin sulit thread tunggal Anda untuk memprosesnya. Ini adalah kesempatan bagi penyerang untuk membuat server bertekuk lutut tanpa banyak mengirimkan request (penyerangan DOS/DDOS). Hindari ini dengan membatasi ukuran body dari request yang masuk di ujung (misalnya firewall, ELB) atau mengonfigurasi express body parser agar hanya menerima payload dengan ukuran kecil

Jika tidak: Aplikasi Anda harus menangani request yang besar, tidak dapat memproses pekerjaan penting lainnya yang harus diselesaikan, yang mengarah ke implikasi performa dan kerentanan terhadap serangan DOS

🔗 Baca selengkapnya: Limit payload size



✔ 6.15. Hindari statement eval pada JavaScript

TL;DR: eval sangat buruk karena memungkinkan untuk mengeksekusi kode JavaScript dalam run time. Ini bukan hanya menjadi perhatian dalam performa tetapi juga perhatian dalam masalah keamanan penting karena kode JavaScript dapat bersumber dari masukan pengguna. Fitur bahasa lain yang harus dihindari adalah konstruktor new Function. setTimeout dan setInterval juga tidak boleh diberikan kode JavaScript yang dinamis.

Jika tidak: Kode JavaScript yang berbahaya menemukan jalan ke dalam teks yang diteruskan ke eval atau fungsi evaluasi real-time bahasa Javascript lainnya, dan akan mendapatkan akses penuh ke izin JavaScript di halaman tersebut. Kerentanan ini sering kali diwujudkan sebagai serangan XSS.

🔗 Baca selengkapnya: Avoid JavaScript eval statements



✔ 6.16. Cegah RegEx yang buruk agar tidak membebani eksekusi thread tunggal Anda

TL;DR: Regular Expressions, meskipun berguna, dapat menimbulkan ancaman pada aplikasi JavaScript secara luas, dan platform Node.js pada khususnya. Masukan teks pengguna mungkin memerlukan jumlah siklus CPU yang luar biasa untuk diproses. Pemrosesan RegEx mungkin tidak efisien sampai-sampai satu request yang memvalidasi 10 kata dapat memblokir seluruh event loop selama 6 detik dan membuat CPU-nya 🔥. Oleh karena itu, gunakan paket validasi pihak ketiga seperti validator.js daripada menuliskan pola Regex Anda sendiri, atau gunakan safe-regex untuk mendeteksi pola regex yang rentan

Jika tidak: Regex yang ditulis dengan buruk dapat rentan terhadap serangan DoS Regular Expression yang akan memblokir event loop sepenuhnya. MIsalnya, paket moment yang populer ditemukan rentan terhadap penggunaan Regex pada November 2017

🔗 Baca selengkapnya: Prevent malicious RegEx



✔ 6.17. Hindari pemuatan modul menggunakan variabel

TL;DR: Hindari pemuatan file lain dengan jalur yang diberikan sebagai parameter karena dikhawatirkan dapat berasal dari masukan pengguna. Aturan ini dapat diperluas untuk mengakses file secara umum (yaitu fs.readFile()) atau pengaksesan sumber sensitif lainnya dengan variabel dinamis yang berasal dari masukan pengguna. Linter Eslint-plugin-security dapat menangkap pola seperti itu dan memberi peringatan cukup dini

Jika tidak: Masukan pengguna yang berbahaya dapat menemukan jalannya ke parameter yang digunakan untuk memuat file, misalnya, file yang sebelumnya diunggah ke sistem file, atau pengaksesan file sistem yang sudah ada.

🔗 Baca selengkapnya: Safe module loading



✔ 6.18. Jalankan kode yang tidak aman di sandbox

TL;DR: Saat ditugaskan untuk menjalankan kode eksternal yang diberikan pada run-time (misalnya plugin), gunakan segala jenis lingkungan eksekusi 'sandbox' yang mengisolasi dan melindungi kode utama dari plugin tersebut. Hal ini dapat dicapai dengan menggunakan proses khusus (misalnya cluster.fork()), lingkungan serverless atau paket npm khusus yang bertindak sebagai sandbox

JIka tidak: Sebuah plugin dapat menyerang dengan berbagai pilihan seperti perulangan tak terbatas, memberi muatan lebih pada memori, dan mengakses variabel lingkungan sensitif pada proses

🔗 Baca selengkapnya: Run unsafe code in a sandbox



✔ 6.19. Berhati-hati saat menggunakan child processes

TL;DR: Hindari penggunaan child processes jika memungkinkan dan validasi serta sanitasi masukan untuk menghindari serangan injeksi shell jika Anda masih perlu menggunakannya. Utamakan penggunaan child_process.execFile yang menurut definisi hanya akan menjalankan satu perintah dengan sekumpulan atribut dan tidak akan mengizinkan perluasan parameter shell.

Jika tidak: Penggunaan child process yang naif dapat mengakibatkan eksekusi perintah secara remote atau serangan injeksi shell karena masukan pengguna yang berbahaya diteruskan ke perintah sistem yang tidak disanitasi.

🔗 Baca selengkapnya: Be cautious when working with child processes



✔ 6.20. Sembunyikan detail kesalahan dari klien

TL;DR: Penangan kesalahan express menyembunyikan detail kesalahan secara default. Namun, besar kemungkinan Anda menerapkan logika penanganan kesalahan Anda sendiri dengan objek Error kustom (dianggap sebagai praktik terbaik oleh banyak orang). Jika iya, pastikan Anda tidak mengembalikan seluruh objek error ke klien, yang mungkin mengandung beberapa informasi aplikasi yang sensitif

Jika tidak: Informasi sensitif aplikasi seperti path file server, modul pihak ketiga yang digunakan, dan alur kerja internal aplikasi lainnya yang dapat dieksploitasi oleh penyerang, dapat dibocorkan dari informasi yang ditemukan di dalam stack trace

🔗 Baca selengkapnya: Hide error details from client



✔ 6.21. Konfigurasi 2FA untuk npm atau Yarn

TL;DR: Setiap langkah dalam rantai pengembangan harus dilindungi dengan MFA (multi-factor authentication), npm/Yarn menjadi peluang yang bagus bagi penyerang yang ingin mendapatkan kata sandi pengembang. Dengan menggunakan kredensial pengembang, penyerang dapat memasukkan kode berbahaya ke dalam pustaka yang diinstal secara luas di seluruh proyek dan layanan. Bahkan mungkin di seluruh web jika dipublikasikan. Mengaktifkan 2-factor-authentication dalam npm akan meninggalkan hampir nol peluang bagi penyerang untuk mengubah kode paket Anda.

Jika tidak: Pernahkah Anda mendengar tentang pengembang eslint yang kata sandinya dibajak?



✔ 6.22. Ubah pengaturan middleware sesi

TL;DR: Setiap framework dan teknologi web mempunyai kelemahannya masing-masing - memberi tahu penyerang framework web apa yang digunakan sangat membantu mereka. Menggunakan setelan default untuk middleware sesi dapat membuat aplikasi Anda terkena pembajakan spesifik untuk module dan framework dengan cara yang mirip dengan header X-Powered-By. Coba sembunyikan apa pun yang mengidentifikasikan dan mengungkapkan teknologi yang Anda gunakan (misalnya Node.js, express)

Jika tidak: Cookie dapat dikirim melalui koneksi yang tidak aman, dan penyerang dapat menggunakan identifikasi sesi untuk mengidentifikasi framework dari aplikasi web, serta kerentanan masing-masing modul

🔗 Baca selengkapnya: Cookie and session security



✔ 6.23. Hindari serangan DOS dengan mengatur kapan proses harus berhenti secara eksplisit

TL;DR: Proses Node akan berhenti ketika ada kesalahan yang tidak ditangani. Banyak praktik terbaik bahkan merekomendasikan untuk menghentikan aplikasi meskipun ada kesalahan yang tertangkap dan ditangani. Express, misalnya, akan berhenti jika ada kesalahan asinkron apa pun - kecuali Anda membungkus rute dengan klausa catch. Ini memberikan kesempatan serangan yang sangat bagus bagi penyerang yang mengetahui masukan apa yang memberhentikan proses dan mengirim request yang sama berulang kali. Tidak ada solusi instan untuk ini tapi ada beberapa teknik yang dapat mengurangi hal ini: Beri peringatan kritis setiap kali proses berhenti karena ada kesalahan yang ditangani, validasi masukan dan hindari memberhentikan proses karena masukan pengguna tidak valid, bungkus semua rute dengan catch dan pertimbangkan untuk tidak memberhentikan aplikasi ketika kesalahan berasal dari dalam request (alih-alih apa yang terjadi secara global)

Jika tidak: Ini hanya tebakan: mengingat banyak aplikasi Node.js, jika kita memberikan JSON kosong ke semua request POST - banyak aplikasi akan berhenti. Pada saat itu, kita dapat mengirim permintaan yang sama berulang kali untuk memberhentikan aplikasi itu dengan mudah



✔ 6.24. Hindari pengalihan yang tidak aman

TL;DR: Pengalihan yang tidak memvalidasi masukan pengguna dapat memungkinkan penyerang untuk meluncurkan penipuan phising, mencuri kredensial pengguna, dan melakukan tindakan berbahaya lainnya.

Jika tidak: Jika penyerang menemukan bahwa Anda tidak memvalidasi masukan eksternal yang diberikan oleh pengguna, mereka dapat mengeksploitasi kerentanan ini dengan memposting tautan yang dibuat khusus di forum, media sosial, dan tempat publik lainnya agar pengguna mengkliknya.

🔗 Baca selengkapnya: Prevent unsafe redirects



✔ 6.25. Hindari menerbitkan rahasia ke registri npm

TL;DR: Tindakan pencegahan harus diambil untuk menghindari risiko penerbitan rahasia ke registri publik npm secara tidak sengaja. File .npmignore dapat digunakan untuk memasukkan file atau folder ke dalam blacklist, atau array files dalam package.json dapat digunakan sebagai whitelist.

Jika tidak: Kunci API, kata sandi atau rahasia lain proyek Anda dapat disalahgunakan oleh siapapun yang menemukannya, yang dapat mengakibatkan kerugian finansial, peniruan identitas, dan risiko lainnya.

🔗 Baca selengkapnya: Avoid publishing secrets


⬆ Kembali ke atas

7. Draf: Praktik Terbaik Performa

Kontributor kami sedang mengerjakan bagian ini. Ingin bergabung?



✔ 7.1. Jangan memblokir event loop

TL;DR: Hindari pekerjaan yang intensif CPU karena mereka akan memblokir Event Loop dalam satu thread dan pindahkan pekerjaan ini ke thread khusus, proses atau bahkan teknologi yang berbeda berdasarkan konteksnya.

Jika tidak: Ketika Event Loop diblokir, Node.js tidak akan dapat menangani permintaan lain sehingga menyebabkan penundaan bagi pengguna lain. 3000 pengguna sedang menunggu tanggapan, konten siap diberikan, tapi satu permintaan mencegah server-nya untuk mengirimkan hasilnya

🔗 Baca selengkapnya: Do not block the event loop




✔ 7.2. Utamakan penggunaan metode JS asli daripada utilitas berlebihan seperti Lodash

TL;DR: Sering kali lebih merugikan jika menggunakan pustaka seperti lodash dan underscore daripada metode asli karena mengarah kepada dependensi yang tidak diperlukan dan memperlambat performa. Ingatlah bahwa dengan diperkenalkannya mesin V8 baru bersama dengan standar ES baru, metode asli telah ditingkatkan sehingga sekarang sekitar 50% lebih baik daripada pustaka utilitas.

Jika tidak: Anda harus mengurus proyek dengan kinerja yang lebih rendah di mana Anda dapat menggunakan apa yang sudah ada atau berurusan dengan lebih sedikit baris namun lebih banyak file sebagai gantinya.

🔗 Baca selengkapnya: Native over user land utils




⬆ Kembali ke atas

8. Praktik Terbaik Docker

🏅 Terima kasih banyak kepada Bret Fisher yang mengajari kami banyak dari praktik berikut



✔ 8.1 Gunakan build multi tahap untuk gambar Docker yang lebih kecil dan aman

TL;DR: Gunakan build multi tahap hanya untuk menyalin artefak produksi yang diperlukan. Banyak file dan dependensi build-time yang tidak diperlukan untuk menjalankan aplikasi Anda. Dengan build multi tahap resource ini dapat digunakan selama build sementara lingkungan runtime hanya berisikan dengan resource yang diperlukan. Build multi tahap adalah cara mudah untuk menyingkirkan kelebihan berat dan ancaman keamanan.

Jika tidak: Gambar yang lebih besar akan memakan waktu yang lebih lama untuk di-build dan dikirim, alat khusus build mungkin mengandung kerentanan dan rahasia yang hanya dimaksudkan untuk fase build mungkin dapat bocor.

Contoh dockerfle untuk build multi tahap

FROM node:14.4.0 AS build

COPY . .
RUN npm ci && npm run build


FROM node:slim-14.4.0

USER node
EXPOSE 8080

COPY --from=build /home/node/app/dist /home/node/app/package.json /home/node/app/package-lock.json ./
RUN npm ci --production

CMD [ "node", "dist/app.js" ]

🔗 Baca selengkapnya: Use multi-stage builds




✔ 8.2. Lakukan bootstrap menggunakan perintah 'node', hindari npm start

TL;DR: Gunakan CMD ['node','server.js'] untuk memulai aplikasi Anda, hindari menggunakan skrip npm yang tidak meneruskan sinyal OS ke kode. Ini mencegah masalah dengan proses anak, penanganan sinyal, pemberhentian yang baik dan proses zombie.

Jika tidak: Ketika tidak ada sinyal yang dilewatkan, kode Anda tidak akan pernah diberi tahu tentang penghentian. Tanpa itu, kode Anda akan kehilangan kesempatan untuk berhenti dengan benar dan kehilangan permintaan dan/atau data dapat terjadi.

Baca selengkapnya: Bootstrap container using node command, avoid npm start




✔ 8.3. Biarkan runtime Docker menangani replikasi dan uptime

TL;DR: Ketika menggunakan orkestrator run time Docker (misalnya Kubernetes), aktifkan proses Node.js seecara langsung tanpa manajer proses perantara atau kode khusus yang mereplikasi proses (misalnya PM2, modul Cluster). Platform runtime mempunyai jumlah data dan visibilitas tertinggi untuk membuat keputusan penempatan - Platform ini mengetahui dengan baik berapa banyak proses yang diperlukan, cara menyebarkannya dan apa yang harus dilakukan jika terjadi kerusakan

Jika tidak: Kontainer tetap rusak karena kekurangan sumber daya akan dimulai ulang tanpa batas oleh manajer proses. Jika Kubernetes menyadari hal ini, Kubernetes dapat memindahkannya ke banyak instance yang berbeda

🔗 Baca selengkapnya: Let the Docker orchestrator restart and replicate processes




✔ 8.4. Gunakan .dockerignore untuk mencegah pembocoran rahasia

TL;DR: Sertakan file .dockerignore yang memfilter file rahasia umum dan artefak pengembangan. Dengan melakukan itu, Anda dapat mencegah kebocoran rahasia ke dalam gambar. Sebagai bonus waktu build akan berkurang secara signifikan. Pastikan juga untuk tidak menyalin semua file secara rekursif melainkan pilih file yang harus disalin ke Docker secara eksplisit

Jika tidak: File rahasia pribadi umum seperti .env, .aws dan .npmrc akan dibagikan dengan siapapun yang memiliki akses ke image (misalnya repositori Docker)

🔗 Baca selengkapnya: Use .dockerignore




✔ 8.5. Bersihkan dependensi sebelum produksi

TL;DR: Meskipun dependensi pengembangan terkadang diperlukan selama siklus hidup build pengujian, pada akhirnya gambar yang dikirim ke produksi harus minimal dan bersih dari dependensi pengembangan. Hal tersebut dapat menjamin hanya kode yang diperlukan yang dikirim dan jumlah potensi serangan (misalnya attack surface) diminimalkan. Ketika menggunakan build multi tahap (lihat poin khusus) hal ini dapat dicapai dengan menginstal semua dependensi terlebih dahulu dan kemudian menjalankan npm ci --production

Jika tidak: Banyak penerobosan keamanan npm yang buruk ditemukan dalam paket pengembangan (misalnya eslint-scope)

🔗 **Baca selengkapnya: Remove development dependencies




✔ 8.6. Matikan aplikasi dengan baik dan cerdas

TL;DR: Tangani proses event SIGTERM dan bersihkan semua koneksi dan sumber daya yang ada. Hal ini harus dilakukan sambil menanggapi permintaan yang sedang berlangsung. Dalam runtime Docker, mematikan kontainer bukanlah peristiwa yang jarang terjadi, melainkan sesuatu yang sering terjadi sebagai bagian dari pekerjaan rutin. Untuk mencapai hal ini, diperlukan beberapa kode yang baik untuk mengatur beberapa bagian yang bergerak: load balancer, koneksi keep-alive, server HTTP dan sumber daya lainnya

Jika tidak: Mematikan aplikasi secara langsung berarti tidak menanggapi ribuan pengguna yang kecewa

🔗 Baca selengkapnya: Graceful shutdown




✔ 8.7. Tetapkan batas memori menggunakan Docker dan v8

TL;DR: Selalu konfigurasikan batas memori menggunakan Docker dan runtime flag JavaScript. Batas pada Docker diperlukan untuk membuat keputusan penempatan kontainer yang baik, flag max-old-space pada --v8 diperlukan untuk memulai GC tepat waktu untuk mencegah penggunaan memori yang kurang. Secara praktis, tetapkan batas memori max-old-space pada v8 sedikit lebih rendah dari pada batas memori kontainer

Jika tidak: Definisi Docker diperlukan untuk melakukan keputusan penskalaan yang baik dan mencegah kelaparan warga lain. Tanpa menentukan batas pada v8 juga, sumber daya kontainer juga akan kurang digunakan oleh Node - Tanpa instruksi eksplisit Node akan berhenti saat menggunakan ~50-60% dari sumber daya hostnya

🔗 Baca selengkapnya: Set memory limits using Docker only




✔ 8.8. Rencanakan caching yang efisien

TL;DR: Membangun ulang seluruh image docker dari cache dapat dilakukan hampir seketika jika dilakukan dengan benar. Instruksi yang jarang diperbarui harus berada di atas Dockerfile Anda dan yang terus berubah (seperti kode app) harus berada di bawah.

Jika tidak: Build Docker akan sangat lama dan memakan banyak sumber daya bahkan saat melakukan perubahan kecil

🔗 Baca selengkapnya: Leverage caching to reduce build times




✔ 8.9. Gunakan referensi gambar eksplisit, hindari tag latest

TL;DR: Tentukan digest eksplisit gambar atau label berversi, jangan pernah merujuk ke latest. Pengembang sering kali percaya bahwa menetapkan tag latest akan memberi mereka gambar terbaru di repositori namun hal ini tidak benar. Menggunakan digest menjamin bahwa setiap instansi layanan menjalankan kode yang sama persis.

Selain itu, merujuk ke sebuah tag gambar berarti gambar dasar dapat berubah, karena tag image tidak dapat diandalkan untuk penginstalan deterministik. Jika penginstalan deterministik diharapkan, digest SHA256 dapat digunakan untuk mereferensikan ke gambar yang tepat.

Jika tidak: Versi baru gambar dasar dapat dideploy ke produksi dengan perubahan yang dapat merusak, menyebabkan perilaku aplikasi yang tidak diinginkan.

🔗 Baca selengkapnya: Understand image tags and use the "latest" tag with caution




✔ 8.10. Utamakan gambar dasar Docker yang lebih kecil

TL;DR: Gambar yang besar mempunyai tingkat kerentanan yang lebih tinggi dan meningkatkan konsumsi sumber daya. Menggunakan gambar docker yang lebih ramping, seperti varian Linux Slim dan Alpine, dapat mengurangi masalah ini.

Jika tidak: Membangun, mendorong, dan menarik gambar akan membutuhkan waktu yang lebih lama, vektor serangan yang tidak diketahui dapat digunakan oleh aktor jahat dan lebih banyak sumber daya yang dikonsumsi.

🔗 Baca selengkapnya: Prefer smaller images




✔ 8.11. Bersihkan rahasia pada build-time, hindari rahasia di args

TL;DR: Hindari rahasia yang bocor dari lingkungan build Docker. Gambar Docker biasanya terbagi di beberapa lingkungan seperti CI dan registri yang tidak disterilkan seperti lingkungan produksi. Contoh tipikalnya adalah token npm yang biasanya diteruskan ke dockerfile sebagai argumen. Token ini tetap berada di dalam gambar lama setelah diperlukan dan memungkinkan penyerang mengakses tanpa batas ke registri npm pribadi. Hal ini dapat dihindari dengan mengatasi file rahasia seperti .npmrc dan kemudian menghapusnya menggunakan build mutli tahap (hati-hati, rahasia build juga harus dihapus) atau dengan menggunakan fitur rahasia build-kit Docker yang tidak meninggalkan jejak

Jika tidak: Setiap orang yang mempunyai akses ke CI dan registri Docker juga akan mendapatkan akses ke rahasia organisasi yang berharga sebagai bonus

🔗 Baca selengkapnya: Clean-out build-time secrets




✔ 8.12. Pindai gambar untuk menemukan lapisan kerentanan

TL;DR: Selain memeriksa kerentanan kode dependensi pastikan juga untuk memindai gambar akhir yang dikirim ke produksi. Pemindai gambar Docker memeriksa kode dependensi tapi juga binari OS. Pemindaian keamanan E2E ini mencakup lebih banyak hal dan memverifikasi bahwa tidak ada orang jahat yang menginjeksi hal-hal buruk selama build. Oleh karena itu, disarankan untuk menjalankan hal ini sebagai langkah terakhir sebelum proses deployment. Ada beberapa pemindai gratis dan komersial yang juga menyediakan plugin CI/CD

Jika tidak: Kode Anda mungkin sepenuhnya bebas dari kerentanan. Namun itu mungkin masih dapat diretas karena versi binari OS-level yang rentan (misalnya OpenSSL, TarBall) yang biasanya digunakan oleh aplikasi

🔗 Baca selengkapnya: Generic Docker practices




✔ 8.13 Bersihkan cache NODE_MODULE

TL;DR: Setelah menginstal dependensi dalam kontainer, hapus cache lokal. Tidak masuk akal untuk menduplikasi dependensi untuk penginstalan lebih cepat di masa mendatang karena tidak akan ada penginstalan lagi seterusnya - Image Docker tidak dapat diubah. Dengan menggunakan satu baris kode, puluhan MB (biasanya 10-50% dari ukuran gambar) dihilangkan

Jika tidak: Gambar yang akan dikirim ke produksi akan menjadi 30% lebih besar karena file yang tidak akan pernah digunakan

🔗 Baca selengkapnya: Clean NODE_MODULE cache




✔ 8.14. Praktik Docker umum

TL;DR: Ini adalah kumpulan saran Docker yang tidak terkait langsung dengan Node.js - implementasi pada Node tidak jauh berbeda dengan bahasa lain. Klik baca selengkapnya untuk membaca sekilas.

🔗 Baca selengkapnya: Generic Docker practices




✔ 8.15. Lint Dockerfile Anda

TL;DR: Melakukan lint pada Dockerfile Anda adalah langkah yang penting untuk mengidentifikasi masalah di Dockerfile Anda yang tidak ada di praktik terbaik. Dengan memeriksa potensi kekurangan menggunakan linter Docker khusus, peningkatan performa dan keamanan dapat dengan mudah diidentifikasi, menghemat waktu yang terbuang atau mengurangi masalah keamanan dalam kode produksi.

Jika tidak: Secara tidak sengaja pembuat Dockerfile meninggalkan Root sebagai pengguna produksi, dan juga menggunakan gambar dari repositori yang tidak dikenal. Hal ini dapat dihindari hanya dengan linter sederhana.

🔗 Baca selengkapnya: Lint your Dockerfile




⬆ Kembali ke atas

Tonggak Sejarah

Untuk menjaga panduan ini agar tetap mutakir, kami terus memperbarui dan meningkatkan pedoman dan praktik terbaik ini dengan bantuan komunitas. Anda dapat mengikuti milestones dan bergabung dalam kelompok kerja jika Anda ingin berkontribusi pada proyek ini


Terjemahan

Semua terjemahan merupakan kontribusi dari komunitas. Kami akan dengan senang hati mendapatkan bantuan baik untuk terjemahan yang telah selesai, sedang berlangsung atau yang baru!

Terjemahan selesai

Terjemahan dalam proses



Komite Pengarah

Memperkenalkan anggota komite pengarah - orang-orang yang bekerja sama untuk memberikan panduan dan arahan masa depan proyek. Selain itu, setiap anggota komite memimpin proyek yang dilacak dalam Github projects kami.

Yoni Goldberg

Konsultan Node.js independen yang bekerja dengan pelanggan di AS, Eropa, dan Israel dalam membangun aplikasi Node.js berskala besar. Banyak praktik terbaik di atas pertama kali dipublikasikan di goldbergyoni.com. Hubungi Yoni di @goldbergyoni atau [email protected]


Bruno Scheufler

💻 Engineer web full-stack, penggemar Node.js & GraphQL


Kyle Martin

Pengembang Full Stack & Site Reliability Engineer yang berbasis di Selandia Baru, tertarik pada keamanan aplikasi web, dan merancang serta membangun aplikasi Node.js untuk bekerja dalam skala global.


Kevyn Bruyere

Pengembang full-stack independen dengan selera untuk Ops dan otomatisasi.


Mantan Komite Pengarah

Sagir Khan

Spesialis mendalam dalam JavaScript dan ekosistemnya — React, Node.js, TypeScript, GraphQL, MongoDB, hampir semua hal yang berhubungan dengan JS/JSON di setiap lapisan sistem — membuat produk menggunakan platform web untuk merek paling terkenal di dunia. Anggota perorangan dari Node.js Foundation.


Kolaborator

Terima kasih untuk semua kolaborator kami! 🙏

Kolaborator kami adalah anggota yang sering berkontribusi ke repositori ini, melalui menyarankan praktik terbaik baru, menyortir masalah, meninjau pull request dan banyak lagi. Jika Anda tertarik untuk membantu kami memandu ribuan orang untuk membuat aplikasi Node.js yang lebih baik, silakan baca contributor guidelines 🎉

Ido Richter (Founder) Keith Holliday

Mantan Kolaborator

Refael Ackermann

Kontribusi

Jika Anda pernah ingin berkontribusi pada open source, sekarang kesempatan Anda! Lihat contributing docs untuk informasi lebih lanjut.

Kontributor ✨

Terima kasih kepada orang-orang hebat ini yang telah berkontribusi pada repositori ini!


Kevin Rambaud

🖋

Michael Fine

🖋

Shreya Dahal

🖋

Matheus Cruz Rocha

🖋

Yog Mehta

🖋

Kudakwashe Paradzayi

🖋

t1st3

🖋

mulijordan1976

🖋

Matan Kushner

🖋

Fabio Hiroki

🖋

James Sumners

🖋

Dan Gamble

🖋

PJ Trainor

🖋

Remek Ambroziak

🖋

Yoni Jah

🖋

Misha Khokhlov

🖋

Evgeny Orekhov

🖋

-

🖋

Isaac Halvorson

🖋

Vedran Karačić

🖋

lallenlowe

🖋

Nathan Wells

🖋

Paulo Reis

🖋

syzer

🖋

David Sancho

🖋

Robert Manolea

🖋

Xavier Ho

🖋

Aaron

🖋

Jan Charles Maghirang Adona

🖋

Allen

🖋

Leonardo Villela

🖋

Michał Załęcki

🖋

Chris Nicola

🖋

Alejandro Corredor

🖋

cwar

🖋

Yuwei

🖋

Utkarsh Bhatt

🖋

Duarte Mendes

🖋

Jason Kim

🖋

Mitja O.

🖋

Sandro Miguel Marques

🖋

Gabe

🖋

Ron Gross

🖋

Valeri Karpov

🖋

Sergio Bernal

🖋

Nikola Telkedzhiev

🖋

Vitor Godoy

🖋

Manish Saraan

🖋

Sangbeom Han

🖋

blackmatch

🖋

Joe Reeve

🖋

Ryan Busby

🖋

Iman Mohamadi

🖋

Sergii Paryzhskyi

🖋

Kapil Patel

🖋

迷渡

🖋

Hozefa

🖋

Ethan

🖋

Sam

🖋

Arlind

🖋

Teddy Toussaint

🖋

Lewis

🖋

Gabriel Lidenor

🖋

Roman

🖋

Francozeira

🖋

Invvard

🖋

Rômulo Garofalo

🖋

Tho Q Luong

🖋

Burak Shen

🖋

Martin Muzatko

🖋

Jared Collier

🖋

Hilton Meyer

🖋

ChangJoo Park(박창주)

🖋

Masahiro Sakaguchi

🖋

Keith Holliday

🖋

coreyc

🖋

Maximilian Berkmann

🖋

Douglas Mariano Valero

🖋

Marcelo Melo

🖋

Mehmet Perk

🖋

ryan ouyang

🖋

Shabeer

🖋

Eduard Kyvenko

🖋

Deyvison Rocha

🖋

George Mamer

🖋

Konstantinos Leimonis

🖋

Oliver Lluberes

🌍

Tien Do

🖋

Ranvir Singh

🖋

Vadim Nicolaev

🖋 🌍

German Gamboa Gonzalez

🖋

Hafez

🖋

Chandiran

🖋

VinayaSathyanarayana

🖋

Kim Kern

🖋

Kenneth Freitas

🖋

songe

🖋

Kirill Shekhovtsov

🖋

Serge

🖋

keyrwinz

🖋

Dmitry Nikitenko

🖋

bushuai

👀 🖋

Benjamin Gruenbaum

🖋

Ezequiel

🌍

Juan José Rodríguez

🌍

Or Bin

🖋

Andreo Vieira

🖋

Michael Solomon

🖋

Jimmy Callin

🖋

Siddharth

🖋

Ryan Smith

🖋

Tom Boettger

🖋

Joaquín Ormaechea

🌍

dfrzuz

🌍

Victor Homyakov

🖋

Josh

🖋 🛡️

Alec Francis

🖋

arjun6610

🖋

Jan Osch

🖋

Thiago Rotondo Sampaio

🌍

Alexsey

🖋

Luis A. Acurero

🌍

Lucas Romano

🌍

Denise Case

🖋

Nick Ribal

🖋 👀

0xflotus

🖋

Jonathan Chen

🖋

Dilan Srilal

🖋

vladthelittleone

🌍

Nik Osvalds

🖋

Daniel Kiss

📖

Forresst

🖋

Jonathan Svenheden

🖋

AustrisC

🖋

kyeongtae kim

🌍

007

🖋

Ane Diaz de Tuesta

🌍 🖋

YukiOta

🌍

Frazer Smith

🖋

Raz Luvaton

🖋

Yuta Azumi

🖋

andrewjbarbour

🖋

mr

🖋

Aleksandar

🖋

Owl

🖋

Yedidya Schwartz

🖋 💡

ari

🖋

Thomas König

🖋

Kalle Lämsä

🖋

Wyatt

🖋

KHADIR Tayeb

🖋