Menu
CoddyTech

الملفات الثابتة

جزء من قسم أساسيات Express في رحلة Node.js على Coddy. الدرس 11 من 23.

لا يتغير ملف الأنماط أو الصورة أبدًا، وإنشاء مسار لكل ملف سيكون عملًا بلا فائدة.

app.use(express.static('assets'));

تُقدّم express.static('assets') ملفات مجلد assets بأسمائها، لذا يستجيب assets/logo.png للطلب GET /logo.png. لا يكون اسم المجلد جزءًا من عنوان URL. يحدد Express نوع المحتوى من الامتداد: text/css لملفات .css، وimage/png لملفات .png. ينتقل المسار الذي لا يقابله ملف إلى مساراتك.

تضيف app.use دالةً تعمل مع كل طلب؛ ويتناول الفصل التالي هذه الدوال. أصبح في مشروعك الآن مجلد public يحتوي على ملف أنماط.

challenge icon

التحدي

سهل

يحصل Recipe Box على ورقة أنماط. الملف جاهز في مجلد public؛ وما على خادمك سوى تقديمه.

  1. في server.js، أضِف مباشرةً بعد const app = express(); تقديم كل ملف في مجلد public باستخدام express.static. عندها يُقدَّم public/style.css على المسار /style.css.
  2. اجعل الصفحة الرئيسية تحمّله: ضع <link rel="stylesheet" href="/style.css"> في بداية HTML الذي يرسله المسار /.

جرّب ذلك: اضغط «تشغيل» وأرسل /. تستخدم الصفحة الآن ورقة الأنماط. أرسل /style.css: الحالة 200، ونص CSS، وقيمة Content-Type هي text/css في تبويب Headers. أرسل /missing.css: لا يوجد ملف بهذا الاسم، لذا ينتقل الطلب إلى مساراتك. لا يطابقه أيٌّ منها، ويستجيب Express بالرمز 404.

جرّب بنفسك

import {escapeHtml} from './html.js';
import express from 'express';
import { recipes } from './data.js';

const app = express();



app.get('/', (req, res) => {
    const items = recipes.map((r) => `<li><a href="/recipes/${r.id}">${escapeHtml(r.title)}</a></li>`);
    res.send(`<h1>Recipe Box</h1><ul>${items.join('')}</ul>`);
});

// ترسل type('text') نصًا عاديًا، لذا يظهر كل عنوان في سطر مستقل.
app.get('/recipes', (req, res) => {
    const { tag } = req.query;
    const list = tag ? recipes.filter((recipe) => recipe.tags.includes(tag)) : recipes;
    res.type('text').send(list.map((recipe) => recipe.title).join('\n'));
});

app.get('/recipes/:id', (req, res) => {
    const recipe = recipes.find((r) => r.id === Number(req.params.id));
    if (!recipe) {
        res.status(404).send('No such recipe');
        return;
    }
    res.send(recipe.title);
});

app.get('/api/recipes', (req, res) => {
    res.json(recipes);
});

app.get('/api/recipes/:id', (req, res) => {
    const recipe = recipes.find((r) => r.id === Number(req.params.id));
    if (!recipe) {
        res.status(404).json({ error: 'No such recipe' });
        return;
    }
    res.json(recipe);
});

app.get('/about', (req, res) => {
    res.send('Recipe Box collects family recipes.');
});

app.listen(3000, () => {
    console.log('Recipe Box is running on port 3000');
});

جميع دروس أساسيات Express

تدرّب بنفسك: Playground لـ Express