Membangun Aplikasi Cuaca dengan Webpack dan Vanilla JS
Sebagai bagian dari kurikulum The Odin Project, saya membangun sebuah aplikasi cuaca. Proyek ini bukan sekadar latihan mengambil data dari API, melainkan sebuah tantangan untuk mengintegrasikan berbagai praktik pengembangan web modern dalam satu proyek yang kohesif.
Dalam tulisan ini, saya akan membagikan pengalaman dan keputusan teknis di balik layar, mulai dari proses bundling aset dengan Webpack, strategi efisiensi saat mengambil data cuaca, hingga alur kerja Git yang saya terapkan.
- Demo Langsung: Odin Weather App
- Repositori GitHub: ulumdcode/odin-weather
Pendahuluan
Aplikasi ini dirancang untuk menampilkan informasi cuaca saat ini beserta prakiraan lima hari ke depan berdasarkan kota yang dicari pengguna. Tujuan utamanya adalah untuk mengasah tiga keterampilan fundamental dalam pengembangan web modern:
- Modern JavaScript Tooling: Menggunakan Webpack untuk mengelola assets (JavaScript, CSS) dan environment variables.
- Asynchronous JavaScript: Mengonsumsi beberapa endpoint API secara efisien tanpa mengorbankan pengalaman pengguna.
- Version Control: Menerapkan alur kerja Git yang bersih, termasuk penggunaan feature branch dan penanganan merge conflict.
Konfigurasi Webpack
Webpack adalah jantung dari proses build proyek ini. Konfigurasi yang tepat memastikan proses pengembangan berjalan lancar dan hasil produksi menjadi optimal. Berikut adalah poin-poin penting dari webpack.config.js yang saya gunakan:
- Entry dan Output: Titik masuk aplikasi adalah
src/script.js, dan semua hasil bundle akan ditempatkan di direktoridist. Opsioutput.clean: truesaya aktifkan untuk membersihkan direktoridistsetiap kali proses build dijalankan. - Loaders: Saya menggunakan
css-loaderuntuk membaca file CSS danstyle-loaderuntuk menyuntikkannya ke dalam DOM. Urutan['style-loader', 'css-loader']penting, karena Webpack memproses loader dari kanan ke kiri. - Plugins:
HtmlWebpackPlugin: Plugin ini secara otomatis membuat fileindex.htmldi dalamdistdan menyisipkan bundle JavaScript ke dalamnya. Ini menghilangkan kebutuhan untuk mengedit HTML secara manual setiap kali nama file bundle berubah.Dotenv-webpack: Untuk mengelola API key tanpa menuliskannya langsung di dalam kode (hardcode), saya menggunakan plugin ini. Ia memuat variabel dari file.envdan membuatnya tersedia di dalam aplikasi melaluiprocess.env.
- DevServer:
webpack-dev-serversangat membantu selama pengembangan dengan fitur hot-reloading, yang secara otomatis memuat ulang halaman di browser setiap kali ada perubahan pada kode.
Berikut adalah cuplikan konfigurasi yang merangkum poin-poin di atas:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const Dotenv = require("dotenv-webpack");
module.exports = {
mode: "development",
entry: "./src/script.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
clean: true,
},
module: {
rules: [{ test: /\.css$/, use: ["style-loader", "css-loader"] }],
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html", // Menggunakan src/index.html sebagai template
}),
new Dotenv(), // Memuat variabel dari file .env
],
devtool: "source-map",
devServer: {
static: "./dist",
hot: true,
open: true,
},
};
Tips praktis:
- Pisahkan konfigurasi untuk development dan production bila perlu.
- Gunakan plugins seperti HtmlWebpackPlugin untuk menyuntikkan bundle ke HTML secara otomatis.
- Aktifkan caching dan minimization di production untuk performa.
Mengoptimalkan Pemanggilan API dengan Promise.all
Di aplikasi cuaca, saya perlu mengambil beberapa resource (mis. data cuaca saat ini, forecast, dan ikon) yang berasal dari beberapa endpoint. Mengambilnya satu-per-satu menambah latensi. Solusi yang saya pakai adalah Promise.all untuk menjalankan beberapa fetch secara paralel.
Contoh pola penggunaan:
const urls = [currentWeatherUrl, forecastUrl, iconsUrl];
Promise.all(urls.map((url) => fetch(url).then((res) => res.json())))
.then(([current, forecast, icons]) => {
// gunakan data secara bersamaan
})
.catch((err) => {
// tangani error: jika salah satu gagal, Promise.all menolak
});
Catatan penting:
- Tangani kegagalan dengan try/catch atau fallback agar satu gagal tidak merusak seluruh UI.
- Untuk permintaan yang bisa gagal tanpa menghentikan keseluruhan, gunakan Promise.allSettled.
- Batasi paralelisme jika API rate-limited (mis. p-limit atau batch requests).
Visualisasi Alur Aplikasi
Untuk memberikan gambaran yang lebih jelas tentang bagaimana semua bagian bekerja sama—mulai dari interaksi pengguna hingga respons dari API—berikut adalah dua diagram yang menggambarkan alur kerja aplikasi.
Diagram Alur (Mermaid)
Diagram sekuens ini menunjukkan interaksi antara pengguna, browser (kode JavaScript Anda), dan OpenWeatherMap API. Ini secara efektif mengilustrasikan bagaimana Promise.all mengeksekusi dua permintaan API secara paralel.
sequenceDiagram
participant User as Pengguna
participant Browser as "Browser (script.js)"
participant API as "OpenWeatherMap API"
User->>Browser: Memasukkan nama kota & klik "Cari"
activate Browser
Browser->>Browser: Menampilkan spinner loading
Browser->>Browser: Memanggil searchCity(city)
par Permintaan Paralel
Browser->>API: GET /weather?q={city}
and
Browser->>API: GET /forecast?q={city}
end
API-->>Browser: Respons: Data Cuaca Saat Ini (JSON)
API-->>Browser: Respons: Data Prakiraan Cuaca (JSON)
Browser->>Browser: Merender data cuaca saat ini ke UI
Browser->>Browser: Merender kartu prakiraan cuaca ke UI
Browser->>Browser: Menyembunyikan spinner loading
deactivate Browser
Diagram Teks (ASCII)
Diagram berbasis teks ini memberikan pandangan langkah demi langkah yang lebih sederhana tentang proses yang sama.
[Pengguna] -> Masukkan "Jakarta", Klik "Cari"
|
v
[Browser: script.js]
|
+-- 1. Tampilkan spinner "Loading..."
|
+-- 2. Panggil searchCity("Jakarta")
| |
| +--> Promise.all() memulai dua permintaan secara paralel:
| |
| +-- A. fetch(currentWeatherUrl) ---> [OpenWeatherMap API]
| |
| +-- B. fetch(forecastUrl) ---> [OpenWeatherMap API]
|
+-- 3. Tunggu hingga A dan B selesai
| |
| +--> [OpenWeatherMap API] ---> Mengembalikan data JSON untuk A
| |
| +--> [OpenWeatherMap API] ---> Mengembalikan data JSON untuk B
|
+-- 4. Terima [currentData, forecastData]
|
+-- 5. Render data ke UI
| - Perbarui bagian cuaca saat ini
| - Buat dan tambahkan kartu prakiraan cuaca
|
+-- 6. Sembunyikan spinner "Loading..."
Alur Kerja Git dan Penanganan Konflik
Selama pengembangan, saya menghadapi konflik merge ketika beberapa orang (atau branch) mengubah file yang sama. Langkah-langkah saya untuk menyelesaikannya:
- Tarik perubahan terbaru:
git fetchdangit pullpada branch tujuan. - Lakukan merge atau rebase dari branch sumber:
git merge feature-branchataugit rebase feature-branch. - Ketika terjadi konflik, Git menandai bagian yang bermasalah dalam file dengan
<<<<<<<,=======,>>>>>>>. - Buka file yang konflik, tinjau kedua bagian, dan pilih/menggabungkan perubahan yang benar secara manual.
- Jalankan tes atau build untuk memastikan tidak ada yang rusak setelah resolusi.
- Setelah bersih:
git add <file>,git commit(atau lanjutkan rebase dengangit rebase --continue).
Praktik yang membantu mencegah konflik besar:
- Lakukan commit kecil dan sering.
- Tarik perubahan terbaru sebelum memulai pekerjaan baru.
- Gunakan feature branch untuk setiap fitur atau perbaikan.
- Komunikasi tim: koordinasikan perubahan pada file yang sensitif.
Kesimpulan
Membangun Odin Weather App memberi pengalaman praktis dalam konfigurasi bundler (Webpack), efisiensi pemanggilan API menggunakan Promise.all, dan keterampilan menyelesaikan konflik Git. Praktik-praktik ini penting untuk pengembangan web modern dan meningkatkan kualitas kode serta alur kerja tim.
Semoga catatan singkat ini berguna bagi siapa saja yang mengerjakan proyek serupa di The Odin Project.