لإنشاء موقع متجر إلكتروني مميز باستخدام نود Node.js، سنقوم بخطوات تفصيلية تغطي جميع جوانب بناء التطبيق من الألف إلى الياء. سنستخدم بعض الأدوات والمكتبات الشهيرة في Node.js مثل Express وMongoDB وMongoose لإدارة قاعدة البيانات، بالإضافة إلى EJS (Embedded JavaScript) لتصميم واجهة المستخدم.
الخطوات التفصيلية لإنشاء متجر إلكتروني باستخدام Node.js
الخطوة 1: إعداد بيئة التطوير
تثبيت Node.js وnpm:
- قم بتحميل وتثبيت Node.js من الموقع الرسمي.
- بعد التثبيت، تأكد من أن Node.js وnpm قد تم تثبيتهما بنجاح عن طريق تشغيل الأوامر التالية في سطر الأوامر (Terminal):
node -v
npm -v
إنشاء مجلد المشروع:
- أنشئ مجلدًا جديدًا لمشروعك وافتحه في Terminal أو Command Prompt.
mkdir ecommerce-site
cd ecommerce-site
تهيئة مشروع Node.js:
- استخدم npm لإنشاء ملف package.json الذي يحتوي على إعدادات المشروع:
npm init -y
الخطوة 2: تثبيت الحزم الأساسية
- قم بتثبيت الحزم اللازمة لتطوير المتجر الإلكتروني:
npm install express mongoose ejs dotenv body-parser express-session bcryptjs connect-flash passport passport-local multer
الخطوة 3: إعداد هيكل المجلدات
- أنشئ هيكل المجلدات والملفات الأساسي للمشروع:
ecommerce-site/
│
├── models/
│ └── user.js
│ └── product.js
│
├── routes/
│ └── index.js
│ └── users.js
│ └── products.js
│
├── views/
│ └── pages/
│ └── partials/
│ └── layout.ejs
│
├── public/
│ └── css/
│ └── images/
│ └── js/
│
├── .env
├── app.js
└── package.json
الخطوة 4: إعداد قاعدة البيانات باستخدام MongoDB
إنشاء قاعدة بيانات باستخدام MongoDB:
- يمكنك استخدام MongoDB Atlas لإنشاء قاعدة بيانات سحابية أو تثبيت MongoDB محليًا.
الاتصال بقاعدة البيانات في Node.js:
- في الملف app.js، أضف كود الاتصال بقاعدة البيانات:
require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const app = express();
const PORT = process.env.PORT || 3000;
// الاتصال بقاعدة البيانات
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Could not connect to MongoDB...', err));
// إعداد المحرك
app.set('view engine', 'ejs');
// إعداد المسارات
app.use(express.static('public'));
app.use(express.urlencoded({ extended: true }));
// استماع للخادم
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
- إنشاء ملف
.env
لتخزين متغيرات البيئة:
- في جذر المشروع، أنشئ ملف .env وأضف رابط الاتصال بقاعدة البيانات:
MONGO_URI=your_mongo_uri
الخطوة 5: إنشاء نماذج البيانات (Models)
إنشاء نموذج المستخدم (user.js):const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
}
});
const User = mongoose.model('User', userSchema);
module.exports = User;
إنشاء نموذج المنتج (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,
},
image: {
type: String,
required: true,
}
});
const Product = mongoose.model('Product', productSchema);
module.exports = Product;
الخطوة 6: إعداد نظام المصادقة باستخدام Passport.js
إعداد Passport في app.js:const session = require('express-session');
const flash = require('connect-flash');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('./models/user');
// إعداد الجلسة
app.use(session({
secret: 'secretKey',
resave: false,
saveUninitialized: false
}));
// إعداد Passport
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy({ usernameField: 'email' }, async (email, password, done) => {
try {
const user = await User.findOne({ email });
if (!user) return done(null, false, { message: 'Email is not registered' });
// تحقق من كلمة المرور (تحتاج إلى إعداد مكتبة bcryptjs)
if (password !== user.password) return done(null, false, { message: 'Incorrect password' });
return done(null, user);
} catch (err) {
return done(err);
}
}));
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
// إعداد الرسائل الفورية
app.use(flash());
app.use((req, res, next) => {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
إنشاء مسارات المصادقة (users.js):const express = require('express');
const router = express.Router();
const passport = require('passport');
const User = require('../models/user');
// صفحة التسجيل
router.get('/register', (req, res) => res.render('pages/register'));
// معالجة عملية التسجيل
router.post('/register', async (req, res) => {
const { username, email, password } = req.body;
try {
const newUser = new User({ username, email, password });
await newUser.save();
req.flash('success_msg', 'You are now registered!');
res.redirect('/users/login');
} catch (err) {
req.flash('error_msg', 'Error registering user');
res.redirect('/users/register');
}
});
// تسجيل الدخول
router.get('/login', (req, res) => res.render('pages/login'));
router.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/users/login',
failureFlash: true
}));
module.exports = router;
الخطوة 7: إعداد الواجهات باستخدام EJS
إنشاء تخطيط الموقع (layout.ejs):<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>E-commerce Site</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<header>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/users/login">Login</a></li>
<li><a href="/users/register">Register</a></li>
</ul>
</nav>
</header>
<main>
<%- body %>
</main>
<footer>
<p>© 2024 E-commerce Site</p>
</footer>
</body>
</html>
- إنشاء الصفحات مثل
login.ejs
وregister.ejs
وindex.ejs
:
- قم بإنشاء كل صفحة باستخدام تنسيق EJS، وضع المحتوى الرئيسي ضمن قسم <%- body %>.
الخطوة 8: تحميل وإدارة المنتجات
إنشاء مسارات المنتجات (products.js):const express = require('express');
const router = express.Router();
const Product = require('../models/product');
// عرض جميع المنتجات
router.get('/', async (req, res) => {
const products = await Product.find();
res.render('pages/products', { products });
});
// عرض صفحة إضافة المنتج
router.get('/add', (req, res) => res.render('pages/add-product'));
// معالجة إضافة المنتج
router.post('/add', async (req, res) => {
const { name, description, price, image } = req.body;
const newProduct = new Product({ name, description, price, image });
await newProduct.save();
req.flash('success_msg', 'Product added successfully!');
res.redirect('/products');
});
module.exports = router;
الخطوة 9: تحميل المشروع وتجربته
افتح Terminal في جذر المشروع وشغّل الخادم:node app.js
قم بزيارة http://localhost:3000 في متصفحك لعرض الموقع وتجربة تسجيل الدخول وتسجيل المستخدمين وتحميل المنتجات.الخطوة 10: تحسين الأمان وتحسين تجربة المستخدم
- استخدام HTTPS، وإضافة التحقق من المدخلات، وتحسين الأداء باستخدام تقنيات مثل CDN وضغط الصور.
- يمكنك أيضاً تحسين المشروع بإضافة ميزات مثل الدفع الإلكتروني باستخدام Stripe أو PayPal.
ولتحسين المتجر الإلكتروني باستخدام بأكود Node.js نقوم بالتالي:
التحقق من المدخلات باستخدام مكتبة express-validator
تثبيت مكتبة
express-validator
:- استخدم الأمر التالي لتثبيت المكتبة:
npm install express-validator
إعداد التحقق من المدخلات في مسارات المنتجات والمستخدمين:
افتح الملف routes/users.js وقم بتحديثه للتحقق من مدخلات التسجيل:
const express = require('express');
const router = express.Router();
const { body, validationResult } = require('express-validator');
const User = require('../models/user');
// صفحة التسجيل
router.get('/register', (req, res) => res.render('pages/register'));
// معالجة عملية التسجيل مع التحقق من المدخلات
router.post(
'/register',
[
body('username').notEmpty().withMessage('Username is required'),
body('email').isEmail().withMessage('Invalid email address'),
body('password').isLength({ min: 6 }).withMessage('Password must be at least 6 characters'),
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.render('pages/register', {
errors: errors.array(),
});
}
const { username, email, password } = req.body;
try {
const newUser = new User({ username, email, password });
await newUser.save();
req.flash('success_msg', 'You are now registered!');
res.redirect('/users/login');
} catch (err) {
req.flash('error_msg', 'Error registering user');
res.redirect('/users/register');
}
}
);
- إعداد التحقق من مدخلات المنتجات في
routes/products.js
:
const express = require('express');
const router = express.Router();
const { body, validationResult } = require('express-validator');
const Product = require('../models/product');
// عرض صفحة إضافة المنتج
router.get('/add', (req, res) => res.render('pages/add-product'));
// معالجة إضافة المنتج مع التحقق من المدخلات
router.post(
'/add',
[
body('name').notEmpty().withMessage('Product name is required'),
body('description').notEmpty().withMessage('Product description is required'),
body('price').isNumeric().withMessage('Price must be a number'),
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.render('pages/add-product', {
errors: errors.array(),
});
}
const { name, description, price, image } = req.body;
const newProduct = new Product({ name, description, price, image });
await newProduct.save();
req.flash('success_msg', 'Product added successfully!');
res.redirect('/products');
}
);
module.exports = router;
ضغط الصور باستخدام مكتبة Multer وSharp
تثبيت مكتبات
multer
وsharp
:npm install multer sharp
إعداد تحميل الصور وضغطها في
routes/products.js
:
const multer = require('multer');
const sharp = require('sharp');
// إعداد Multer للتعامل مع تحميل الملفات
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });
// معالجة إضافة المنتج مع تحميل وضغط الصورة
router.post(
'/add',
upload.single('image'),
[
body('name').notEmpty().withMessage('Product name is required'),
body('description').notEmpty().withMessage('Product description is required'),
body('price').isNumeric().withMessage('Price must be a number'),
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.render('pages/add-product', {
errors: errors.array(),
});
}
// ضغط الصورة باستخدام Sharp
const { name, description, price } = req.body;
let imagePath = '';
if (req.file) {
const filename = `product-${Date.now()}.jpeg`;
await sharp(req.file.buffer)
.resize(300, 300)
.toFormat('jpeg')
.jpeg({ quality: 90 })
.toFile(`public/images/${filename}`);
imagePath = `/images/${filename}`;
}
const newProduct = new Product({ name, description, price, image: imagePath });
await newProduct.save();
req.flash('success_msg', 'Product added successfully!');
res.redirect('/products');
}
);
الدفع الإلكتروني باستخدام PayPal وStripe
تثبيت مكتبات PayPal وStripe:
npm install paypal-rest-sdk stripe
إعداد الدفع باستخدام PayPal:
- تكوين PayPal في
app.js
:
const paypal = require('paypal-rest-sdk');
paypal.configure({
mode: 'sandbox', // أو 'live' للإنتاج
client_id: process.env.PAYPAL_CLIENT_ID,
client_secret: process.env.PAYPAL_CLIENT_SECRET,
});
- إنشاء مسار الدفع بـ PayPal في
routes/payments.js
:
const express = require('express');
const router = express.Router();
const paypal = require('paypal-rest-sdk');
// إنشاء عملية دفع PayPal
router.post('/pay', (req, res) => {
const create_payment_json = {
intent: 'sale',
payer: {
payment_method: 'paypal',
},
redirect_urls: {
return_url: 'http://localhost:3000/success',
cancel_url: 'http://localhost:3000/cancel',
},
transactions: [{
item_list: {
items: [{
name: 'Product Name',
sku: '001',
price: '25.00',
currency: 'USD',
quantity: 1
}]
},
amount: {
currency: 'USD',
total: '25.00'
},
description: 'This is the payment description.'
}]
};
paypal.payment.create(create_payment_json, function (error, payment) {
if (error) {
throw error;
} else {
for (let i = 0; i < payment.links.length; i++) {
if (payment.links[i].rel === 'approval_url') {
res.redirect(payment.links[i].href);
}
}
}
});
});
// نجاح الدفع
router.get('/success', (req, res) => {
const payerId = req.query.PayerID;
const paymentId = req.query.paymentId;
const execute_payment_json = {
payer_id: payerId,
transactions: [{
amount: {
currency: 'USD',
total: '25.00'
}
}]
};
paypal.payment.execute(paymentId, execute_payment_json, function (error, payment) {
if (error) {
console.log(error.response);
throw error;
} else {
console.log('Get Payment Response');
console.log(JSON.stringify(payment));
res.send('Success');
}
});
});
// إلغاء الدفع
router.get('/cancel', (req, res) => res.send('Cancelled'));
module.exports = router;
إعداد الدفع باستخدام Stripe:
- تكوين Stripe في
app.js
:
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
- إنشاء مسار الدفع بـ Stripe في
routes/payments.js
:
router.post('/stripe', async (req, res) => {
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [{
price_data: {
currency: 'usd',
product_data: {
name: 'Product Name',
},
unit_amount: 2500,
},
quantity: 1,
}],
mode: 'payment',
success_url: 'http://localhost:3000/success',
cancel_url: 'http://localhost:3000/cancel',
});
res.redirect(303, session.url);
});
الخطوة 11: تحسين الأمان وتجربة المستخدم
- تأكد من استخدام HTTPS، وتشفير البيانات الحساسة، وتحديث جميع المكتبات بانتظام.
- قم بإعداد بيئة إنتاج (Production) بشكل صحيح على منصة مثل Heroku أو AWS لضمان أمان الموقع الإلكتروني وأداءه.
وهكذا نكون قد غطينا كيفية إعداد التحقق من المدخلات، وضغط الصور، والدفع الإلكتروني باستخدام PayPal وStripe لمتجر إلكتروني تم إنشاؤه باستخدام Node.js. وباتباع كل الخطوات السابقة، يمكنك بناء متجر إلكتروني متكامل باستخدام Node.js من البداية للنهاية.