1. Pengantar MERN Stack dan E-Commerce
MERN Stack adalah kombinasi teknologi modern yang terdiri dari MongoDB, Express.js, React.js, dan Node.js. Dengan MERN, Anda dapat membangun aplikasi web full-stack secara efisien dan scalable. Pada panduan ini, kita akan membangun aplikasi e-commerce profesional yang lengkap, mulai dari backend hingga frontend, termasuk fitur penting seperti autentikasi, manajemen produk, keranjang belanja, dan pembayaran.
2. Persiapan Lingkungan dan Tools
Sebelum mulai coding, pastikan Anda sudah menyiapkan beberapa tools berikut:
-
Node.js (versi terbaru) dan npm/yarn
-
MongoDB Atlas (cloud) atau MongoDB lokal
-
Code editor seperti VSCode
-
Postman untuk testing API
-
Git untuk version control
Install Node.js dari
nodejs.org
dan buat akun MongoDB Atlas di
mongodb.com/cloud/atlas
.
3. Struktur Proyek MERN E-Commerce
Struktur proyek yang rapi memudahkan pengembangan dan pemeliharaan. Berikut contoh struktur folder yang akan kita gunakan:
/mern-ecommerce
├── backend
│ ├── config
│ ├── controllers
│ ├── middleware
│ ├── models
│ ├── routes
│ └── server.js
└── frontend
├── public
├── src
│ ├── components
│ ├── pages
│ ├── context
│ ├── hooks
│ └── App.js
└── package.json
Backend berisi API dan logika server, sedangkan frontend berisi React app yang berinteraksi dengan API.
4. Membangun Backend dengan Node.js & Express
Kita mulai dengan membuat server Express yang akan menangani API untuk produk, user, dan transaksi.
Langkah 1: Inisialisasi proyek backend
mkdir backend
cd backend
npm init -y
npm install express mongoose dotenv cors bcryptjs jsonwebtoken
Langkah 2: Buat file
server.js
dasar
const express = require('express');
const cors = require('cors');
const dotenv = require('dotenv');
const mongoose = require('mongoose');
dotenv.config();
const app = express();
app.use(cors());
app.use(express.json());
const PORT = process.env.PORT || 5000;
mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log('MongoDB connected'))
.catch((err) => console.error(err));
app.get('/', (req, res) => {
res.send('API MERN E-Commerce berjalan');
});
app.listen(PORT, () => {
console.log(`Server berjalan di port ${PORT}`);
});
Pastikan buat file
.env
di folder backend dengan isi:
MONGO_URI=your_mongodb_connection_string
JWT_SECRET=your_jwt_secret_key
5. Mengelola Data dengan MongoDB
Kita akan membuat model data untuk produk, user, dan order menggunakan Mongoose.
Contoh model Produk (
models/Product.js
):
const mongoose = require('mongoose');
const productSchema = new mongoose.Schema({
name: { type: String, required: true },
description: { type: String, required: true },
price: { type: Number, required: true },
imageUrl: { type: String, required: true },
countInStock: { type: Number, required: true, default: 0 },
}, { timestamps: true });
module.exports = mongoose.model('Product', productSchema);
Contoh model User (
models/User.js
):
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
isAdmin: { type: Boolean, default: false },
}, { timestamps: true });
module.exports = mongoose.model('User', userSchema);
Contoh model Order (
models/Order.js
):
const mongoose = require('mongoose');
const orderSchema = new mongoose.Schema({
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
orderItems: [
{
product: { type: mongoose.Schema.Types.ObjectId, ref: 'Product', required: true },
qty: { type: Number, required: true },
}
],
shippingAddress: {
address: String,
city: String,
postalCode: String,
country: String,
},
paymentMethod: String,
totalPrice: Number,
isPaid: { type: Boolean, default: false },
paidAt: Date,
}, { timestamps: true });
module.exports = mongoose.model('Order', orderSchema);
6. Autentikasi dan Otorisasi Pengguna
Kita akan menggunakan JWT untuk autentikasi dan bcrypt untuk hashing password.
Contoh route register dan login (
routes/userRoutes.js
):
const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const User = require('../models/User');
const router = express.Router();
router.post('/register', async (req, res) => {
const { name, email, password } = req.body;
try {
const userExist = await User.findOne({ email });
if (userExist) return res.status(400).json({ message: 'Email sudah terdaftar' });
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
const user = new User({ name, email, password: hashedPassword });
await user.save();
res.status(201).json({ message: 'User berhasil didaftarkan' });
} catch (error) {
res.status(500).json({ message: 'Server error' });
}
});
router.post('/login', async (req, res) => {
const { email, password } = req.body;
try {
const user = await User.findOne({ email });
if (!user) return res.status(400).json({ message: 'Email atau password salah' });
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) return res.status(400).json({ message: 'Email atau password salah' });
const token = jwt.sign({ id: user._id, isAdmin: user.isAdmin }, process.env.JWT_SECRET, {
expiresIn: '1d',
});
res.json({ token, user: { id: user._id, name: user.name, email: user.email, isAdmin: user.isAdmin } });
} catch (error) {
res.status(500).json({ message: 'Server error' });
}
});
module.exports = router;
Jangan lupa untuk menambahkan middleware autentikasi untuk melindungi route tertentu.
7. Membangun Frontend dengan React
Kita akan membuat aplikasi React yang berkomunikasi dengan backend API untuk menampilkan produk, mengelola keranjang, dan proses checkout.
Langkah 1: Inisialisasi React app
npx create-react-app frontend
cd frontend
npm install axios react-router-dom
Langkah 2: Contoh komponen daftar produk (
src/components/ProductList.js
):
import React, { useEffect, useState } from 'react';
import axios from 'axios';
export default function ProductList() {
const [products, setProducts] = useState([]);
useEffect(() => {
axios.get('http://localhost:5000/api/products')
.then(res => setProducts(res.data))
.catch(err => console.error(err));
}, []);
return (
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
{products.map(product => (
<div key={product._id} className="bg-white rounded-lg shadow p-4 flex flex-col">
<img src={product.imageUrl} alt={`Gambar produk ${product.name}`} className="h-48 w-full object-cover rounded mb-4" />
<h3 className="text-lg font-semibold mb-2">{product.name}</h3>
<p className="text-indigo-700 font-bold mb-2">Rp {product.price.toLocaleString()}</p>
<button className="mt-auto bg-indigo-600 text-white py-2 rounded hover:bg-indigo-700">Tambah ke Keranjang</button>
</div>
))}
</div>
);
}
8. State Management dan Integrasi API
Untuk mengelola state global seperti keranjang dan user login, kita bisa menggunakan React Context API atau library seperti Redux. Berikut contoh sederhana menggunakan Context API untuk keranjang:
import React, { createContext, useReducer, useContext } from 'react';
const CartContext = createContext();
const initialState = { cartItems: [] };
function reducer(state, action) {
switch(action.type) {
case 'ADD_ITEM':
const exist = state.cartItems.find(item => item._id === action.payload._id);
if (exist) {
return {
...state,
cartItems: state.cartItems.map(item =>
item._id === action.payload._id ? { ...item, qty: item.qty + 1 } : item
),
};
} else {
return { ...state, cartItems: [...state.cartItems, { ...action.payload, qty: 1 }] };
}
case 'REMOVE_ITEM':
return {
...state,
cartItems: state.cartItems.filter(item => item._id !== action.payload._id),
};
default:
return state;
}
}
export function CartProvider({ children }) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<CartContext.Provider value={{ state, dispatch }}>
{children}
</CartContext.Provider>
);
}
export function useCart() {
return useContext(CartContext);
}
Gunakan
useCart()
di komponen untuk menambah atau menghapus produk dari keranjang.
9. Fitur E-Commerce Penting
Fitur utama yang harus ada di aplikasi e-commerce:
-
Daftar dan login pengguna dengan autentikasi JWT
-
Manajemen produk: tampilkan, tambah, edit, hapus (admin)
-
Keranjang belanja dengan update jumlah dan hapus item
-
Checkout dengan pengisian alamat dan metode pembayaran
-
Riwayat pesanan pengguna
-
Responsif dan user-friendly UI
Contoh endpoint API produk:
const express = require('express');
const Product = require('../models/Product');
const router = express.Router();
// Get all products
router.get('/', async (req, res) => {
const products = await Product.find({});
res.json(products);
});
// Get product by ID
router.get('/:id', async (req, res) => {
const product = await Product.findById(req.params.id);
if (product) res.json(product);
else res.status(404).json({ message: 'Produk tidak ditemukan' });
});
module.exports = router;
10. Deploy Aplikasi MERN E-Commerce
Setelah aplikasi selesai, saatnya deploy ke hosting agar bisa diakses publik. Berikut beberapa opsi:
-
Backend:
Deploy ke Heroku, Railway, atau Vercel (serverless functions)
-
Frontend:
Deploy ke Netlify, Vercel, atau GitHub Pages (jika statis)
-
Database:
Gunakan MongoDB Atlas cloud untuk akses global
Contoh deploy backend ke Heroku:
heroku login
heroku create nama-aplikasi-anda
git push heroku main
heroku config:set MONGO_URI=your_mongodb_connection_string
heroku config:set JWT_SECRET=your_jwt_secret_key
heroku open
11. Sumber Belajar dan Source Code
Berikut beberapa sumber belajar dan repository yang bisa Anda gunakan untuk memperdalam dan mendapatkan source code lengkap:
Jangan lupa untuk selalu praktik dan eksplorasi lebih lanjut agar mahir membangun aplikasi MERN stack profesional.