Menu

express.static: Menyajikan File Statis di Express

app.use(express.static(path.join(__dirname, 'public'))) menyajikan setiap file di folder public pada URL yang sesuai: public/style.css menjawab /style.css. Tambahkan mount path untuk menyajikannya di bawah sebuah prefix.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

express.static adalah middleware bawaan yang menyajikan file dari sebuah folder. app.use(express.static(path.join(__dirname, 'public'))) membuat setiap file di public tersedia di path yang sama di URL: public/style.css menjawab /style.css, dan public/index.html menjawab /. Express mengatur Content-Type dari ekstensi file, dan saat tidak ada file yang cocok, ia meneruskan request ke route-mu alih-alih menjawab 404.

Jawaban untuk GET /style.css adalah teks file-nya, dengan Content-Type: text/css; charset=utf-8 di tab Headers. Kirim GET / untuk mendapat index.html, lalu GET /api/time: tidak ada file seperti itu, jadi route-nya yang menjawab.

Kenapa path folder butuh __dirname

express.static('public') me-resolve 'public' terhadap folder tempat kamu menjalankan Node, bukan folder tempat server.js berada. Ini bekerja saat kamu menjalankan node server.js di dalam proyek dan rusak saat process manager atau script menjalankan aplikasinya dari tempat lain:

// project/server.js uses express.static('public')
// cd project && node server.js      -> serves project/public
// node project/server.js            -> looks for ./public, every file is 404

path.join(__dirname, 'public') adalah folder di samping file yang berisi baris itu, dari mana pun Node dijalankan. Di ES module, pakai path.join(import.meta.dirname, 'public') (Node 20.11 ke atas). Halaman module path membahas __dirname dan path.join secara detail.

Menyajikan file di bawah prefix

Berikan mount path lebih dulu untuk menyajikan folder di bawah prefix URL. Prefix itu bukan bagian dari path file di disk:

GET /assets/app.js mengembalikan console.log("hi"); sebagai text/javascript, dan GET /assets/img/dot.svg menjangkau subfolder. Kirim GET /app.js tanpa prefix: hasilnya 404, karena file-file itu hanya ada di bawah /assets. Pakai prefix supaya URL file tidak bertabrakan dengan route API-mu.

Header cache dengan maxAge

Secara default Express mengirim Cache-Control: public, max-age=0, jadi browser mengecek ke server setiap kali memakai file (dan mendapat 304 Not Modified yang cepat saat file-nya tidak berubah, berkat header ETag). Untuk file yang namanya berubah di setiap build, seperti app.3f9a1c.js, minta browser menyimpannya:

Buka tab Headers: Cache-Control sekarang public, max-age=604800, tujuh hari dalam detik. index: false mematikan penyajian index.html untuk URL folder. Opsi berguna lainnya adalah extensions: ['html'], yang membuat /about menemukan about.html, dan dotfiles, yang secara default 'ignore' sehingga file seperti .env tidak pernah disajikan.

Single page app: kembali ke index.html

Aplikasi React atau Vue yang dibangun dengan routing di sisi client butuh setiap path yang tidak dikenal mengembalikan index.html, supaya reload di /settings tidak 404. Taruh fallback-nya setelah express.static dan route API-mu:

app.use(express.static(path.join(__dirname, 'dist')));
app.use('/api', apiRouter);

// Express 5 wildcard syntax
app.get('/*splat', (req, res) => {
    res.sendFile(path.join(__dirname, 'dist', 'index.html'));
});

Kesalahan umum

Menyertakan nama folder di URL. Dengan app.use(express.static('public')) URL-nya adalah /style.css, bukan /public/style.css. Kalau kamu ingin /public ada di URL, pasang sebagai mount path: app.use('/public', express.static(...)).

Menautkan file dengan path relatif di HTML. <link href="style.css"> di halaman /blog/post meminta /blog/style.css. Awali path-nya dengan slash: /style.css.

Menaruh rahasia di folder statis. Semua yang ada di dalamnya bersifat publik. Jauhkan file config, key, dan source code dari folder itu.

Pertanyaan yang sering diajukan

Bisakah aku memakai express.static lebih dari sekali?

Bisa. Daftarkan satu per folder; Express mencari di folder-folder itu sesuai urutan penambahannya dan menyajikan file pertama yang ditemukan. Beri masing-masing mount path sendiri kalau folder-foldernya bisa berisi file dengan nama yang sama.

Sebaiknya Express menyajikan file statis di production?

Untuk aplikasi kecil tidak masalah. Untuk traffic tinggi, taruh CDN atau reverse proxy seperti Nginx di depannya, yang menyajikan file lebih cepat dan menyimpannya di cache lebih dekat ke user, dan biarkan Express mengurus API.

Bagaimana mengirim satu file tertentu dari sebuah route?

Pakai res.sendFile(path.join(__dirname, 'files', 'report.pdf')). Path-nya harus absolut (atau kamu memberikan opsi root). Pakai res.download() saat browser sebaiknya menyimpan file-nya, bukan menampilkannya.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai