محمد قتيبة شيخانيأبني. أستكشف. أشارك

18من 22

تطوير الويب

أدوات البناء: npm وVite من ملفّاتك إلى موقعٍ جاهز للنشر

لقطة شاشة لطرفيّة داكنة بعد بناء صفحة المشروع بأداة Vite: سطر vite v8.3.2 يبني للإنتاج، ثمّ ثلاثة ملفّات في dist بأحجامها وأحجامها بعد الضغط، ملفّ HTML وملفّ CSS وملفّ JavaScript في assets بأسماءٍ فيها بصمة، ثمّ built in 24ms، ثمّ grep يُظهر أنّ مسار السكربت يبدأ بـ/my-first-site/assets/. وتحتها عنوان المقالة «أدوات البناء» وسطرٌ يقول: من ملفّاتك إلى موقعٍ جاهز للنشر، مع npm وVite.

صفحة المشروع ما زالت ثلاثة ملفّات تكتبها بيدك وترفعها كما هي، وهذا يكفي لصفحةٍ واحدة. لكنّ المشاريع تكبر: عشرة ملفّات JavaScript بدل واحد، ومكتبةٌ من npm تريد أن تستعملها، وصورٌ تريدها أصغر، وCSS تريده مضغوطًا. وفي مرحلةٍ ما يصير نقل الملفّات بيدك إلى الخادم هو المشكلة، وهنا تدخل أدوات البناء: برنامجٌ يأخذ ملفّاتك كما تكتبها، ويخرج منها ملفّاتٍ أصغر وأسرع جاهزة للنشر.

في هذا المقال تحوّل صفحة المشروع نفسها إلى مشروع Vite، الأداة الأشهر اليوم، على نسخةٍ محلّيّة على هذا الجهاز يوم 1 تشرين الأوّل 2026. فتثبّتها بـnpm، وتبني الصفحة، وترى التحذير الذي يظهر لكلّ من يجرّب أوّل مرّة، ثمّ الخطأ نفسه الذي كسر التنسيق في مقال النشر وهو يعود بشكلٍ جديد. وفي الطريق تفهم ما في ملفّ package.json سطرًا سطرًا، ولماذا تقول شروحٌ كثيرة شيئًا عن Vite لم يعد صحيحًا منذ آذار 2026.

ما هي خطوة البناء؟

خطوة البناء أمرٌ تشغّله قبل النشر، يقرأ ملفّات المصدر التي تكتبها ويكتب ملفّاتٍ جديدة في مجلّدٍ آخر هي التي ترفعها. فأنت تكتب بأوضح طريقةٍ لك، بأسماء متغيّراتٍ طويلة ومسافاتٍ وتعليقات، وفي ملفّاتٍ كثيرة صغيرة يسهل البحث فيها. أمّا الزائر فيحتاج إلى العكس: ملفّاتٍ قليلة، بلا مسافاتٍ ولا تعليقات، تصل بسرعة على اتّصالٍ بطيء.

وهذا ليس تفصيلًا نظريًّا. فكثيرٌ من قرّاء العربيّة يتصفّحون من هاتفٍ على شبكةٍ متقطّعة، في دمشق أو في ضواحي مدينةٍ خليجيّة أو في قطار أوروبيّ بين مدينتين. وكلّ ملفٍّ إضافيّ طلبٌ جديد ينتظره المتصفّح قبل أن تظهر الصفحة.

وأداة البناء تفعل ثلاثة أشياء في الغالب. فهي تجمع الملفّات الكثيرة في عددٍ قليل، وتسمّى لهذا المجمِّع. وهي تصغّر الشيفرة بحذف ما لا يحتاجه المتصفّح. وهي تضيف إلى أسماء الملفّات الناتجة بصمةً من محتواها، مثل index-D4K57yHg.css، فيستطيع المتصفّح أن يحفظ الملفّ طويلًا، ولا يأخذ نسخةً جديدة إلّا حين يتغيّر الاسم. وتصف MDN أدوات الواجهة الأماميّة بأنّها طبقاتٌ تساعدك على كتابة الشيفرة ثمّ تحويلها إلى ما يعمل في المتصفّح.[1]

شكل 1 ما تفعله خطوة البناء ثلاثة أعمدة من اليمين إلى اليسار. في اليمين ملفّات المصدر الثلاثة: index.html وstyle.css وscript.js. وفي الوسط الصندوق المميّز «خطوة البناء» وتحته vite build. وفي اليسار المجلّد dist وفيه index.html وملفّان في assets بأسماءٍ فيها بصمة، أحدهما للتنسيق والآخر للسكربت. ملفّات المصدر index.html style.css script.js خطوة البناء vite build المجلّد dist index.html assets/index-…css assets/index-…js ما تفعله خطوة البناء ثلاثة صناديق من الأعلى إلى الأسفل: ملفّات المصدر index.html وstyle.css وscript.js، ثمّ الصندوق المميّز «خطوة البناء» وتحته vite build، ثمّ المجلّد dist وفيه index.html وملفّان في assets بأسماءٍ فيها بصمة. ملفّات المصدر index.html style.css script.js خطوة البناء vite build المجلّد dist index.html assets/index-…css assets/index-…js
ما فعلته خطوة البناء بصفحة المشروع: ثلاثة ملفّات مصدر دخلت الأمر vite build، فخرج منها مجلّد dist فيه index.html وملفّان في assets بأسماءٍ فيها بصمة.

ما هو npm؟

قبل أداة البناء تحتاج إلى من يثبّتها، وnpm هو مدير الحزم الذي يأتي مع Node.js، وقد عرفته في مقال تجهيز بيئة العمل حين ثبّتّ النسخة طويلة الدعم. واليوم هي Node 24، وآخر إصدارٍ منها 24.21.0 صدر في 7 أيلول 2026، وVite نفسها تحتاج إلى Node بإصدار 20.19 أو 22.12 على الأقلّ.[2] وكلّ مشروعٍ يستعمل npm يبدأ بملفٍّ اسمه package.json، تصنعه في مجلّد المشروع بالأمر:

npm init -y

والخيار -y يقبل كلّ القيم الافتراضيّة من غير أن يسألك عنها. وهذا الملفّ بطاقة هويّة المشروع: اسمه وإصداره، والأوامر التي يشغّلها، والحزم التي يعتمد عليها. وستعود إليه كثيرًا، فاقرأه بعد كلّ أمرٍ يغيّره.

ثبّت Vite وابنِ الصفحة

في الجلسة التالية ثلاثة أوامر. الأوّل يثبّت Vite، والخيار -D يضعها في قسم devDependencies لا dependencies. والفرق كما يشرحه توثيق npm: الحزم التي يحتاجها المشروع وهو يعمل مكانها dependencies، أمّا أدوات التطوير والاختبار والبناء التي لا يحتاجها من يستعمل النتيجة فمكانها devDependencies.[3] وVite أداةٌ تعمل على جهازك وتنتهي، ولا يصل منها شيءٌ إلى الزائر.

والأمر الثاني يضيف إلى package.json ثلاثة سكربتات، فتصير npm run dev وnpm run build وnpm run preview أوامر يفهمها المشروع. والثالث يبني الصفحة لأوّل مرّة:

طرفيّة داكنة: npm install -D vite يضيف 15 حزمة بلا ثغرات، ثمّ npm pkg set يضيف السكربتات dev وbuild وpreview، ثمّ npm run build يشغّل vite v8.3.2، ويطبع تحذيرًا يقول إنّ الوسم script في index.html لا يُجمَّع من غير السمة type=module، ثمّ يكتب ملفّين فقط: dist/index.html وملفّ CSS في assets باسمٍ فيه بصمة، من غير ملفّ JavaScript.
تثبيت Vite وأوّل بناء لصفحة المشروع: npm يضيف 15 حزمة، ثمّ تُضاف السكربتات الثلاثة، ثمّ يطبع Vite تحذيرًا عن الوسم script ويخرج ملفّ HTML وملفّ CSS فقط. لقطة شاشة من جهازي.

وقبل أن تقرأ النتيجة، لاحظ ما فعله npm run build. فهو لم يجد أمرًا اسمه vite في النظام، لأنّ Vite لم تُثبَّت إلّا داخل المشروع. لكنّ npm، كما يشرح توثيقه، يضيف المجلّد node_modules/.bin إلى مسار البحث عن الأوامر حين يشغّل سكربتات package.json، وهناك وضعت Vite برنامجها.[4] ولهذا تعمل السكربتات نفسها على كلّ جهاز، من غير أن يثبّت أحدٌ Vite على نظامه كلّه.

انظر إلى السطر الأوسط. فقد قرأ Vite الصفحة، وجمع ملفّ التنسيق في ملفٍّ اسمه فيه بصمة، لكنّه قال إنّ الوسم <script src="script.js"> لا يُجمَّع من غير السمة type="module". ولهذا خرج البناء بلا أيّ ملفّ JavaScript: زرّ الوضع الداكن وبطاقة الطقس لن يعملا في النسخة المنشورة، والأمر انتهى بعلامة نجاحٍ خضراء، وهذا أخطر ما فيه.

ما هي الوحدات في JavaScript؟

السبب أنّ أدوات البناء الحديثة تفهم JavaScript بشكلها الحديث: الوحدات. والوحدة ملفٌّ يصرّح بما يأخذه من ملفّاتٍ أخرى بالكلمة import، وبما يعطيه لها بالكلمة export، فيعرف المجمِّع من ذلك أيّ الملفّات تحتاج إلى أيّها ويرتّبها. ويطلب ذلك أن يكون السكربت في الصفحة من نوع module. وVite تبدأ دائمًا من index.html، فتقرأ ما يذكره من سكربتات وأنماط وتبني منها.[5]

والإصلاح سطرٌ واحد في index.html. احذف الكلمة defer، لأنّ سكربتات الوحدات مؤجّلةٌ تلقائيًّا، كما شرح مقال JavaScript، وأضف السمة type:

<script type="module" src="script.js"></script>

ومعه تفصيلٌ آخر. فصفحة 404.html التي أضفتها في مقال النشر ليست جزءًا من الصفحة الرئيسة، ولا تريد أن يغيّرها Vite. ولهذا تضعها في مجلّدٍ اسمه public، لأنّ ما فيه يُنسخ إلى جذر مجلّد البناء كما هو، من غير أن يُعالج.[6] ثمّ ابنِ من جديد:

طرفيّة داكنة: grep يُظهر سطر السكربت الجديد في index.html وفيه type=module، ثمّ npm run build يكتب ثلاثة ملفّات: dist/index.html وملفّ CSS وملفّ JavaScript في assets، لكلٍّ منها حجمه وحجمه بعد الضغط، ثمّ grep في dist/index.html يُظهر أنّ مسار السكربت يبدأ بشرطة: /assets/index-DKQsVIM0.js.
البناء بعد إضافة type=module: ثلاثة ملفّات هذه المرّة، ومنها ملفّ JavaScript، لكنّ مسار السكربت في الصفحة المبنيّة يبدأ بشرطة: /assets/. لقطة شاشة من جهازي.

صار في مجلّد dist الآن ثلاثة ملفّات، ومنها السكربت بحجم 2.16 kB، ونحو نصفه بعد الضغط الذي تطبّقه الخوادم. لكنّ السطر الأخير يستحقّ وقفة: مسار السكربت في الصفحة المبنيّة يبدأ بشرطة، /assets/index-DKQsVIM0.js. وإن كنت قرأت مقال نشر موقعك الأوّل، فقد عرفت هذا الخطأ من قبل.

والوحدات ليست شرطًا يفرضه Vite فقط، فهي طريقةٌ أفضل لتنظيم الشيفرة. فصفحة المشروع فيها شيئان لا علاقة بينهما: زرّ الوضع الداكن، وبطاقة الطقس. فانقل كلّ ما يخصّ الطقس إلى ملفٍّ اسمه weather.js، وأضف الكلمة export قبل الدالّة التي تريد أن يراها غيره:

// weather.js
const cities = [ /* دمشق والرياض وبرلين كما في مقال الواجهات */ ];

export async function loadWeather() {
  /* الشيفرة نفسها بلا تغيير */
}

ثمّ يأخذها script.js في سطره الأوّل ويستدعيها في آخره:

import { loadWeather } from './weather.js';

// شيفرة زرّ الوضع الداكن كما هي…

loadWeather();

وحين بُني المشروع بعد هذا التقسيم، قال Vite إنّه عالج ستّ وحداتٍ بدل خمس، لكنّه أخرج ملفّ JavaScript واحدًا كما من قبل. فأنت تكتب في ملفّاتٍ صغيرة يسهل فهمها، والزائر يحمّل ملفًّا واحدًا، وهذا معنى المجمِّع بالضبط.

الخطأ القديم بشكلٍ جديد: الإعداد base

صفحتك على GitHub Pages تعيش في المجلّد ‎/my-first-site/، لا في جذر النطاق. والمسار الذي يبدأ بشرطة يُقرأ من جذر النطاق، فيطلب المتصفّح kutaibashi.github.io/assets/… حيث لا يوجد شيء، فتظهر الصفحة بلا سكربت ولا تنسيق، وفي مقال النشر كتبت المسارات بيدك فأصلحتها بيدك. أمّا هنا فالأداة هي التي تكتبها، فتخبرها أين ستعيش الصفحة بالإعداد base، وقيمته الافتراضيّة الشرطة وحدها، أي الجذر.[7] فتنشئ في مجلّد المشروع ملفًّا اسمه vite.config.js:

import { defineConfig } from 'vite';

export default defineConfig({
  base: '/my-first-site/',
});

وحين بُني المشروع بهذا الملفّ أوّل مرّة، طبع Vite تحذيرًا طويلًا: الملفّ مكتوبٌ بصيغة الوحدات، وpackage.json لا يقول إنّ المشروع يستعملها. فالأمر npm init يصنع الملفّ من غير الحقل type، وVite تقترح أن تضيفه، والأمر npm pkg set type=module يضيفه بلا تحرير يدويّ، وبعده خرج البناء نظيفًا:

طرفيّة داكنة: cat vite.config.js يُظهر ملفّ إعدادٍ فيه base يساوي /my-first-site/، ثمّ npm pkg set type=module، ثمّ npm run build يكتب الملفّات الثلاثة، ثمّ grep يُظهر أنّ مسار السكربت صار /my-first-site/assets/، والأمر ls dist يُظهر 404.html وassets وindex.html.
البناء مع الإعداد base: ملفّ الإعداد، ثمّ إضافة الحقل type، ثمّ بناءٌ بلا تحذير، ومسار السكربت صار /my-first-site/assets/، وصفحة 404.html منسوخةٌ في dist من مجلّد public. لقطة شاشة من جهازي.

واسم ملفّ السكربت تغيّر بين البناءين، من DKQsVIM0 إلى DzkQBZGk، لأنّ الملفّ الناتج تغيّر بتغيّر الإعدادات. وهذه البصمة هي ما يجعل الذاكرة المؤقّتة آمنة: يحفظ المتصفّح ملفّ assets سنةً إن شئت، وحين تنشر نسخةً جديدة يتغيّر الاسم، فيطلبه من جديد.

ماذا فعل البناء بملفّاتك؟

افتح ملفّ CSS المبنيّ في dist/assets لترى ما جرى. فهذه بداية style.css كما كتبته، بمسافاتٍ وأسطرٍ مستقلّة لكلّ خاصّيّة، ثمّ البداية نفسها بعد البناء، في سطرٍ واحد بلا مسافة زائدة:

:root {
  --ink: #1a1a1a;
  --paper: #f5f1e8;
  --accent: #aa4b3b;
}

:root{--ink:#1a1a1a;--paper:#f5f1e8;--accent:#aa4b3b}body{max-inline-size:46rem;…

والأرقام هنا صادقة، وتستحقّ أن تُقال كما هي. فملفّ التنسيق صغر من 2,230 بايت إلى 1,803، أمّا ملفّ JavaScript فكبر قليلًا، من 2,067 إلى 2,091، لأنّ Vite أضافت إليه شيفرةً صغيرة تعين المتصفّح على تحميل الوحدات مبكّرًا. ومجموع الصفحة كلّها نقص نحو 300 بايت فقط. فلصفحةٍ من ثلاثة ملفّات، لا تكسب من البناء شيئًا يُذكر في الحجم. ويظهر الفرق حين يكثر الكلام: عشرات الوحدات، ومكتبات من npm فيها آلاف الأسطر لا تستعمل منها إلّا قليلًا، فيحذف المجمِّع ما لا يُستدعى منها، ويجمع الباقي في ملفّاتٍ قليلة.

خادم التطوير: npm run dev

البناء لحظة النشر. أمّا وأنت تكتب، فلن تبني بعد كلّ تعديل. والأمر npm run dev يشغّل خادم تطويرٍ على جهازك يقدّم الصفحة من الذاكرة، ويحدّثها في المتصفّح كلّما حفظت ملفًّا، وغالبًا من غير أن تعيد تحميلها. ويمسح Vite الطرفية حين يبدأ، فلا يبقى على الشاشة إلّا رسالته:

طرفيّة داكنة فيها رسالة خادم التطوير: VITE v8.3.2 جاهز في 81 ميلّي ثانية، وتحتها العنوان المحلّيّ http://localhost:5173/my-first-site/، وسطرٌ يقول إنّ الخيار --host يكشفه للشبكة، وآخر يقول اضغط h ثمّ Enter للمساعدة.
خادم التطوير جاهزٌ بعد 81 ميلّي ثانية، وعنوانه المحلّيّ يحترم الإعداد base: localhost:5173/my-first-site/. لقطة شاشة من جهازي.

والميزة التي ستشعر بها أوّلًا هي التبديل السريع للوحدات، أو HMR كما يسمّيه توثيق Vite.[2] فافتح الصفحة على العنوان المحلّيّ، وغيّر لون الخلفيّة في style.css واحفظ الملفّ، فيتغيّر اللون في المتصفّح في اللحظة نفسها. ولا تحتاج إلى إعادة تحميل الصفحة، ولا يضيع ما كتبته فيها. ولاحظ أنّ العنوان المحلّيّ نفسه يحترم الإعداد base، فما تراه على جهازك هو ما سيراه الزائر. وحين تريد أن تتأكّد من النسخة المبنيّة لا نسخة التطوير، فالأمر npm run preview يقدّم مجلّد dist كما سيُنشر. والخادم لا يُرى إلّا على جهازك، ما لم تطلب غير ذلك بالخيار --host كما تقول الرسالة.

شكل 2 أمران لمرحلتين عمودان. في اليمين الأمر npm run dev: خادمٌ على جهازك على العنوان localhost:5173، والصفحة تتحدّث عند الحفظ. وفي اليسار العمود المميّز للأمر npm run build: ملفّاتٌ جاهزة للنشر في المجلّد dist، ترفعها إلى الاستضافة. npm run dev خادمٌ على جهازك localhost:5173 يتحدّث عند الحفظ npm run build ملفّاتٌ جاهزة للنشر dist/ ترفعها إلى الاستضافة أمران لمرحلتين عمودان. في اليمين الأمر npm run dev: خادمٌ على جهازك على العنوان localhost:5173، والصفحة تتحدّث عند الحفظ. وفي اليسار العمود المميّز للأمر npm run build: ملفّاتٌ جاهزة للنشر في المجلّد dist، ترفعها إلى الاستضافة. npm run dev خادمٌ على جهازك localhost:5173 يتحدّث عند الحفظ npm run build ملفّاتٌ جاهزة للنشر dist/ ترفعها إلى الاستضافة
أمران لمرحلتين: npm run dev خادمٌ على جهازك على localhost:5173 يتحدّث عند الحفظ، وnpm run build المميّز يكتب ملفّاتٍ جاهزة للنشر في المجلّد dist ترفعها إلى الاستضافة.

ما هي Vite في 2026؟

ستقرأ في شروحٍ كثيرة، بعضها مكتوبٌ هذه السنة، أنّ Vite تستعمل أداة esbuild في التطوير وأداة Rollup في البناء. وكان هذا صحيحًا، ويقول توثيق Vite نفسه إنّ الأداتين المنفصلتين سبّبتا اختلافاتٍ في السلوك بين المرحلتين. ولهذا بُنيت أداةٌ واحدة اسمها Rolldown، مكتوبةٌ بلغة Rust وتعتمد على مجموعة Oxc في التحليل والتحويل والتصغير، لتوحّد الطريق من التطوير إلى البناء.[8] وصارت الأداة الافتراضيّة مع Vite 8، الصادرة في 12 آذار 2026، وآخر إصدارٍ منها يوم كتابة هذا المقال 8.3.2.[9]

فإن قرأت شرحًا عن إعدادات Rollup في Vite، فاعرف أنّه مكتوبٌ لإصدارٍ أقدم، وراجع التوثيق الحاليّ قبل أن تنسخ منه. والقاعدة نفسها تصدق على كلّ أداةٍ في هذا المجال، فالأدوات تتغيّر أسرع من الشروح، والتوثيق الرسميّ وحده يواكبها. والأمر نفسه في ملفّ package.json: رقم الإصدار الذي تثبّته يقول لك أيّ صفحةٍ من التوثيق تقرأ.

وماذا عن webpack؟

ستقابل في مشاريع قائمة أداةً أقدم اسمها webpack، وما زالت تعمل في آلاف المواقع. ويعرّفها توثيقها بأنّها مجمِّعٌ ثابت للوحدات: تبدأ من نقطة دخولٍ أو أكثر، وتبني منها خريطةً بكلّ ما يعتمد عليه كلّ ملفّ، ثمّ تجمع ذلك في حزمةٍ أو أكثر.[10] وهذه الفكرة نفسها التي رأيتها في Vite. والفرق في التفاصيل: webpack تحتاج عادةً إلى ملفّ إعدادٍ أطول، وتجمع كلّ شيءٍ حتّى في التطوير. أمّا Vite فتقدّم الوحدات للمتصفّح مباشرةً أثناء التطوير، ولهذا بدأ خادمها في أقلّ من عُشر ثانية.

فإن ورثت مشروعًا مبنيًّا بـwebpack فلا تسرع إلى تغييره. اقرأ ملفّ webpack.config.js وابحث فيه عن entry وoutput، وستعرف من أين يبدأ وإلى أين يكتب. وإن بدأت مشروعًا جديدًا في 2026، فـVite نقطة البداية الأبسط، وهي الأداة التي تقف خلف أغلب أطر العمل الحديثة كما سترى في المقال التالي.

ما بعد البناء: ملفّ القفل وما لا يُرفع

بعد هذه الجلسة صار في المجلّد ما لم يكن فيه: مجلّد node_modules فيه Vite وحزمها، ومجلّد dist فيه الصفحة المبنيّة، وملفّ package-lock.json. والأوّلان لا يُرفعان إلى Git، وقالب Vite الرسميّ نفسه يضعهما في ملفّ ‎.gitignore.[11] فـnode_modules يعيد بناءه أيّ أحدٍ بأمرٍ واحد، وdist يعيد بناءه أمرٌ آخر. أمّا package-lock.json فيُرفع دائمًا، لأنّه يسجّل الإصدار الدقيق لكلّ حزمة، كما شرح مقال أمان الواجهة الأماميّة، وكما يضبط مقال Git ما يدخل المستودع وما يبقى خارجه.

وفي package.json ستجد Vite مكتوبةً هكذا: "vite": "^8.3.2". والعلامة ^ تقول لـnpm: اقبل أيّ إصدارٍ أحدث ما دام الرقم الأوّل هو نفسه، أي الإصدارات الصغيرة وإصلاحاتها. والعلامة ~ أضيق، تقبل الإصلاحات فقط.[12] وملفّ القفل هو ما يثبّت الرقم الفعليّ داخل هذا النطاق، فيبني كلّ من يثبّت المشروع بالأداة نفسها بالضبط.

وتذكّر من مقال الأمان قاعدةً تمسّ خطوة البناء مباشرةً. فقد تحتاج يومًا إلى قيمةٍ تختلف بين جهازك والموقع المنشور، كعنوان واجهة، فتضعها في ملفٍّ اسمه ‎.env. وVite تكشف في شيفرة الزائر كلّ متغيّرٍ يبدأ اسمه بـVITE_، فتكتب قيمته داخل الملفّ المبنيّ نفسه، ولا تكشف غيره.[13] فالعنوان العامّ لا بأس به هناك، أمّا المفتاح السرّيّ فلا يدخل ملفّ ‎.env بهذه البادئة أبدًا.

تحديث الأدوات بلا مفاجآت

الأدوات تتحدّث كلّ أسبوع تقريبًا، وVite نفسها وصلت إلى 8.3.2 بعد أقلّ من سبعة أشهر على الإصدار 8، ولمعرفة ما تأخّر في مشروعك، اكتب npm outdated. فيعرض لكلّ حزمةٍ ثلاثة أرقام: الحاليّ المثبّت، والمطلوب، أي أعلى إصدارٍ يسمح به النطاق في package.json، والأخير المنشور في السجلّ.[14] والفرق بين الأخيرين هو ما يحتاج منك قرارًا.

فالتحديث داخل النطاق، بالأمر npm update، آمنٌ في الغالب لأنّه لا يتجاوز الرقم الأوّل، أمّا الانتقال إلى رقمٍ أوّل جديد، من Vite 7 إلى 8 مثلًا، فقد يغيّر السلوك. ولهذا ينشر فريق Vite دليل انتقالٍ لكلّ إصدارٍ كبير، ويذكر فيه ما تغيّر بالتفصيل. ومن أمثلته في الانتقال إلى 8 أنّ المتصفّحات التي يستهدفها البناء افتراضيًّا صارت أحدث: من Chrome 107 إلى 111، ومن Safari 16.0 إلى 16.4.[15] فإن كان جمهورك يستعمل أجهزةً قديمة، فهذا سطرٌ يعنيك قبل أن تحدّث.

وإن تعطّل البناء بعد تحديثٍ أو سحبٍ من GitHub، فاقرأ أوّل سطر خطأٍ لا آخره، فالأسطر التالية نتائج له في الغالب. وإن شككت في أنّ node_modules فاسد، فاحذفه وثبّت من جديد بـnpm ci، فهو يبني المجلّد من ملفّ القفل وحده، كما شرح مقال الأمان. فتعرف حينها أنّ المشكلة في الشيفرة لا في التثبيت.

من dist إلى GitHub Pages

بقي سؤال: صفحتك على GitHub Pages تُنشر من الفرع main كما هو، والآن تحتاج إلى أن تُنشر محتويات dist بعد البناء. ولهذا طريقان. الأوّل أن يبني GitHub نفسه عند كلّ دفع، بسير عملٍ في GitHub Actions يثبّت التبعيّات بـnpm ثمّ يبني ثمّ ينشر dist. ويشرح توثيق Vite هذا الطريق في دليل النشر: تضبط base على اسم المستودع، وتختار من Settings ثمّ Pages المصدر GitHub Actions بدل الفرع.[16] والثاني أن تبني على جهازك وتدفع dist إلى فرعٍ خاصّ للنشر. والأوّل أفضل، لأنّ ما يُنشر يُبنى دائمًا من الشيفرة الموجودة في المستودع، لا من جهازٍ قد يكون عليه تعديلٌ لم تلتزم به.

وانتبه إلى ما يتغيّر حين تختار هذا الطريق. ففي مقال النشر كان GitHub يأخذ ملفّات الفرع main كما هي وينشرها. أمّا مع GitHub Actions فالفرع main يحمل ملفّات المصدر، وما يُنشر هو ما يخرجه البناء على خوادم GitHub. فإن فشل البناء مرّةً، بقي الموقع على آخر نسخةٍ نجحت، وظهرت لك العلامة الحمراء في تبويب Actions مع سجلّ الخطأ كاملًا، فتقرؤه كما تقرأ خطأ البناء على جهازك.

ولهذا تبقى صفحة المشروع على github.io بشكلها البسيط بلا خطوة بناء، فثلاثة ملفّات لا تحتاج إلى أداة. فخطوة البناء تُضاف حين يحتاجها المشروع: حين تتعدّد الملفّات، أو تأتي مكتباتٌ من npm، أو تكتب بلغةٍ يحوّلها شيءٌ قبل المتصفّح.

خلاصة عمليّة

ابدأ المشروع بـnpm init، وثبّت أدوات البناء بـ-D لأنّها لا تصل إلى الزائر، واجعل سكربتك من نوع module، وضع ما يُنسخ كما هو في مجلّد public. إن كانت صفحتك ستعيش في مجلّدٍ فرعيّ مثل github.io، فاضبط base قبل أوّل نشر، وافحص المسارات في dist/index.html بعينك. اعمل بـnpm run dev، وتأكّد بـnpm run preview، وانشر ما يخرجه npm run build. وارفع package-lock.json إلى Git، واترك node_modules وdist خارجه.

وكلّ ما بنيته في هذه السلسلة كتبته بـJavaScript عاديّة: زرٌّ هنا، وبطاقة طقسٍ هناك، لكنّ الواجهات الكبيرة فيها مئات العناصر التي تتغيّر معًا، وكتابتها بيدك تصير عبئًا. ولهذا وُلدت أطر العمل، وهي موضوع مقال أطر عمل JavaScript، حيث تقف Vite نفسها في الخلفيّة، تبني ما يكتبه الإطار.

المصادر

  1. موسوعة MDN، «Client-side tooling overview»: أدوات تساعدك على إنتاج شيفرة الويب بكفاءة، ومنها أدوات التحويل التي تحوّل ما تكتبه إلى ما يفهمه المتصفّح.
  2. مشروع Node.js، «Node.js Releases»: الإصدار طويل الدعم Node 24 (Krypton)، وآخر إصداراته 24.21.0 في 7 أيلول 2026. وتوثيق Vite، «Getting Started»: تحتاج Vite إلى Node.js بإصدار 20.19 أو 22.12 فما فوق.
  3. توثيق npm، «package.json»: أدوات الاختبار والتوثيق التي لا يحتاجها من يستعمل الحزمة مكانها devDependencies.
  4. توثيق npm، «scripts»: البرامج التي تثبّتها الحزم في node_modules/.bin تُضاف إلى مسار البحث حين يشغّل npm سكربتات package.json.
  5. توثيق Vite، «index.html and Project Root»: الملفّ index.html في واجهة مشروع Vite، وهو نقطة الدخول التي تبدأ منها الأداة.
  6. توثيق Vite، «The public Directory»: ما في المجلّد public يُقدَّم من الجذر أثناء التطوير ويُنسخ إلى جذر dist كما هو.
  7. توثيق Vite، «Shared Options: base»: المسار العامّ الأساسيّ للموقع، وقيمته الافتراضيّة الشرطة المائلة.
  8. توثيق Vite، «Why Vite»: اعتمدت Vite أوّلًا على esbuild في التطوير وRollup في البناء فظهرت اختلافاتٌ بينهما، ثمّ وحّدتهما Rolldown المكتوبة بلغة Rust والمعتمدة على Oxc في التحليل والتحويل والتصغير.
  9. فريق Vite، «Vite 8.0 is out!»، 12 آذار 2026. وسجلّ npm، «vite»: الإصدار 8.3.2 يوم 1 تشرين الأوّل 2026.
  10. توثيق webpack، «Concepts»: webpack مجمِّعٌ ثابت للوحدات يبني خريطة اعتمادٍ من نقطة دخولٍ أو أكثر ثمّ يجمعها في حزمة، ومفاهيمه الأساسيّة entry وoutput والمحمِّلات والإضافات.
  11. مستودع Vite، «template-vanilla/_gitignore»: القالب الرسميّ يستثني node_modules وdist من Git.
  12. توثيق npm، «About semantic versioning»: ‎^1.0.4 تقبل الإصدارات الصغيرة، و‎~1.0.4 تقبل الإصلاحات فقط.
  13. توثيق Vite، «Env Variables and Modes»: المتغيّرات التي تبدأ بـVITE_ تُكشف في شيفرة العميل بعد البناء ولا يجوز أن تحمل معلوماتٍ حسّاسة.
  14. توثيق npm، «npm-outdated»: الحقل wanted أعلى إصدارٍ يرضي نطاق package.json، والحقل latest الإصدار الموسوم بالأخير في السجلّ.
  15. توثيق Vite، «Migration from v7»: صارت قيم build.target الافتراضيّة أحدث، ومنها Chrome من 107 إلى 111 وSafari من 16.0 إلى 16.4.
  16. توثيق Vite، «Deploying a Static Site: GitHub Pages»: اضبط base على ‎/<REPO>/ لموقع المشروع، واختر المصدر GitHub Actions في إعدادات Pages، وسير عملٍ يثبّت التبعيّات بـnpm ويبني الموقع وينشره عند كلّ دفعٍ إلى main.

اترك تعليقاً

الحقول المميّزة بـ مطلوبة