Sorotan Django: Perselisihan Aset Statis Dan Berkas Media (Bagian 4)
Diterbitkan: 2022-03-10Situs web Django melibatkan banyak file. Ini bukan hanya kode sumber untuk konfigurasi, model, tampilan, dan template, tetapi juga aset statis: CSS dan JavaScript, gambar, ikon. Seolah itu belum cukup, terkadang pengguna datang dan ingin mengunggah file mereka sendiri ke situs web Anda. Itu cukup untuk membuat pengembang mana pun tidak percaya. File di mana-mana!
Di sinilah saya berharap bisa mengatakan (tanpa peringatan): “Jangan khawatir, Django mendukung Anda!” Namun sayangnya, ketika berhadapan dengan aset statis dan file media, ada banyak peringatan yang harus dihadapi.
Hari ini, kami akan membahas penyimpanan dan penyajian file untuk server tunggal dan penerapan yang dapat diskalakan sambil mempertimbangkan faktor-faktor seperti kompresi, caching, dan ketersediaan. Kami juga akan membahas biaya dan manfaat CDN dan solusi penyimpanan file khusus.
Catatan : Ini bukan tutorial tentang cara menyebarkan situs Django ke platform tertentu. Alih-alih, seperti artikel lainnya dalam seri Sorotan Django (lihat di bawah), ini dimaksudkan sebagai panduan bagi pengembang dan perancang front-end untuk memahami bagian lain dari proses pembuatan aplikasi web. Hari ini, kami berfokus pada apa yang terjadi setelah hotfix gaya atau grafik indah yang baru saja Anda selesaikan didorong untuk dikuasai. Bersama-sama, kami akan mengembangkan intuisi untuk strategi yang tersedia bagi pengembang Django untuk menyajikan file-file ini kepada pengguna di seluruh dunia dengan cara yang aman, berkinerja, dan hemat biaya.
Bagian Sebelumnya Dalam Seri:
- Bagian 1: Model Pengguna Dan Otentikasi
- Bagian 2: Membuat Template Menghemat Garis
- Bagian 3: Model, Admin, Dan Memanfaatkan Basis Data Relasional
definisi
Sebagian besar istilah ini cukup mudah, tetapi ada baiknya meluangkan waktu sejenak untuk membangun kosakata bersama untuk diskusi ini.
Tiga jenis file dalam aplikasi Django langsung adalah:
- Kode sumber
File Python dan HTML yang dibuat dengan kerangka kerja Django. File-file ini adalah inti dari aplikasi. File kode sumber umumnya cukup kecil, diukur dalam kilobyte. - File Statis
Juga disebut "aset statis", file-file ini termasuk CSS dan JavaScript, keduanya ditulis oleh pengembang aplikasi dan perpustakaan pihak ketiga, serta PDF, penginstal perangkat lunak, gambar, musik, video, dan ikon. File-file ini hanya digunakan di sisi klien. File statis berkisar dari beberapa kilobyte CSS hingga gigabyte video. - File Media
File apa pun yang diunggah oleh pengguna, dari gambar profil hingga dokumen pribadi, disebut file media. File-file ini harus disimpan dan diambil dengan aman dan andal untuk pengguna. File media dapat berukuran berapa pun, pengguna dapat mengunggah beberapa kilobyte teks biasa ke beberapa gigabyte video. Jika Anda berada di ujung akhir skala ini, Anda mungkin memerlukan saran yang lebih khusus daripada yang siap diberikan artikel ini.
Dua jenis penyebaran Django adalah:
- Server Tunggal
Penyebaran Django server-tunggal persis seperti yang terdengar: semuanya hidup di satu server. Strategi ini sangat sederhana dan sangat mirip dengan lingkungan pengembangan, tetapi tidak dapat menangani lalu lintas dalam jumlah besar atau tidak konsisten secara efektif. Pendekatan server tunggal hanya berlaku untuk proyek pembelajaran atau demonstrasi, bukan aplikasi nyata yang membutuhkan waktu kerja yang andal. - Dapat diskalakan
Ada banyak cara berbeda untuk menyebarkan proyek Django yang memungkinkannya untuk menskalakan untuk memenuhi permintaan pengguna. Strategi ini sering kali melibatkan memutar naik turun banyak server dan menggunakan alat seperti penyeimbang beban dan database terkelola. Untungnya, kami dapat secara efektif menggabungkan segala sesuatu yang lebih kompleks daripada penerapan server tunggal ke dalam kategori ini untuk tujuan artikel ini.
Opsi 1: Django bawaan
Proyek kecil mendapat manfaat dari arsitektur sederhana. Penanganan default Django dari aset statis dan file media hanya itu: sederhana. Untuk masing-masing, Anda memiliki folder root yang menyimpan file dan tinggal tepat di sebelah kode sumber di server. Sederhana. Folder root ini dibuat dan dikelola sebagian besar melalui konfigurasi yourproject/settings.py .
Aset Statis
Hal terpenting untuk dipahami ketika bekerja dengan file statis di Django adalah perintah python manage.py collectstatic
. Perintah ini menelusuri folder statis dari setiap aplikasi dalam proyek Django dan menyalin semua aset statis ke folder akar. Menjalankan perintah ini adalah bagian penting dari penggelaran proyek Django. Perhatikan struktur direktori berikut:
- project - project - settings.py - urls.py - ... - app1 - static/ - app1 - style.css - script.js - img.jpg - templates/ - views.py - ... - app2 - static/ - app2 - style.css - image.png - templates/ - views.py - ...
Juga asumsikan pengaturan berikut di project/settings.py :
STATIC_URL = "/static/" STATIC_ROOT = "/path/on/server/to/djangoproject/static"
Menjalankan perintah python manage.py collectstatic
akan membuat folder berikut di server:
- /path/on/server/to/djangoproject/static - app1 - style.css - script.js - img.jpg - app2 - style.css - image.png
Perhatikan bahwa di dalam setiap folder statis, ada folder lain dengan nama aplikasi. Ini untuk mencegah konflik penspasian nama setelah file statis dikumpulkan; seperti yang Anda lihat dalam struktur file di atas, ini membuat app1/style.css dan app2/style.css berbeda. Dari sini, aplikasi akan mencari file statis dalam struktur ini di STATIC_ROOT
selama produksi. Dengan demikian, referensikan file statis sebagai berikut dalam template di app1/templates/ :
{% load static %} <link rel="stylesheet" type="text/css" href="{% static "app1/style.css" %}">
Django secara otomatis mencari tahu dari mana mendapatkan file statis dalam pengembangan untuk memodelkan perilaku ini, Anda tidak perlu menjalankan collectstatic
selama pengembangan.
Untuk detail lebih lanjut, lihat dokumentasi Django.
File Media
Bayangkan sebuah situs jaringan profesional dengan database pengguna. Masing-masing pengguna tersebut akan memiliki profil terkait, yang mungkin berisi, antara lain, gambar avatar dan dokumen resume. Berikut adalah contoh model singkat dari informasi tersebut:
from django.db import models from django.contrib.auth.models import User def avatar_path(instance, filename): return "avatar_{}_{}".format(instance.user.id, filename) class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) resume = models.FileField(upload_to="path/string") avatar = models.ImageField(upload_to=avatar_path)
Agar ini berfungsi, Anda memerlukan opsi berikut di project/settings.py , seperti dengan aset statis:
MEDIA_URL = "/media/" MEDIA_ROOT = "/path/on/server/to/media"
ImageField
mewarisi dari FileField
, sehingga memiliki parameter dan kemampuan yang sama. Kedua bidang memiliki argumen upload_to
opsional, yang mengambil string yang merupakan jalur dan menambahkannya ke MEDIA_ROOT
untuk menyimpan file, yang kemudian dapat diakses dengan jalur yang sama di atas MEDIA_URL
. Argumen upload_to
juga dapat mengambil fungsi yang mengembalikan string, seperti yang ditunjukkan dengan fungsi avatar_path
.
Pastikan untuk menghilangkan direktori file media dan isinya dari kontrol versi. Isinya mungkin bertentangan ketika dua pengembang menguji aplikasi yang sama pada mesin yang berbeda, dan itu, tidak seperti aset statis, bukan bagian dari aplikasi Django yang dapat disebarkan.
Opsi 2: Django Dengan Layanan
Filosofi panduan saya adalah menggunakan alat untuk hal yang terbaik. Django adalah kerangka kerja yang luar biasa, dan menyediakan perkakas hebat di luar kotak untuk otentikasi pengguna, rendering sisi server, bekerja dengan model dan formulir, fungsi administratif, dan lusinan aspek penting lainnya dalam membangun aplikasi web. Namun, perkakasnya untuk menangani aset statis dan file media, menurut pendapat saya, tidak cocok untuk produksi di situs yang dapat diskalakan. Pengembang inti Django mengenali bahwa banyak orang memilih pendekatan alternatif untuk menangani file-file ini dalam produksi; kerangka kerja sangat baik untuk keluar dari jalan Anda ketika Anda melakukannya. Sebagian besar situs Django yang dimaksudkan untuk penggunaan umum ingin menggabungkan aset statis dan menangani file media menggunakan pendekatan non-Django-spesifik ini.
Aset Statis Pada CDN
Sementara proyek kecil-menengah bisa lolos tanpa satu, CDN (jaringan pengiriman konten) mudah digunakan dan meningkatkan kinerja aplikasi dari berbagai ukuran. CDN adalah jaringan server, umumnya di seluruh dunia, yang mendistribusikan dan menyajikan konten web, sebagian besar aset statis. CDN populer termasuk Cloudflare CDN, Amazon CloudFront, dan Fastly. Untuk menggunakan CDN, Anda mengunggah file statis Anda, lalu dalam aplikasi Anda merujuknya sebagai berikut:
<link rel="stylesheet" type="text/css" href="https://cdn.example.com/path/to/your/files/app1/style.css">
Proses ini mudah diintegrasikan dengan skrip penerapan Django Anda. Setelah menjalankan perintah python manage.py collectstatic
, salin direktori yang dihasilkan ke CDN Anda (proses yang sangat bervariasi berdasarkan layanan yang Anda gunakan), kemudian hapus aset statis dari paket penerapan Django.
Dalam pengembangan, Anda ingin mengakses salinan berbeda dari aset statis Anda daripada di produksi. Dengan cara ini, Anda dapat membuat perubahan secara lokal tanpa memengaruhi situs produksi. Anda dapat menggunakan aset lokal atau menjalankan instance kedua dari CDN untuk mengirimkan file. Konfigurasikan proyek/settings.py Anda dengan beberapa variabel khusus, seperti CDN_URL
, dan gunakan nilai itu di template Anda untuk memastikan Anda menggunakan versi aset yang benar dalam pengembangan dan produksi.
Satu catatan terakhir adalah bahwa banyak perpustakaan untuk CSS dan JavaScript memiliki CDN gratis yang dapat digunakan sebagian besar situs web. Jika Anda memuat, katakanlah, Bootstrap 4 atau underscore.js, Anda dapat melewati kerumitan menggunakan salinan Anda sendiri dalam pengembangan dan biaya untuk melayani salinan Anda sendiri dalam produksi dengan menggunakan CDN publik ini.
File Media dengan Filestore Khusus
Tidak ada situs Django produksi yang harus menyimpan file pengguna dalam folder /media/ sederhana di suatu tempat di server yang menjalankan situs. Berikut adalah tiga dari banyak alasan mengapa tidak:
- Jika Anda perlu meningkatkan situs dengan menambahkan beberapa server, Anda memerlukan beberapa cara untuk menyalin dan menyinkronkan file yang diunggah di seluruh server tersebut.
- Jika server mogok, kode sumber dicadangkan di sistem kontrol versi Anda, tetapi file media tidak dicadangkan secara default, kecuali jika Anda mengonfigurasi server Anda untuk melakukannya, tetapi untuk upaya itu Anda akan lebih baik menggunakan dedicated penyimpanan file.
- Dalam kasus aktivitas jahat, lebih baik menyimpan file yang diunggah pengguna di server terpisah dari server yang menjalankan aplikasi, meskipun ini sama sekali tidak menghilangkan persyaratan untuk memvalidasi file yang diunggah pengguna.
Mengintegrasikan pihak ketiga untuk menyimpan file yang Anda unggah pengguna sangatlah mudah. Anda tidak perlu mengubah apa pun dalam kode Anda, kecuali mungkin menghapus atau memodifikasi nilai upload_to
dari FileField
s di model Anda, dan mengonfigurasi beberapa pengaturan. Misalnya, jika Anda berencana untuk menyimpan file Anda di AWS S3, Anda ingin melakukan hal berikut, yang sangat mirip dengan proses penyimpanan file dengan Google Cloud, Azure, Backblaze, atau layanan pesaing serupa.
Pertama, Anda harus menginstal pustaka boto3
dan django-storages
. Kemudian, Anda perlu menyiapkan ember dan peran IAM di AWS, yang berada di luar cakupan artikel ini, tetapi Anda dapat melihat petunjuknya di sini. Setelah semua itu dikonfigurasi, Anda perlu menambahkan tiga variabel ke project/settings.py Anda :
DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" AWS_STORAGE_BUCKET_NAME = "BUCKET_NAME" AWS_S3_REGION_NAME = "us-east-2"
Selain itu, Anda perlu menyiapkan akses kredensial ke bucket AWS Anda. Beberapa tutorial akan menunjukkan penambahan ID dan kunci rahasia ke file pengaturan Anda atau sebagai variabel lingkungan, tetapi ini adalah praktik yang tidak aman. Sebagai gantinya, gunakan django-storages
dengan AWS CLI untuk mengonfigurasi kunci, seperti yang dijelaskan di sini. Anda mungkin juga tertarik dengan dokumentasi django-storages
.
Anda tidak ingin pengembangan atau pengujian file media tercampur dengan unggahan dari pengguna sebenarnya. Menghindari ini cukup sederhana: siapkan beberapa ember, satu untuk pengembangan (atau satu untuk setiap pengembang), satu untuk pengujian, dan satu untuk produksi. Kemudian, yang perlu Anda ubah hanyalah pengaturan AWS_STORAGE_BUCKET_NAME
per lingkungan dan Anda siap melakukannya.
Performa Dan Ketersediaan
Ada banyak faktor yang memengaruhi kinerja dan keandalan situs web Anda. Berikut adalah beberapa yang penting ketika mempertimbangkan file statis dan media yang penting terlepas dari pendekatan mana yang Anda ambil untuk mengelolanya.
Biaya
Melayani file ke pengguna membutuhkan biaya karena dua alasan: penyimpanan dan bandwidth. Anda harus membayar penyedia hosting untuk menyimpan file untuk Anda, tetapi Anda juga harus membayar mereka untuk melayani file. Bandwidth jauh lebih mahal daripada penyimpanan (misalnya, AWS S3 mengenakan biaya 2,3 sen per gigabyte untuk penyimpanan versus 9 sen per gigabyte transfer data ke Internet pada saat penulisan). Ekonomi penyimpanan file seperti S3 atau CDN berbeda dari ekonomi host umum seperti tetesan Digital Ocean. Manfaatkan spesialisasi dan skala ekonomi dengan memindahkan file mahal ke layanan yang dirancang untuk mereka. Selain itu, banyak penyimpanan file dan CDN menawarkan paket gratis sehingga situs yang mungkin cukup kecil untuk pergi tanpa menggunakannya dapat melakukannya dan menuai keuntungan tanpa biaya infrastruktur tambahan.
Kompresi dan Transcoding
Sebagian besar masalah yang disebabkan oleh aset statis seperti foto dan video adalah karena mereka adalah file besar. Secara alami, pengembang mengatasi ini dengan mencoba membuat file-file ini lebih kecil. Ada beberapa cara untuk melakukan ini menggunakan campuran kompresi dan transcoding dalam dua kategori umum: lossless dan lossy. Kompresi lossless mempertahankan kualitas asli aset tetapi memberikan penurunan ukuran file yang relatif sederhana. Kompresi lossy, atau transcoding ke dalam format lossy, memungkinkan ukuran file yang jauh lebih kecil dengan mengorbankan beberapa kualitas artefak asli. Contohnya adalah transcoding video ke bitrate yang lebih rendah. Untuk detailnya, lihat artikel ini tentang mengoptimalkan pengiriman video. Saat menyajikan file besar melalui web, kecepatan bandwidth sering kali mengharuskan Anda menyajikan artefak yang sangat terkompresi, yang memerlukan kompresi lossy.
Kecuali Anda YouTube, kompresi dan transcoding tidak terjadi dengan cepat. Aset statis harus diformat dengan tepat sebelum penerapan, dan Anda dapat menerapkan jenis file dasar dan batasan ukuran file pada unggahan pengguna untuk memastikan kompresi yang memadai dan pemformatan yang sesuai di file media pengguna Anda.
Minifikasi
Meskipun file JavaScript dan CSS biasanya tidak sebesar gambar, mereka sering kali dapat dikompresi menjadi lebih sedikit byte. Proses ini disebut minifikasi. Minifikasi tidak mengubah penyandian file, file tersebut masih berupa teks, dan file yang diperkecil masih memerlukan kode yang valid untuk bahasa aslinya. File yang diperkecil mempertahankan ekstensi aslinya.
Hal utama yang dihapus dalam file yang diperkecil adalah spasi putih yang tidak perlu, dan dari sudut pandang komputer, hampir semua spasi putih dalam CSS dan JavaScript tidak diperlukan. Skema minifikasi juga mempersingkat nama variabel dan menghapus komentar.
Minifikasi secara default mengaburkan kode; sebagai pengembang, Anda harus bekerja secara eksklusif dengan file yang tidak diperkecil. Beberapa langkah otomatis selama proses penerapan harus mengecilkan file sebelum disimpan dan disajikan. Jika Anda menggunakan perpustakaan yang disediakan oleh CDN pihak ketiga, pastikan Anda menggunakan versi perpustakaan yang diperkecil jika tersedia. File HTML dapat diperkecil, tetapi karena Django menggunakan rendering sisi server, biaya pemrosesan untuk melakukannya dengan cepat kemungkinan besar akan lebih besar daripada penurunan kecil dalam ukuran halaman.
Ketersediaan Global
Sama seperti waktu yang dibutuhkan untuk mengirim surat ke tetangga Anda lebih sedikit daripada mengirimnya ke seluruh negeri, begitu juga waktu yang dibutuhkan untuk mengirimkan data di sekitar daripada ke seluruh dunia. Salah satu cara CDN meningkatkan kinerja halaman adalah dengan menyalin aset ke server di seluruh dunia. Kemudian, ketika klien membuat permintaan, mereka menerima aset statis dari server terdekat (sering disebut node tepi), mengurangi waktu muat. Salah satu keuntungan menggunakan CDN dengan situs Django adalah memisahkan distribusi global aset statis Anda dari distribusi global kode Anda.
Caching Sisi Klien
Apa yang lebih baik daripada memiliki file statis di server di dekat pengguna Anda? Memiliki file statis yang sudah tersimpan di perangkat pengguna Anda! Caching adalah proses penyimpanan hasil komputasi atau request agar dapat diakses berulang kali dengan lebih cepat. Sama seperti stylesheet CSS yang dapat di-cache di seluruh dunia dalam CDN, CSS dapat di-cache di browser klien saat pertama kali mereka memuat halaman dari situs Anda. Kemudian, stylesheet tersedia di perangkat itu sendiri dalam permintaan berikutnya, sehingga klien membuat lebih sedikit permintaan, meningkatkan waktu buka halaman, dan mengurangi penggunaan bandwidth.
Peramban melakukan operasi caching mereka sendiri, tetapi jika situs Anda menikmati lalu lintas substansial, Anda dapat mengoptimalkan perilaku caching sisi klien Anda menggunakan kerangka kerja cache Django.
Kesimpulannya
Sekali lagi, filosofi panduan saya adalah menggunakan alat untuk hal yang terbaik. Proyek server tunggal dan penerapan skala kecil dengan hanya aset statis ringan dapat menggunakan manajemen aset statis bawaan Django, tetapi sebagian besar aplikasi harus memisahkan aset untuk dilayani melalui CDN.
Jika proyek Anda ditujukan untuk jenis penggunaan kata nyata apa pun, jangan simpan file media dengan metode default Django, alih-alih gunakan layanan. Dengan lalu lintas yang cukup, di mana "lalu lintas yang cukup" adalah jumlah yang relatif kecil pada skala Internet, komplikasi tambahan untuk arsitektur, proses pengembangan, dan penyebaran lebih dari sepadan untuk kinerja, keandalan, dan penghematan biaya menggunakan CDN terpisah dan solusi penyimpanan file untuk file statis dan media, masing-masing.
Bacaan yang Direkomendasikan
- Bagian 1: Model Pengguna Dan Otentikasi
- Bagian 2: Membuat Template Menghemat Garis
- Bagian 3: Model, Admin, Dan Memanfaatkan Basis Data Relasional