<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: nodejs</title><link>https://academy.hsoub.com/programming/javascript/nodejs/page/3/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: nodejs</description><language>ar</language><item><title>&#x62F;&#x645;&#x62C; &#x642;&#x627;&#x639;&#x62F;&#x629; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MongoDB &#x641;&#x64A; &#x62A;&#x637;&#x628;&#x64A;&#x642;&#x643; Node</title><link>https://academy.hsoub.com/programming/javascript/nodejs/%D8%AF%D9%85%D8%AC-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mongodb-%D9%81%D9%8A-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%83-node-r810/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_02/2.jpg.4b30b4e168181700f931b69df81fc638.jpg" /></p>

<p>
	قد تجد نفسك، وأنت تستخدم <a href="https://wiki.hsoub.com/Node.js" rel="external">node.js</a>، أنك بصدد تطوير مشروع يُخزّن البيانات والاستعلام عنها. في هذه الحالة، ستحتاج إلى اختيار حلّ تقني لقاعدة البيانات يكون ملائما لأنواع البيانات والاستعلامات التي يستخدمها تطبيقك.
</p>

<p>
	في هذا الدّرس، ستعمل على دمج قاعدة بيانات <a href="https://www.mongodb.com/" rel="external nofollow">MongoDB</a> مع تطبيق Node موجودٍ سلفًا. يمكن أن تكون قواعد البيانات <a href="https://academy.hsoub.com/devops/servers/databases/%D8%B4%D8%B1%D8%AD-%D8%A7%D9%84%D9%81%D8%B1%D9%88%D9%82%D8%A7%D8%AA-%D8%A8%D9%8A%D9%86-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-sql-%D9%88%D9%86%D8%B8%D9%8A%D8%B1%D8%A7%D8%AA%D9%87%D8%A7-nosql-r71/" rel="">NoSQL</a> مثل MongoDB مفيدةً إذا كانت متطلبات بياناتك تتضمن قابلية التوسع والمرونة. ويتكامل MongoDB جيدًا مع Node لأنه مصمم للعمل بشكل غير متزامن مع <a href="https://wiki.hsoub.com/JavaScript/JSON" rel="external">كائنات JSON</a>.
</p>

<p>
	من أجل دمج MongoDB في مشروعك، سوف تستخدم Object Document Mapper) ODM) الخاص ب <a href="https://mongoosejs.com/" rel="external nofollow">Mongoose</a> لإنشاء مخططات ونماذج بيانات لتطبيقك. سيتيح لك ذلك تنظيم شيفرة التطبيق وفقًا للنمط الهيكلي MVC، والذي يسمح بفصل المنطق الذي يحكم كيفية معالجة التطبيق لإدخالات المستخدم عن ذلك الذي يتعلق بكيفية هيكلة البيانات وتقديمها إلى المستخدم. ويسهّل الاعتمادُ على هذا النمط الاختبار والتطوير في المستقبل عبر فصل المتعلّقات في قاعدة البيانات الخاصة بك.
</p>

<p>
	في نهاية البرنامج التعليمي، سيكون لديك تطبيق جاهز خاصّ بمعلومات سمك القرش يعمل على أخذ مدخلات المستخدم حول أسماك القرش المفضلة لديه وعرض النتائج في المتصفح:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33613" href="https://academy.hsoub.com/uploads/monthly_2020_02/shark_added.png.34746f17cf2306be59c6004c617f5049.png" rel=""><img alt="shark_added.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33613" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_02/shark_added.thumb.png.754592f15632ec446b561ba5df68537c.png"></a>
</p>

<h2>
	المتطلبات الأساسية
</h2>

<ul>
<li>
		جهاز أو خادم تطوير محلي يعمل على نظام أوبونتو 18.04، إلى جانب مستخدم غير جذري بصلاحيات sudo وجدار حماية نشط. للحصول على إرشادات حول كيفية إعدادها على خادم 18.04، يرجى الاطلاع على <a href="https://academy.hsoub.com/devops/servers/%D8%AF%D9%84%D9%8A%D9%84-%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%AE%D8%A7%D8%AF%D9%85-%D9%88%D9%8A%D8%A8-%D9%85%D8%AD%D9%84%D9%8A-%D8%AE%D8%B7%D9%88%D8%A9-%D8%A8%D8%AE%D8%B7%D9%88%D8%A9-r422/" rel="">دليل إعداد الخادم الأولي</a>.
	</li>
	<li>
		Node.js و npm مثبتين على الجهاز أو الخادم، باتباع هذه <a href="https://academy.hsoub.com/devops/linux/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-nodejs-%D8%B9%D9%84%D9%89-%D9%86%D8%B8%D8%A7%D9%85-%D8%A3%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r419" rel="">الإرشادات حول التثبيت باستخدام PPA المدار بواسطة NodeSource</a>.
	</li>
	<li>
		تثبيت MongoDB على الجهاز أو الخادم، باتباع الخطوة الأولى من <a href="https://academy.hsoub.com/devops/servers/databases/mongodb/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%AA%D8%A3%D9%85%D9%8A%D9%86-mongodb-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r435/" rel="">كيفية تثبيت MongoDB في أوبونتو 18.04</a>.
	</li>
</ul>
<h2>
	الخطوة الأولى: إنشاء مستخدم Mongo
</h2>

<p>
	قبل أن نبدأ العمل بشيفرة التطبيق، سننشئ مستخدمًا إداريًا يملك صلاحية الوصول إلى قاعدة بيانات التطبيق. سيكون لهذا المستخدم أذونات إدارية على أي قاعدة بيانات، مما يمنحك المرونة في التبديل وإنشاء قواعد بيانات جديدة حسب الحاجة.
</p>

<p>
	أولاً، تحقق أن <code>MongoDB</code> يشتغل على خادمك:
</p>

<pre class="ipsCode">
sudo systemctl status mongodb
</pre>

<p>
	يدلّ الإخراج التالي على أنّ <code>MongoDB</code> يشتغل:
</p>

<pre class="ipsCode">
● mongodb.service - An object/document-oriented database
   Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2019-01-31 21:07:25 UTC; 21min ago
...
</pre>

<p>
	بعد ذلك، افتح الصدفة الخاصة ب Mongo من أجل إنشاء مستخدمك:
</p>

<pre class="ipsCode">
Mongo
</pre>

<p>
	سينقلك هذا الأمر إلى صدفة إدارية:
</p>

<pre class="ipsCode">
MongoDB shell version v3.6.3
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.3
...
&gt;
</pre>

<p>
	ستظهر لك بعض التحذيرات الإدارية عند فتح الصدفة (shell) نظرًا لغياب قيود على وصولك إلى قاعدة بيانات الخاصة بالمشرف admin. لمعرفة المزيد حول تقييد هذا الوصول يمكنك قراءة <a href="https://academy.hsoub.com/devops/servers/databases/mongodb/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%AA%D8%A3%D9%85%D9%8A%D9%86-mongodb-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r435/" rel="">كيفية تثبيت وتأمين MongoDB على أوبونتو 18.04</a>، عندما تنتقل إلى إعدادات الإنتاج.
</p>

<p>
	تستطيع الآن الاستفادة من وصولك إلى قاعدة بيانات المشرف admin لإنشاء مستخدم يمتلك الأذونات <code>userAdminAnyDatabase</code> التي تتيح الوصول المحمي بكلمة مرور لقواعد بيانات التطبيق.
</p>

<p>
	حدّد في الصّدفة shell، أنك تريد استخدام قاعدة بيانات المشرف admin لإنشاء مستخدمك:
</p>

<pre class="ipsCode">
use admin
</pre>

<p>
	بعد ذلك، أنشئ دورًا (role) وكلمة مرور عبر إضافة اسم مستخدم وكلمة مرور باستخدام الأمر <code>db.createUser</code>. بعد كتابة هذا الأمر، ستُظهِر الصدفة ثلاث نقاط قبل كل سطر حتى يكتمل تنفيذ الأمر. تأكد من تغيير المستخدم وكلمة المرور المقدمين هنا باسم المستخدم وكلمة المرور الخاصين بك:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_6" style="">
<span class="pln">db</span><span class="pun">.</span><span class="pln">createUser</span><span class="pun">(</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    user</span><span class="pun">:</span><span class="pln"> </span><span class="str">"sammy"</span><span class="pun">,</span><span class="pln">
    pwd</span><span class="pun">:</span><span class="pln"> </span><span class="str">"your_password"</span><span class="pun">,</span><span class="pln">
    roles</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> role</span><span class="pun">:</span><span class="pln"> </span><span class="str">"userAdminAnyDatabase"</span><span class="pun">,</span><span class="pln"> db</span><span class="pun">:</span><span class="pln"> </span><span class="str">"admin"</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">)</span></pre>

<p>
	سينشئ هذا الأمر إدخالًا للمستخدم sammy في قاعدة بيانات المشرف admin. وسيعمل اسم المستخدم الذي تحدده وقاعدة بيانات المشرف admin كمحدّدات للمستخدم.
</p>

<p>
	وسيبدو إخراج العملية برمّتها كما يلي، بما في ذلك الرسالة التي تشير إلى نجاح الإدخال:
</p>

<pre class="ipsCode">
&gt; db.createUser(
...  {
...    user: "sammy",
...    pwd: "your_password",
...    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
...  }
...)
Successfully added user: {
        "user" : "sammy",
        "roles" : [
                {
                        "role" : "userAdminAnyDatabase",
                        "db" : "admin"
                }
        ]
}
</pre>

<p>
	يمكنك بعد إنشاء المستخدم وكلمة المرور، الخروج من الصّدفة الخاصة ب Mongo:
</p>

<pre class="ipsCode">
exit
</pre>

<p>
	وتستطيع كذلك الآن، بعد أن أنشأت مستخدم قاعدة البيانات الخاصة بك، الانتقال إلى استنساخ شيفرة المشروع البدئية وإضافة مكتبة <code>Mongoose</code>، والتي سوف تسمح لك بتنفيذ المخططات والنماذج للمجموعات (collections) في قواعد بياناتك.
</p>

<h2>
	الخطوة الثانية: إضافة معلومات Mongoose وقاعدة البيانات إلى المشروع
</h2>

<p>
	ستكون خطوتنا التالية هي استنساخ شيفرة التطبيق البدئية وإضافة معلومات Mongoose وقاعدة بيانات MongoDB إلى المشروع.
</p>

<p>
	في المجلّد الرئيسي للمستخدم غير الجذري، استنسخ مستودع <code>nodejs-image-demo</code> من حساب DigitalOcean Community GitHub. ويتضمن مستودع التخزين هذا الشيفرة الخاصة بالإعداد الموضح في <a href="https://academy.hsoub.com/programming/javascript/nodejs/%D8%A8%D9%86%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-nodejs-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-docker-r809/" rel="">كيفية إنشاء تطبيق Node.js باستخدام Docker</a>.
</p>

<p>
	انسخ المستودع في مجلّد يسمى node_project:
</p>

<pre class="ipsCode">
git clone https://github.com/do-community/nodejs-image-demo.git node_project
</pre>

<p>
	انتقل إلى المجلّد <code>node_project</code>:
</p>

<pre class="ipsCode">
cd  node_project
</pre>

<p>
	قبل تعديل شيفرة المشروع، دعنا نلقي نظرة على بنية المشروع باستخدام الأمر <code>tree</code> . ملحوظة: يعدّ الأمر <code>tree</code> مفيدًا لعرض بنيات الملفات والمجلّدات من سطر الأوامر. يمكنك تثبيته باستخدام الأمر التالي:
</p>

<pre class="ipsCode">
sudo apt install tree
</pre>

<p>
	ومن أجل استخدامه، انتقل بالأمر <code>cd</code> إلى مجلّد معين واكتب <code>tree</code>. يمكنك أيضًا أن تزوّد الأمر بكامل المسار إلى النقطة المحدّدة باستخدام أمر مثل:
</p>

<pre class="ipsCode">
tree /home/sammy/sammys-project
</pre>

<p>
	اكتب ما يلي لمعاينة المجلّد node_project:
</p>

<pre class="ipsCode">
tree
</pre>

<p>
	تبدو بنية المشروع الحالي كما يلي:
</p>

<pre class="ipsCode">
├── Dockerfile
├── README.md
├── app.js
├── package-lock.json
├── package.json
└── views
    ├── css
    │   └── styles.css
    ├── index.html
    └── sharks.html
</pre>

<p>
	سنضيف كلما تقدمنا في هذا البرنامج التعليمي بعض المجلّدات إلى هذا المشروع، وسيكون الأمر tree مفيدًا لمساعدتنا في تتبع تقدمنا.
</p>

<p>
	بعد ذلك، أضف حزمة npm mongoose إلى المشروع باستخدام الأمر <code>npm install</code>:
</p>

<pre class="ipsCode">
npm install mongoose
</pre>

<p>
	سينشئ هذا الأمر مجلّد node_modules في مجلّد مشروعك، باستخدام الاعتماديات المدرجة في ملف package.json الخاص بالمشروع، وسيضيف كذلك mongoose إلى هذا المجلّد. سيضيف mongoose أيضًا إلى الاعتماديات المدرجة في ملفك package.json. للحصول على توضيح أكثر تفصيلا عن package.json، يرجى الاطلاع على الخطوة الأولى في <a href="https://academy.hsoub.com/programming/javascript/nodejs/%D8%A8%D9%86%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-nodejs-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-docker-r809/" rel="">كيفية إنشاء تطبيق Node.js باستخدام Docker</a>.
</p>

<p>
	قبل إنشاء أي مخططات أو نماذج لMongoose، سنضيف معلومات اتصال قاعدة البيانات حتى يتمكن التطبيق من الاتصال بقاعدة البيانات الخاصة بنا.
</p>

<p>
	من أجل فصل العناصر المتعلّقة بالتطبيق قدر الإمكان، أنشئ ملفًا منفصلًا لمعلومات اتصال قاعدة البيانات باسم <code>db.js</code>. ويمكنك فتح هذا الملف باستخدام nano أو المحرر المفضل لديك:
</p>

<pre class="ipsCode">
nano db.js
</pre>

<p>
	ستستورد أولاً وحدة mongoose باستخدام الدالّة require:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/db.js</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_8" style="">
<span class="kwd">const</span><span class="pln"> mongoose </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'mongoose'</span><span class="pun">);</span></pre>

<p>
	سوف يتيح لك ذلك الوصول إلى توابع Mongoose المدمجة، والتي ستستخدمها لإنشاء اتصال بقاعدة البيانات الخاصة بك.
</p>

<p>
	بعد ذلك، أضف <a href="https://wiki.hsoub.com/PHP/constants" rel="external">الثوابت</a> التالية لتحديد معلومات الاتصال URI الخاصة بMongo. رغم أن اسم المستخدم وكلمة المرور اختياريان، ولكننا سندرجهما حتى نتمكن من طلب مصادقة الهوية على قاعدة البيانات. تأكد من استبدال اسم المستخدم وكلمة المرور بمعلوماتك الخاصة، وتبقى لك الحرية في طلب شيء آخر من قاعدة البيانات غير sharkinfo إذا كنت تفضل ذلك:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/db.js</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_10" style="">
<span class="kwd">const</span><span class="pln"> mongoose </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'mongoose'</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> MONGO_USERNAME </span><span class="pun">=</span><span class="pln"> </span><span class="str">'sammy'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> MONGO_PASSWORD </span><span class="pun">=</span><span class="pln"> </span><span class="str">'your_password'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> MONGO_HOSTNAME </span><span class="pun">=</span><span class="pln"> </span><span class="str">'127.0.0.1'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> MONGO_PORT </span><span class="pun">=</span><span class="pln"> </span><span class="str">'27017'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> MONGO_DB </span><span class="pun">=</span><span class="pln"> </span><span class="str">'sharkinfo'</span><span class="pun">;</span></pre>

<p>
	نظرًا لأننا نشغّل قاعدة البيانات محليًا، فقد استخدمنا 127.0.0.1 اسمًا للمضيف. قد يكون الأمر مغايرًا في سياقات تطوير أخرى: على سبيل المثال، إذا كنت تستخدم خادم قاعدة بيانات منفصل أو تعمل باستخدام عقد متعدّدة في إطار سير عمل يتضمن حاويات.
</p>

<p>
	ختامًا، حدّد قيمة ثابتة لـ URI وأنشئ الاتصال باستخدام التابع <code>()mongoose.connect</code>: الملف <code>‎~/node_project/db.js</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_12" style="">
<span class="pun">...</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> url </span><span class="pun">=</span><span class="pln"> </span><span class="pun">`</span><span class="pln">mongodb</span><span class="pun">:</span><span class="com">//${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?authSource=admin`;</span><span class="pln">

mongoose</span><span class="pun">.</span><span class="pln">connect</span><span class="pun">(</span><span class="pln">url</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">useNewUrlParser</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">});</span></pre>

<p>
	لاحظ أننا في URI حدّدنا <code>authSource</code> لمستخدمنا كمشرف لقاعدة البيانات. ويعدّ هذا الأمر ضروريًا لأننا حددنا اسم مستخدم في سلسلة الاتصال connection string. ويحدّد استخدام الراية <code>useNewUrlParser</code> مع التابع ()mongoose.connect أننا نريد استخدام مفسّر URL الجديد الخاص بـ Mongo.
</p>

<p>
	احفظ الملف وأغلقه عند الانتهاء من التحرير.
</p>

<p>
	كخطوة أخيرة، أضف معلومات اتصال قاعدة البيانات إلى ملف app.js بحيث يمكن للتطبيق استخدامها. ثم افتح التطبيق.
</p>

<pre class="ipsCode">
nano app.js
</pre>

<p>
	ستبدو الأسطر الأولى من الملف كما يلي:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/app.js</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_14" style="">
<span class="kwd">const</span><span class="pln"> express </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'express'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> app </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> router </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">.</span><span class="typ">Router</span><span class="pun">();</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> path </span><span class="pun">=</span><span class="pln"> __dirname </span><span class="pun">+</span><span class="pln"> </span><span class="str">'/views/'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">...</span></pre>

<p>
	أسفل السّطر الذي يحدّد القيمة الثابتة للكائن router، الموجود قريبًا من أعلى الملف، أضف السطر التالي:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/app.js</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_16" style="">
<span class="pun">...</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> router </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">.</span><span class="typ">Router</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> db </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'./db'</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> path </span><span class="pun">=</span><span class="pln"> __dirname </span><span class="pun">+</span><span class="pln"> </span><span class="str">'/views/'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">...</span></pre>

<p>
	يطلب هذا الأمر من التطبيق استخدام معلومات اتصال قاعدة البيانات المحددة في <code>db.js</code>.
</p>

<p>
	احفظ الملف وأغلقه عند الانتهاء من التحرير.
</p>

<p>
	بوجود معلومات قاعدة البيانات وبعد إضافتها إلى مشروعك، تكون مستعدًا لإنشاء المخططات والنماذج التي ستشكل البيانات في المجموعة sharks.
</p>

<h2>
	الخطوة الثالثة: إنشاء مخططات ونماذج Mongoose
</h2>

<p>
	ستكون خطوتنا التالية هي التفكير في بنية المجموعة sharks التي سينشئها المستخدمون في قاعدة بيانات sharkinfo بواسطة مدخلاتهم. فما هي البنية التي نريد أن تكون لهذه المستندات التي أُنشئت؟ تتضمن صفحة معلومات سمك القرش في تطبيقنا الحالي بعض التفاصيل حول أسماك القرش المختلفة وسلوكياتها:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33616" href="https://academy.hsoub.com/uploads/monthly_2020_02/shark.png.652bfb0573bc51764700b982a4364a4d.png" rel=""><img alt="shark.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33616" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_02/shark.thumb.png.604eeba2a7b1580f930878a8fdea6f81.png"></a>
</p>

<p>
	وفقًا لذلك، سيكون بإمكان المستخدمين أن يضيفوا أسماك قرش جديدة مرفقة بتفاصيل حول سلوكها العام. وسيحدّد هذا الهدف كيفية إنشاء مخططنا.
</p>

<p>
	من أجل تمييز مخططاتك ونماذجك عن الأجزاء الأخرى لتطبيقك، أنشئ مجلّدا models في مجلّد المشروع الحالي:
</p>

<pre class="ipsCode">
mkdir models
</pre>

<p>
	بعد ذلك، افتح ملفًا باسم <code>sharks.js</code> لإنشاء مخططك ونموذجك:
</p>

<pre class="ipsCode">
nano models/sharks.js
</pre>

<p>
	استورد وحدة <code>Mongose</code> في الجزء العلوي من الملف:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/models/sharks.js</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_18" style="">
<span class="kwd">const</span><span class="pln"> mongoose </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'mongoose'</span><span class="pun">);</span></pre>

<p>
	بعد ذلك، حدّد كائنًا Schema لاستخدامه أساسًا للمخطط الخاصّ بأسماك القرش:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/models/sharks.js</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_20" style="">
<span class="kwd">const</span><span class="pln"> mongoose </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'mongoose'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Schema</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> mongoose</span><span class="pun">.</span><span class="typ">Schema</span><span class="pun">;</span></pre>

<p>
	يمكنك الآن تحديد الحقول التي تريد تضمينها في مخطّطك. ونظرًا لأننا نريد إنشاء مجموعة تحتوي على أسماك قرش فردية ومعلومات حول سلوكياتها، فلنُضمِّن فيها مفتاحين واحدٌ للاسم name والآخر للسلوك character. أضف مخطط Shark التالي أسفل تعريفات الثوابت:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/models/sharks.js</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_22" style="">
<span class="pun">...</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Shark</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Schema</span><span class="pln"> </span><span class="pun">({</span><span class="pln">
        name</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> type</span><span class="pun">:</span><span class="pln"> </span><span class="typ">String</span><span class="pun">,</span><span class="pln"> required</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
        character</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> type</span><span class="pun">:</span><span class="pln"> </span><span class="typ">String</span><span class="pun">,</span><span class="pln"> required</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	يتضمن هذا التعريف معلومات حول نوع الإدخال الذي نتوقعه من المستخدمين، وهو في هذه الحالة، سلسلة نصّية، وهل هذا الإدخال ضروري أم لا.
</p>

<p>
	أخيرًا ، أنشئ نموذج Shark باستخدام دالة Mongoose التالية model()‎. سيتيح لك هذا النموذج الاستعلام عن المستندات من خلال مجموعتك والتحقق من صحة المستندات الجديدة. أضف السطر التالي في أسفل الملف:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_24" style="">
<span class="pun">...</span><span class="pln">
module</span><span class="pun">.</span><span class="pln">exports </span><span class="pun">=</span><span class="pln"> mongoose</span><span class="pun">.</span><span class="pln">model</span><span class="pun">(</span><span class="str">'Shark'</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">)</span></pre>

<p>
	يجعل هذا السطر الأخير النموذج Shark متاحًا كوحدة نمطية باستخدام <a href="https://nodejs.org/api/modules.html#modules_exports_shortcut" rel="external nofollow">خاصية module.exports</a>. إذ تحدّد هذه الخاصية القيم التي ستصدرها الوحدة النمطية، مما يجعلها متاحة للاستخدام في أي مكان آخر في التطبيق.
</p>

<p>
	سيبدو الملف النهائي models/sharks.js على هذا النحو:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_26" style="">
<span class="kwd">const</span><span class="pln"> mongoose </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'mongoose'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Schema</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> mongoose</span><span class="pun">.</span><span class="typ">Schema</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Shark</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Schema</span><span class="pln"> </span><span class="pun">({</span><span class="pln">
        name</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> type</span><span class="pun">:</span><span class="pln"> </span><span class="typ">String</span><span class="pun">,</span><span class="pln"> required</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
        character</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> type</span><span class="pun">:</span><span class="pln"> </span><span class="typ">String</span><span class="pun">,</span><span class="pln"> required</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

module</span><span class="pun">.</span><span class="pln">exports </span><span class="pun">=</span><span class="pln"> mongoose</span><span class="pun">.</span><span class="pln">model</span><span class="pun">(</span><span class="str">'Shark'</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">)</span></pre>

<p>
	احفظ الملف وأغلقه عند الانتهاء من التحرير.
</p>

<p>
	بإنشائك لمخطط Shark ونموذجه، سيكون بإمكانك البدء في العمل على المنطق الذي تريده أن يحكم كيفية تعامل تطبيقك مع مدخلات المستخدم.
</p>

<h2>
	الخطوة الرابعة: إنشاء وحدات التحكم
</h2>

<p>
	ستكون خطوتنا التالية هي إنشاء وحدة التحكم التي تحدد كيفية حفظ مدخلات المستخدم في قاعدة البيانات وإعادتها إليه.
</p>

<p>
	أنشئ أولاً مجلّدًا لوحدة التحكم:
</p>

<pre class="ipsCode">
mkdir controllers
</pre>

<p>
	بعد ذلك، افتح ملفًا في هذا المجلد باسم sharks.js:
</p>

<pre class="ipsCode">
nano controllers/sharks.js
</pre>

<p>
	في الجزء العلوي من الملف، سنستورد الوحدة مع النموذج Shark لكي نستطيع استخدامها في منطق وحدة التحكم لدينا. سنستورد أيضًا <a href="https://nodejs.org/api/path.html" rel="external nofollow">وحدة المسار path</a> للوصول إلى الأدوات المساعدة التي ستتيح لنا تعيين المسار إلى الاستمارة التي سيدخل فيها المستخدمون معلوماتهم عن أسماك القرش.
</p>

<p>
	أضف الدوالّ require التالية إلى بداية الملف:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/controllers/sharks.js</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_28" style="">
<span class="kwd">const</span><span class="pln"> path </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'path'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Shark</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'../models/sharks'</span><span class="pun">);</span></pre>

<p>
	بعد ذلك، سنكتب سلسلة من الدوال التي سنصدّرها مع وحدة التحكم باستخدام اختصارات Node للتصدير exports. ستشمل هذه الدوالّ المهام الثلاثة المتعلقة ببيانات سمك القرش الخاصة بمستخدمنا:
</p>

<ul>
<li>
		إرسال إستمارة إدخال سمك القرش للمستخدمين.
	</li>
	<li>
		إنشاء إدخالٍ لقرش جديد.
	</li>
	<li>
		إعادة عرض أسماك القرش للمستخدمين.
	</li>
</ul>
<p>
	من أجل البدء، أنشئ دالةً index لعرض صفحة أسماك القرش مع إستمارة الإدخال. أضف هذه الدّالة أسفل الاستيرادات:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_30" style="">
<span class="pun">...</span><span class="pln">
exports</span><span class="pun">.</span><span class="pln">index </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    res</span><span class="pun">.</span><span class="pln">sendFile</span><span class="pun">(</span><span class="pln">path</span><span class="pun">.</span><span class="pln">resolve</span><span class="pun">(</span><span class="str">'views/sharks.html'</span><span class="pun">));</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	بعد ذلك أضف، أسفل الدالة index، دالّة بالاسم create لإنشاء إدخال جديد لسمك القرش في المجموعة Sharks:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_32" style="">
<span class="pun">...</span><span class="pln">
exports</span><span class="pun">.</span><span class="pln">create </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">var</span><span class="pln"> newShark </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="pln">req</span><span class="pun">.</span><span class="pln">body</span><span class="pun">);</span><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">req</span><span class="pun">.</span><span class="pln">body</span><span class="pun">);</span><span class="pln">
    newShark</span><span class="pun">.</span><span class="pln">save</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">err</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">err</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            res</span><span class="pun">.</span><span class="pln">status</span><span class="pun">(</span><span class="lit">400</span><span class="pun">).</span><span class="pln">send</span><span class="pun">(</span><span class="str">'Unable to save shark to database'</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            res</span><span class="pun">.</span><span class="pln">redirect</span><span class="pun">(</span><span class="str">'/sharks/getshark'</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">
               </span><span class="pun">};</span></pre>

<p>
	سوف تستدعى هذه الدّالة عندما يرسل المستخدم بيانات سمك القرش إلى الإستمارة على الصفحة sharks.html. سننشئ لاحقًا المسار route الخاصّ بهذا الإرسال POST في هذا البرنامج التعليمي عندما ننشئ مسارات التطبيق. باستخدام المحتوى body الخاصّ بالطلب POST، ستنشئ الدالة create كائن ملفّ سمك القرش الجديد، الذي يأخذ هنا الاسم newShark، اعتمادًا على النموذج Shark الذي استوردناه. ولقد أضفنا التابع console.log من أجل إظهار الإدخال الخاصّ بسمك القرش إلى الطرفية من أجل التحقق من أن طريقة POST تعمل على النحو المنشود، ولكن تبقى لك الحرّية في تجاوز هذا الأمر إذا كنت تفضل ذلك.
</p>

<p>
	باستخدام الكائنnewShark ، ستستدعي الدالة create بعد ذلك تابع Mongoose المسمّى model.save()‎ من أجل إنشاء ملفّ سمك قرش جديد اعتمادًا على المفاتيح التي حدّدتها في النموذج Shark.
</p>

<p>
	تتبع دالّة ردّ النداء هذه نموذج ردّ النداء المعياري في Node وهو: callback(error, results)‎. في حالة وجود خطأ، نرسل رسالة تُبلغ المستخدمين عن الخطأ، وفي حالة نجاح العمليّة، نستخدم التابع res.redirect()‎ لتوجيه المستخدمين إلى نقطة النهاية التي ستعيد معلومات القرش إليهم على المتصفح.
</p>

<p>
	في الختام، ستعرض الدّالة list محتويات المجموعة مرة أخرى للمستخدم. أضف الشيفرة التالية أسفل الدالة create:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_34" style="">
<span class="pun">...</span><span class="pln">
exports</span><span class="pun">.</span><span class="pln">list </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Shark</span><span class="pun">.</span><span class="pln">find</span><span class="pun">({}).</span><span class="pln">exec</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">err</span><span class="pun">,</span><span class="pln"> sharks</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">err</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                        </span><span class="kwd">return</span><span class="pln"> res</span><span class="pun">.</span><span class="pln">send</span><span class="pun">(</span><span class="lit">500</span><span class="pun">,</span><span class="pln"> err</span><span class="pun">);</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
                res</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="str">'getshark'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                        sharks</span><span class="pun">:</span><span class="pln"> sharks
             </span><span class="pun">});</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	تستخدم هذه الدالّة النموذج Shark بالاعتماد على التابع ()model.find الخاصّ بMongoose من أجل إرجاع معلومات أسماك القرش التي أُدخِلت في المجموعة sharks. يتمّ هذا الأمر عبر إرجاع كائن الاستعلام query object، ويمثل في هذه الحالة جميع الإدخالات في المجموعة sharks، باستخدام الدالّة ()exec الخاصّة ب Mongoose. في حالة وجود خطأ، سترسل دالّة رد النّداء خطأً 500.
</p>

<p>
	سوف يُعرض كائن الاستعلام الذي أرجعته الدّالة مع المجموعة sharks في الصفحة getshark التي سننشئها في الخطوة التالية باستخدام لغة القوالب EJS.
</p>

<p>
	سيبدو الملف النهائي <code>‎~/node_project/controllers/sharks.js</code> على هذا النحو:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_36" style="">
<span class="kwd">const</span><span class="pln"> path </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'path'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Shark</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'../models/sharks'</span><span class="pun">);</span><span class="pln">

exports</span><span class="pun">.</span><span class="pln">index </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    res</span><span class="pun">.</span><span class="pln">sendFile</span><span class="pun">(</span><span class="pln">path</span><span class="pun">.</span><span class="pln">resolve</span><span class="pun">(</span><span class="str">'views/sharks.html'</span><span class="pun">));</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

exports</span><span class="pun">.</span><span class="pln">create </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">var</span><span class="pln"> newShark </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="pln">req</span><span class="pun">.</span><span class="pln">body</span><span class="pun">);</span><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">req</span><span class="pun">.</span><span class="pln">body</span><span class="pun">);</span><span class="pln">
    newShark</span><span class="pun">.</span><span class="pln">save</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">err</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">err</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            res</span><span class="pun">.</span><span class="pln">status</span><span class="pun">(</span><span class="lit">400</span><span class="pun">).</span><span class="pln">send</span><span class="pun">(</span><span class="str">'Unable to save shark to database'</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            res</span><span class="pun">.</span><span class="pln">redirect</span><span class="pun">(</span><span class="str">'/sharks/getshark'</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">
               </span><span class="pun">};</span><span class="pln">

exports</span><span class="pun">.</span><span class="pln">list </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Shark</span><span class="pun">.</span><span class="pln">find</span><span class="pun">({}).</span><span class="pln">exec</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">err</span><span class="pun">,</span><span class="pln"> sharks</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">err</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                        </span><span class="kwd">return</span><span class="pln"> res</span><span class="pun">.</span><span class="pln">send</span><span class="pun">(</span><span class="lit">500</span><span class="pun">,</span><span class="pln"> err</span><span class="pun">);</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
                res</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="str">'getshark'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                        sharks</span><span class="pun">:</span><span class="pln"> sharks
             </span><span class="pun">});</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	ضع في اعتبارك أنه رغم أننا لا نستخدم الدّوال السهمية هنا، فقد ترغب في تضمينها أثناء تكرارك لهذه الشيفرة في عمليتك التطويرية.
</p>

<p>
	احفظ الملف وأغلقه عند الانتهاء من التحرير.
</p>

<p>
	قبل الانتقال إلى الخطوة التالية، يمكنك تنفيذ الأمر tree مرة أخرى من المجلّد node<em>project لعرض بنية المشروع في هذه المرحلة. هذه المرة، ومن أجل الإيجاز، سنطلب من tree استبعاد المجلّد node</em>modules عبر الراية ‎-I:
</p>

<pre class="ipsCode">
tree -I node_modules
</pre>

<p>
	مع الإضافات التي أجريتها، ستبدو بنية مشروعك على النحو التالي:
</p>

<pre class="ipsCode">
├── Dockerfile
├── README.md
├── app.js
├── controllers
│   └── sharks.js
├── db.js
├── models
│   └── sharks.js
├── package-lock.json
├── package.json
└── views
    ├── css
    │   └── styles.css
    ├── index.html
    └── sharks.html
</pre>

<p>
	الآن بعد أن أصبحت لديك وحدة تحكم لتوجيه كيفية حفظ مدخلات المستخدم وإعادتها إليه، يمكنك الانتقال إلى إنشاء طرق العرض التي ستبلور منطق وحدة التحكم الخاصة بك.
</p>

<h2>
	الخطوة الخامسة: استخدام برمجيات EJS و Express الوسيطة لجمع البيانات وعرضها
</h2>

<p>
	من أجل تمكين التطبيق من العمل ببيانات المستخدم، سنقوم بأمرين مهمّين: سنضمّن أولاً دالة وسيطة Express تسمى ()urlencoded، والتي ستمكن تطبيقنا من تحليل بيانات المستخدم المُدخلَة. ثم سنضيف ثانيا علامات القوالب (template tags) إلى واجهة العرض views لتمكين التفاعل الديناميكي مع بيانات المستخدم في الشيفرة.
</p>

<p>
	من أجل استخدام الدالة <code>()urlencoded</code> الخاصة بـ Express، افتح أولاً الملف app.js:
</p>

<pre class="ipsCode">
nano app.js
</pre>

<p>
	أضف السطر التالي فوق الدالة <code>()express.static</code> في الملف <code>‎~/node_project/app.js</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_40" style="">
<span class="pun">...</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="pln">express</span><span class="pun">.</span><span class="pln">urlencoded</span><span class="pun">({</span><span class="pln"> extended</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">}));</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="pln">express</span><span class="pun">.</span><span class="kwd">static</span><span class="pun">(</span><span class="pln">path</span><span class="pun">));</span><span class="pln">
</span><span class="pun">...</span></pre>

<p>
	ستمكّن إضافة هذه الدّالة الوصول إلى بيانات POST المحلّلة (parsed) في استمارة معلومات سمك القرش. نحدّد القيمة true في الخيار extended لإتاحة قدر أكبر من المرونة في نوع البيانات التي سيحللها التطبيق (بما في ذلك الكائنات مثل الكائنات المتداخلة). يرجى الاطلاع على <a href="https://expressjs.com/en/4x/api.html#express.urlencoded" rel="external nofollow">توثيق الدّالة</a> لمزيد من المعلومات حول الخيارات.
</p>

<p>
	احفظ الملف وأغلقه عند الانتهاء من التحرير.
</p>

<p>
	بعد ذلك، سنضيف إمكانية استخدام القالب إلى واجهات العرض. ثبّت أولاً <a href="https://www.npmjs.com/package/ejs" rel="external nofollow">حزمة ejs</a> باستخدام instaill npm:
</p>

<pre class="ipsCode">
npm install ejs
</pre>

<p>
	بعد ذلك ، افتح ملف sharks.html في المجلد views:
</p>

<pre class="ipsCode">
nano views/sharks.html
</pre>

<p>
	لقد ألقينا نظرة من قبل في الخطوة الثالثة على هذه الصفحة لتحديد كيفية كتابة المخطط والنموذج Mongoose:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33617" href="https://academy.hsoub.com/uploads/monthly_2020_02/sharko.png.a1ff9810f7044afd0ddbf6f390105382.png" rel=""><img alt="sharko.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33617" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_02/sharko.thumb.png.c271691d3ffe4b38c84d795b6504f228.png"></a>
</p>

<p>
	الآن ، بدلاً من وجود تنسيق بعمودين، سنضيف عمودًا ثالثًا يحتوي على استمارة يمكن للمستخدمين إدخال معلومات حول أسماك القرش فيها.
</p>

<p>
	كخطوة أولى، عدّل أبعاد الأعمدة الموجودة إلى 4 لإنشاء ثلاثة أعمدة متساوية الحجم. لاحظ أنك ستحتاج إلى إجراء هذا التعديل على السطرين اللذين يقرآن حاليًا <code>&lt;div class="col-lg-6"‎&gt;</code>. سيصبح كلاهما <code>&lt;div class="col-lg-4"‎&gt;</code>: الملف <code>‎~/node_project/views/sharks.html</code>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2968_42" style="">
<span class="pln">...
</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"row"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-4"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;p&gt;</span><span class="pln">
                </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"caption"</span><span class="tag">&gt;</span><span class="pln">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.
                </span><span class="tag">&lt;/div&gt;</span><span class="pln">
                </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"Sawshark"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-4"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;p&gt;</span><span class="pln">
                </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"caption"</span><span class="tag">&gt;</span><span class="pln">Other sharks are known to be friendly and welcoming!</span><span class="tag">&lt;/div&gt;</span><span class="pln">
                </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://assets.digitalocean.com/articles/docker_node_image/sammy.png"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"Sammy the Shark"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;/div&gt;</span><span class="pln">

 </span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	للاطلاع على توضيح أكثر لنظام الشبكة في Bootstrap، بما في ذلك تخطيطات الصفوف والأعمدة، يرجى الاطلاع على هذه <a href="https://wiki.hsoub.com/Bootstrap" rel="external">المقدمة إلى إطار Bootstrap</a>.
</p>

<p>
	بعد ذلك، أضف عمودًا آخر يتضمن نقطة النهاية المحددة للطلب POST مع بيانات المستخدم عن سمك القرش ووسوم القالب EJS التي ستلتقط تلك البيانات. سيكون هذا العمود أسفل وسمي الإغلاق <code>&lt;‎/p&gt;</code> و <code>&lt;‎/div&gt;</code> للعمود السابق وفوق وسوم الإغلاق للصف والحاوية والصفحة HTML. وتوجد وسوم الإغلاق هذه بالفعل في الشّيفرة. اتركها في مكانها وأنت تضيف الشيفرة التالية لإنشاء العمود الجديد:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2968_44" style="">
<span class="pln">...
       </span><span class="tag">&lt;/p&gt;</span><span class="pln"> </span><span class="com">&lt;!-- closing p from previous column --&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln"> </span><span class="com">&lt;!-- closing div from previous column --&gt;</span><span class="pln">
</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-4"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;p&gt;</span><span class="pln">
                </span><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">action</span><span class="pun">=</span><span class="atv">"/sharks/addshark"</span><span class="pln"> </span><span class="atn">method</span><span class="pun">=</span><span class="atv">"post"</span><span class="tag">&gt;</span><span class="pln">
                    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"caption"</span><span class="tag">&gt;</span><span class="pln">Enter Your Shark</span><span class="tag">&lt;/div&gt;</span><span class="pln">
                    &lt;input type="text" placeholder="Shark Name" name="name" </span><span class="pun">&lt;%=</span><span class="pln">sharks</span><span class="pun">[</span><span class="pln">i</span><span class="pun">].</span><span class="pln">name</span><span class="pun">;</span><span class="pln"> %&gt;
                    &lt;input type="text" placeholder="Shark Character" name="character" </span><span class="pun">&lt;%=</span><span class="pln">sharks</span><span class="pun">[</span><span class="pln">i</span><span class="pun">].</span><span class="pln">character</span><span class="pun">;</span><span class="pln"> %&gt;
                    </span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="tag">&gt;</span><span class="pln">Submit</span><span class="tag">&lt;/button&gt;</span><span class="pln">
                </span><span class="tag">&lt;/form&gt;</span><span class="pln">
            </span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln"> 
    </span><span class="tag">&lt;/div&gt;</span><span class="pln"> </span><span class="com">&lt;!-- closing div for row --&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span><span class="pln"> </span><span class="com">&lt;!-- closing div for container --&gt;</span><span class="pln">

</span><span class="tag">&lt;/html&gt;</span><span class="pln"> </span><span class="com">&lt;!-- closing html tag --&gt;</span></pre>

<p>
	تضيف هنا في الوسم form نقطة نهاية "‎/sharks/addhark" لبيانات سمك القرش الخاصة بالمستخدم وتحدّد الطريقة POST لإرسالها. كما تحدّد في حقول الإدخال، الحقلين "Shark Name" و"Shark Character" ، وفقًا للنموذج Shark الذي حدّدته سابقًا.
</p>

<p>
	لإضافة مُدخلات المستخدم إلى المجموعة sharks، فأنت تستخدم وسوم قالب:EJS (&lt;%=, %&gt;) بناءً على قواعد لغة جافاسكربت لتوجيه مدخلات المستخدم إلى الحقول المناسبة في المستند الذي أنشئ حديثًا. لمزيد من المعلومات حول كائنات جافاسكربت، يرجى مراجعة <a href="https://wiki.hsoub.com/JavaScript" rel="external">توثيق جافاسكربت في الموسوعة</a>. ولمعرفة المزيد عن وسوم قالبEJS ، يرجى الاطلاع على <a href="https://ejs.co/#docs" rel="external nofollow">التوثيق الرسمي لEJS</a>.
</p>

<p>
	ستبدو الحاوية بأكملها مع جميع الأعمدة الثلاثة، بما في ذلك العمود الذي يحتوي على استمارة إدخال سمك القرش، على هذا النحو عند الانتهاء: الملف <code>‎~/node_project/views/sharks.html</code>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2968_46" style="">
<span class="pln">...
</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"row"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-4"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;p&gt;</span><span class="pln">
                </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"caption"</span><span class="tag">&gt;</span><span class="pln">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.
                </span><span class="tag">&lt;/div&gt;</span><span class="pln">
                </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"Sawshark"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-4"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;p&gt;</span><span class="pln">
                </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"caption"</span><span class="tag">&gt;</span><span class="pln">Other sharks are known to be friendly and welcoming!</span><span class="tag">&lt;/div&gt;</span><span class="pln">
                </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://assets.digitalocean.com/articles/docker_node_image/sammy.png"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"Sammy the Shark"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-4"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;p&gt;</span><span class="pln">
                </span><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">action</span><span class="pun">=</span><span class="atv">"/sharks/addshark"</span><span class="pln"> </span><span class="atn">method</span><span class="pun">=</span><span class="atv">"post"</span><span class="tag">&gt;</span><span class="pln">
                    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"caption"</span><span class="tag">&gt;</span><span class="pln">Enter Your Shark</span><span class="tag">&lt;/div&gt;</span><span class="pln">
                    &lt;input type="text" placeholder="Shark Name" name="name" </span><span class="pun">&lt;%=</span><span class="pln">sharks</span><span class="pun">[</span><span class="pln">i</span><span class="pun">].</span><span class="pln">name</span><span class="pun">;</span><span class="pln"> %&gt;
                    &lt;input type="text" placeholder="Shark Character" name="character" </span><span class="pun">&lt;%=</span><span class="pln">sharks</span><span class="pun">[</span><span class="pln">i</span><span class="pun">].</span><span class="pln">character</span><span class="pun">;</span><span class="pln"> %&gt;
                    </span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="tag">&gt;</span><span class="pln">Submit</span><span class="tag">&lt;/button&gt;</span><span class="pln">
                </span><span class="tag">&lt;/form&gt;</span><span class="pln">
            </span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;/div&gt;</span><span class="pln">

</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	احفظ الملف وأغلقه عند الانتهاء من التحرير.
</p>

<p>
	الآن بعد أن أصبح لديك طريقة لجمع مدخلات المستخدم، يمكنك إنشاء نقطة نهاية (endpoint) لعرض أسماك القرش المُعادة وكذلك معلومات السلوك المرتبطة بها.
</p>

<p>
	انسخ ملف sharks.html المعدّل حديثًا إلى ملف يسمى getshark.html:
</p>

<pre class="ipsCode">
cp views/sharks.html views/getshark.html
</pre>

<p>
	افتح الملف getshark.html:
</p>

<pre class="ipsCode">
nano views/getshark.html
</pre>

<p>
	داخل الملف، سنعدّل العمود الذي استخدمناه لإنشاء استمارة إدخال أسماك القرش من خلال استبداله بعمود سيعرض أسماك القرش في المجموعة sharks. مرة أخرى، ستمتدّ الشفرة بين وسمي <code>&lt;p/&gt;</code> و <code>&lt;‎/div&gt;</code> للعمود السابق ووسوم الإغلاق للصف والحاوية والصفحة HTML. احرص على ترك هذه الوسوم في مكانها وأنت تضيف الشيفرة التالية لإنشاء العمود:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2968_48" style="">
<span class="pln">...
       </span><span class="tag">&lt;/p&gt;</span><span class="pln"> </span><span class="com">&lt;!-- closing p from previous column --&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln"> </span><span class="com">&lt;!-- closing div from previous column --&gt;</span><span class="pln">
</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-4"</span><span class="tag">&gt;</span><span class="pln">
           </span><span class="tag">&lt;p&gt;</span><span class="pln">
              </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"caption"</span><span class="tag">&gt;</span><span class="pln">Your Sharks</span><span class="tag">&lt;/div&gt;</span><span class="pln">
                  </span><span class="tag">&lt;ul&gt;</span><span class="pln">
                     </span><span class="pun">&lt;%</span><span class="pln"> sharks</span><span class="pun">.</span><span class="pln">forEach</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">shark</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> %&gt;
                        </span><span class="tag">&lt;p&gt;</span><span class="pln">Name: </span><span class="pun">&lt;%=</span><span class="pln"> shark</span><span class="pun">.</span><span class="pln">name %&gt;</span><span class="tag">&lt;/p&gt;</span><span class="pln">
                        </span><span class="tag">&lt;p&gt;</span><span class="pln">Character: </span><span class="pun">&lt;%=</span><span class="pln"> shark</span><span class="pun">.</span><span class="pln">character %&gt;</span><span class="tag">&lt;/p&gt;</span><span class="pln">
                     </span><span class="pun">&lt;%</span><span class="pln"> </span><span class="pun">});</span><span class="pln"> %&gt;
                  </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
            </span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;/div&gt;</span><span class="pln"> </span><span class="com">&lt;!-- closing div for row --&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span><span class="pln"> </span><span class="com">&lt;!-- closing div for container --&gt;</span><span class="pln">

</span><span class="tag">&lt;/html&gt;</span><span class="pln"> </span><span class="com">&lt;!-- closing html tag --&gt;</span></pre>

<p>
	هنا تستخدم وسوم قالب EJS والدالّة <code>forEach()‎</code> لإخراج كل قيمة في المجموعة sharks ، بما في ذلك معلومات حول أحدث أسماك القرش المضافة.
</p>

<p>
	ستبدو الحاوية بأكملها التي تحتوي على جميع الأعمدة الثلاثة، بما في ذلك العمود الذي يتضمن المجموعة sharks، على هذا النحو عند الانتهاء:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2968_50" style="">
<span class="pln">...
</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"row"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-4"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;p&gt;</span><span class="pln">
                </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"caption"</span><span class="tag">&gt;</span><span class="pln">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.
                </span><span class="tag">&lt;/div&gt;</span><span class="pln">
                </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"Sawshark"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-4"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;p&gt;</span><span class="pln">
                </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"caption"</span><span class="tag">&gt;</span><span class="pln">Other sharks are known to be friendly and welcoming!</span><span class="tag">&lt;/div&gt;</span><span class="pln">
                </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://assets.digitalocean.com/articles/docker_node_image/sammy.png"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"Sammy the Shark"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-4"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;p&gt;</span><span class="pln">
              </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"caption"</span><span class="tag">&gt;</span><span class="pln">Your Sharks</span><span class="tag">&lt;/div&gt;</span><span class="pln">
                  </span><span class="tag">&lt;ul&gt;</span><span class="pln">
                     </span><span class="pun">&lt;%</span><span class="pln"> sharks</span><span class="pun">.</span><span class="pln">forEach</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">shark</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> %&gt;
                        </span><span class="tag">&lt;p&gt;</span><span class="pln">Name: </span><span class="pun">&lt;%=</span><span class="pln"> shark</span><span class="pun">.</span><span class="pln">name %&gt;</span><span class="tag">&lt;/p&gt;</span><span class="pln">
                        </span><span class="tag">&lt;p&gt;</span><span class="pln">Character: </span><span class="pun">&lt;%=</span><span class="pln"> shark</span><span class="pun">.</span><span class="pln">character %&gt;</span><span class="tag">&lt;/p&gt;</span><span class="pln">
                     </span><span class="pun">&lt;%</span><span class="pln"> </span><span class="pun">});</span><span class="pln"> %&gt;
                  </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
            </span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;/div&gt;</span><span class="pln">

</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	احفظ الملف وأغلقه عند الانتهاء من التحرير.
</p>

<p>
	لكي يستخدم التطبيق القوالب التي أنشأتها، ستحتاج إلى إضافة بضعة أسطر إلى ملفّك app.js. لذا افتحه مرة أخرى:
</p>

<pre class="ipsCode">
nano app.js
</pre>

<p>
	فوق المكان الذي أضفت فيه الدالة <code>express.urlencoded()‎</code>، أضف الآن الأسطر التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_52" style="">
<span class="pun">...</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">engine</span><span class="pun">(</span><span class="str">'html'</span><span class="pun">,</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'ejs'</span><span class="pun">).</span><span class="pln">renderFile</span><span class="pun">);</span><span class="pln">
app</span><span class="pun">.</span><span class="kwd">set</span><span class="pun">(</span><span class="str">'view engine'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'html'</span><span class="pun">);</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="pln">express</span><span class="pun">.</span><span class="pln">urlencoded</span><span class="pun">({</span><span class="pln"> extended</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">}));</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="pln">express</span><span class="pun">.</span><span class="kwd">static</span><span class="pun">(</span><span class="pln">path</span><span class="pun">));</span><span class="pln">

</span><span class="pun">...</span></pre>

<p>
	تطلب الدّالة app.engine من التطبيق توجيه محرك قوالب EJS إلى ملفات HTML، بينما تحدّد app.set محرك العرض الافتراضي.
</p>

<p>
	يجب أن يبدو ملف app.js الآن على النحو التالي:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/app.js</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_54" style="">
<span class="kwd">const</span><span class="pln"> express </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'express'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> app </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> router </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">.</span><span class="typ">Router</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> db </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'./db'</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> path </span><span class="pun">=</span><span class="pln"> __dirname </span><span class="pun">+</span><span class="pln"> </span><span class="str">'/views/'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> port </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8080</span><span class="pun">;</span><span class="pln">

router</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">,</span><span class="pln">next</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'/'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> req</span><span class="pun">.</span><span class="pln">method</span><span class="pun">);</span><span class="pln">
  next</span><span class="pun">();</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

router</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">){</span><span class="pln">
  res</span><span class="pun">.</span><span class="pln">sendFile</span><span class="pun">(</span><span class="pln">path </span><span class="pun">+</span><span class="pln"> </span><span class="str">'index.html'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

router</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/sharks'</span><span class="pun">,</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">){</span><span class="pln">
  res</span><span class="pun">.</span><span class="pln">sendFile</span><span class="pun">(</span><span class="pln">path </span><span class="pun">+</span><span class="pln"> </span><span class="str">'sharks.html'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

app</span><span class="pun">.</span><span class="pln">engine</span><span class="pun">(</span><span class="str">'html'</span><span class="pun">,</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'ejs'</span><span class="pun">).</span><span class="pln">renderFile</span><span class="pun">);</span><span class="pln">
app</span><span class="pun">.</span><span class="kwd">set</span><span class="pun">(</span><span class="str">'view engine'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'html'</span><span class="pun">);</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="pln">express</span><span class="pun">.</span><span class="pln">urlencoded</span><span class="pun">({</span><span class="pln"> extended</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">}));</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="pln">express</span><span class="pun">.</span><span class="kwd">static</span><span class="pun">(</span><span class="pln">path</span><span class="pun">));</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> router</span><span class="pun">);</span><span class="pln">

app</span><span class="pun">.</span><span class="pln">listen</span><span class="pun">(</span><span class="pln">port</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'Example app listening on port 8080!'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	الآن وبعد أن أنشأت واجهات عرض يمكن أن تعمل ديناميكيًا مع بيانات المستخدم، فقد حان الوقت لإنشاء المسارات لمشروعك من أجل الجمع بين واجهات العرض ومنطق وحدة التحكم الذي تعمل به.
</p>

<h2>
	الخطوة السادسة: إنشاء المسارات (routes)
</h2>

<p>
	الخطوة الأخيرة في الجمع بين مكونات التطبيق هي إنشاء المسارات. سنحاول فصل المسارات حسب وظيفتها، بما في ذلك المسار إلى صفحة الهبوط لتطبيقنا ومسار آخر إلى صفحة أسماك القرش. سيكون المسار sharks هو المكان الذي ندمج فيه منطق وحدة التحكم مع واجهات العرض التي أنشأناها في الخطوة السابقة.
</p>

<p>
	أنشئ في البداية مجلّدًا باسم routes:
</p>

<pre class="ipsCode">
mkdir routes
</pre>

<p>
	بعد ذلك، أنشئ ملفًا يسمى index.js في هذا المجلّد وافتحه:
</p>

<pre class="ipsCode">
nano routes/index.js
</pre>

<p>
	سيستورد هذا الملف في البداية كائنات express وrouter وpath، مما يتيح لنا تحديد المسارات التي نريد تصديرها باستخدام الكائن router، وهذا يتيح بدوره العمل ديناميكيًا بمسارات الملفات (file paths). أضف الشيفرة التالية في أعلى الملف:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/routes/index.js</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_56" style="">
<span class="kwd">const</span><span class="pln"> express </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'express'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> router </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">.</span><span class="typ">Router</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> path </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'path'</span><span class="pun">);</span></pre>

<p>
	بعد ذلك، أضف الدّالة router.use التالية، والتي تُحمّل الدالّة الوسيطة التي ستسجل طلبات الموجه وتمررها إلى مسار التطبيق:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_58" style="">
<span class="pun">...</span><span class="pln">

router</span><span class="pun">.</span><span class="pln">use </span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">,</span><span class="pln">next</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'/'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> req</span><span class="pun">.</span><span class="pln">method</span><span class="pun">);</span><span class="pln">
  next</span><span class="pun">();</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	ستُوجَّه الطلبات الخاصّة بجذر التطبيق إلى هنا في البداية، ومن ثم سيُوجّه المستخدمون إلى صفحة الهبوط لتطبيقنا، وهو المسار الذي سنحدّده بعد ذلك. أضف الشيفرة التالية أسفل الدّالة router.use لتحديد المسار نحو صفحة الهبوط:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_60" style="">
<span class="pun">...</span><span class="pln">

router</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">){</span><span class="pln">
  res</span><span class="pun">.</span><span class="pln">sendFile</span><span class="pun">(</span><span class="pln">path</span><span class="pun">.</span><span class="pln">resolve</span><span class="pun">(</span><span class="str">'views/index.html'</span><span class="pun">));</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	إن أول ما نريد إرساله إليه المستخدم عندما يزور التطبيق هو صفحة الهبوط index.html الموجودة في المجلّد views.
</p>

<p>
	ختامًا، لجعل هذه المسارات قابلة للوصول كوحدات يمكن استيرادها في مكان آخر من التطبيق، أضف عبارة ختامية إلى نهاية الملف لتصدير الكائن router:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_62" style="">
<span class="pun">...</span><span class="pln">

module</span><span class="pun">.</span><span class="pln">exports </span><span class="pun">=</span><span class="pln"> router</span><span class="pun">;</span></pre>

<p>
	سوف يبدو الملف النهائي على هذا النحو:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_64" style="">
<span class="kwd">const</span><span class="pln"> express </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'express'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> router </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">.</span><span class="typ">Router</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> path </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'path'</span><span class="pun">);</span><span class="pln">

router</span><span class="pun">.</span><span class="pln">use </span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">,</span><span class="pln">next</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'/'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> req</span><span class="pun">.</span><span class="pln">method</span><span class="pun">);</span><span class="pln">
  next</span><span class="pun">();</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

router</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">){</span><span class="pln">
  res</span><span class="pun">.</span><span class="pln">sendFile</span><span class="pun">(</span><span class="pln">path</span><span class="pun">.</span><span class="pln">resolve</span><span class="pun">(</span><span class="str">'views/index.html'</span><span class="pun">));</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

module</span><span class="pun">.</span><span class="pln">exports </span><span class="pun">=</span><span class="pln"> router</span><span class="pun">;</span></pre>

<p>
	احفظ هذا الملف وأغلقه عندما تنتهي من التحرير.
</p>

<p>
	بعد ذلك، افتح ملفًا باسم sharks.js لتحديد كيفية استخدام التطبيق لنقاط النهاية وواجهات العرض المختلفة التي أنشأناها للتعامل مع مدخلات المستخدم لأسماك القرش:
</p>

<pre class="ipsCode">
nano routes/sharks.js
</pre>

<p>
	في الجزء العلوي من الملف، استورد الكائنات epress وrouter:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_66" style="">
<span class="kwd">const</span><span class="pln"> express </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'express'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> router </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">.</span><span class="typ">Router</span><span class="pun">();</span></pre>

<p>
	بعد ذلك، استورد وحدة نمطية تسمى shark لتتيح لك العمل بالدّوال المصدرة التي حددتها في وحدة التحكم:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_68" style="">
<span class="kwd">const</span><span class="pln"> express </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'express'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> router </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">.</span><span class="typ">Router</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> shark </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'../controllers/sharks'</span><span class="pun">);</span></pre>

<p>
	يمكنك الآن إنشاء مسارات باستخدام الدّوال index وcreate وlist التي حدّدتها في ملف وحدة التحكم sharks. سيُربط كل مسار بطريقة HTTP المناسبة والتي تكون إما GET في حالة عرض صفحة الهبوط لمعلومات أسماك القرش الرئيسية وإعادة قائمة أسماك القرش إلى المستخدم، وإما POST في حالة إنشاء إدخال جديد لسمك قرش:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_70" style="">
<span class="pun">...</span><span class="pln">

router</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">){</span><span class="pln">
    shark</span><span class="pun">.</span><span class="pln">index</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

router</span><span class="pun">.</span><span class="pln">post</span><span class="pun">(</span><span class="str">'/addshark'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    shark</span><span class="pun">.</span><span class="pln">create</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

router</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/getshark'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    shark</span><span class="pun">.</span><span class="pln">list</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	يستخدم كل مسار الدّالة المرتبطة به في controllers/sharks.js، لأننا جعلنا هذه الوحدة قابلة للوصول عن طريق استيرادها في الجزء العلوي من هذا الملف.
</p>

<p>
	ختامًا، أغلق الملف بربط هذه المسارات بالكائن routes وتصديرها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_72" style="">
<span class="pun">...</span><span class="pln">

module</span><span class="pun">.</span><span class="pln">exports </span><span class="pun">=</span><span class="pln"> router</span><span class="pun">;</span></pre>

<p>
	سيبدو الملف النهائي على هذا النحو:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_74" style="">
<span class="kwd">const</span><span class="pln"> express </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'express'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> router </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">.</span><span class="typ">Router</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> shark </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'../controllers/sharks'</span><span class="pun">);</span><span class="pln">

router</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">){</span><span class="pln">
    shark</span><span class="pun">.</span><span class="pln">index</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

router</span><span class="pun">.</span><span class="pln">post</span><span class="pun">(</span><span class="str">'/addshark'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    shark</span><span class="pun">.</span><span class="pln">create</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

router</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/getshark'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    shark</span><span class="pun">.</span><span class="pln">list</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

module</span><span class="pun">.</span><span class="pln">exports </span><span class="pun">=</span><span class="pln"> router</span><span class="pun">;</span></pre>

<p>
	احفظ الملف وأغلقه عند الانتهاء من التحرير.
</p>

<p>
	ستكون الخطوة الأخيرة في جعل هذه المسارات متاحةً للتطبيق هي إضافتها إلى app.js. افتح هذا الملف مرة أخرى:
</p>

<pre class="ipsCode">
nano app.js
</pre>

<p>
	أسفل الثابتة db، أضف الاستيراد التالي لمساراتك:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_76" style="">
<span class="pun">...</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> db </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'./db'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> sharks </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'./routes/sharks'</span><span class="pun">);</span></pre>

<p>
	بعد ذلك، عوّض الدّالة <code>app.use</code> التي تُركّب الكائن <code>router</code> بالسطر التالي الذي سيركّب وحدة التوجيه <code>sharks</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_78" style="">
<span class="pun">...</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="pln">express</span><span class="pun">.</span><span class="kwd">static</span><span class="pun">(</span><span class="pln">path</span><span class="pun">));</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="str">'/sharks'</span><span class="pun">,</span><span class="pln"> sharks</span><span class="pun">);</span><span class="pln">

app</span><span class="pun">.</span><span class="pln">listen</span><span class="pun">(</span><span class="pln">port</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Example app listening on port 8080!"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	تستطيع الآن حذف المسارات التي حدّدتها مسبقًا في هذا الملف، نظرًا لأنك تستورد مسارات تطبيقك باستخدام وحدة التوجيه <code>sharks</code>.
</p>

<p>
	ستبدو النسخة النهائية للملف app.js على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_80" style="">
<span class="kwd">const</span><span class="pln"> express </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'express'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> app </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> router </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">.</span><span class="typ">Router</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> db </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'./db'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> sharks </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'./routes/sharks'</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> path </span><span class="pun">=</span><span class="pln"> __dirname </span><span class="pun">+</span><span class="pln"> </span><span class="str">'/views/'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> port </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8080</span><span class="pun">;</span><span class="pln">

app</span><span class="pun">.</span><span class="pln">engine</span><span class="pun">(</span><span class="str">'html'</span><span class="pun">,</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'ejs'</span><span class="pun">).</span><span class="pln">renderFile</span><span class="pun">);</span><span class="pln">
app</span><span class="pun">.</span><span class="kwd">set</span><span class="pun">(</span><span class="str">'view engine'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'html'</span><span class="pun">);</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="pln">express</span><span class="pun">.</span><span class="pln">urlencoded</span><span class="pun">({</span><span class="pln"> extended</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">}));</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="pln">express</span><span class="pun">.</span><span class="kwd">static</span><span class="pun">(</span><span class="pln">path</span><span class="pun">));</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="str">'/sharks'</span><span class="pun">,</span><span class="pln"> sharks</span><span class="pun">);</span><span class="pln">

app</span><span class="pun">.</span><span class="pln">listen</span><span class="pun">(</span><span class="pln">port</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'Example app listening on port 8080!'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	احفظ الملف وأغلقه عند الانتهاء من التحرير.
</p>

<p>
	يمكنك الآن إعادة تنفيذ الأمر tree مرة أخرى لرؤية البنية النهائية لمشروعك:
</p>

<pre class="ipsCode">
tree -I node_modules
</pre>

<p>
	ستبدو بنية مشروعك الآن على هذا النحو:
</p>

<pre class="ipsCode">
├── Dockerfile
├── README.md
├── app.js
├── controllers
│   └── sharks.js
├── db.js
├── models
│   └── sharks.js
├── package-lock.json
├── package.json
├── routes
│   ├── index.js
│   └── sharks.js
└── views
    ├── css
    │   └── styles.css
    ├── getshark.html
    ├── index.html
    └── sharks.html
</pre>

<p>
	بإنشائك لجميع مكونات تطبيقك ووضعها في المكان المناسب، فأنت الآن مستعدّ لإضافة سمك قرش للاختبار إلى قاعدة بياناتك!
</p>

<p>
	إذا تتبعت درس إعداد الخادم الأولي في المتطلبات الأساسية، فستحتاج إلى تعديل جدار الحماية الخاص بك، لأنه لا يسمح حاليًا سوى بحركة المرور <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr>. لذا نفّذ هذا الأمر من أجل السماح بحركة المرور إلى منفذ 8080:
</p>

<pre class="ipsCode">
sudo ufw allow 8080
</pre>

<p>
	شغّل التطبيق:
</p>

<pre class="ipsCode">
node app.js
</pre>

<p>
	بعد ذلك، انتقل بمتصفّحك إلى http://your<em>server</em>ip:8080. ستظهر لك صفحة الهبوط التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33612" href="https://academy.hsoub.com/uploads/monthly_2020_02/landing_pages.png.27f95f9549559e854597b3185cc3cf8e.png" rel=""><img alt="landing_pages.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33612" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_02/landing_pages.thumb.png.2518587deb042f62bae496b6e4b923e9.png"></a>
</p>

<p>
	انقر على زر الحصول على معلومات القرش. ستظهر لك صفحة المعلومات التالية، مع استمارة إدخال سمك القرش المضافة:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33615" href="https://academy.hsoub.com/uploads/monthly_2020_02/shark_form.png.49977f3316c2197c2bd586fa83850997.png" rel=""><img alt="shark_form.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33615" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_02/shark_form.thumb.png.546a20883cafb89882b52433052e86e8.png"></a>
</p>

<p>
	أضف في الاستمارة، سمكة قرش من اختيارك. لأغراض هذا العرض التوضيحي، سنضيف Megalodon Shark إلى حقل اسم القرش، وAncient إلى حقل سلوك القرش:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33614" href="https://academy.hsoub.com/uploads/monthly_2020_02/shark_filled.png.2a3b4e296db853d5d8acf17f025317a0.png" rel=""><img alt="shark_filled.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33614" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_02/shark_filled.thumb.png.2d2115c76e37e6328d6b5cbc7eba6feb.png"></a>
</p>

<p>
	انقر على زر الإرسال. ستظهر لك صفحة بها معلومات القرش معروضة لك:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33613" href="https://academy.hsoub.com/uploads/monthly_2020_02/shark_added.png.34746f17cf2306be59c6004c617f5049.png" rel=""><img alt="shark_added.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33613" data-unique="4qcjxoj51" src="https://academy.hsoub.com/uploads/monthly_2020_02/shark_added.thumb.png.754592f15632ec446b561ba5df68537c.png"></a>
</p>

<p>
	سترى أيضًا مخرجاتٍ في وحدة التحكم الخاصة بك تشير إلى أنّ سمك القرش أضيف إلى مجموعتك:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2968_84" style="">
<span class="typ">Example</span><span class="pln"> app listening on port </span><span class="lit">8080</span><span class="pun">!</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Megalodon Shark'</span><span class="pun">,</span><span class="pln"> character</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Ancient'</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	إذا كنت ترغب في إنشاء إدخال جديد لسمك القرش، فارجع إلى صفحة أسماك القرش وكرر عملية إضافة سمكة قرش.
</p>

<p>
	لديك الآن تطبيق لمعلومات سمك القرش يتيح للمستخدمين بإضافة معلومات حول أسماك القرش المفضلة لديهم.
</p>

<h2>
	خاتمة
</h2>

<p>
	لقد أنشأت في هذا البرنامج التعليمي تطبيق Node من خلال دمج قاعدة بيانات MongoDB وإعادة كتابة منطق التطبيق باستخدام النظام الهيكلي MVC. ويمكن أن يكون هذا التطبيق بمثابة نقطة انطلاق جيدة لتطبيق CRUD مكتمل.
</p>

<p>
	لمزيد من التفصيل حول النظام الهيكلي MVC في سياقات أخرى، يرجى الاطلاع على <a href="https://academy.hsoub.com/programming/python/django/" rel="">سلسلة مقالات تطوير Django</a>.
</p>

<p>
	لمزيد من المعلومات حول العمل على MongoDB، يرجى الاطلاع على <a href="https://academy.hsoub.com/devops/servers/databases/mongodb/" rel="">سلسلة المقالات حول MongoDB</a>.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-integrate-mongodb-with-your-node-application" rel="external nofollow">How To Integrate MongoDB with Your Node Application</a> لصاحبته Kathleen Juell
</p>
]]></description><guid isPermaLink="false">810</guid><pubDate>Wed, 05 Feb 2020 06:29:59 +0000</pubDate></item><item><title>&#x628;&#x646;&#x627;&#x621; &#x62A;&#x637;&#x628;&#x64A;&#x642; Node.js &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Docker</title><link>https://academy.hsoub.com/programming/javascript/nodejs/%D8%A8%D9%86%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-nodejs-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-docker-r809/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_02/1.jpg.62e38110da3cb247256672a75732daa6.jpg" /></p>

<p>
	تتيح منصة <a href="https://academy.hsoub.com/devops/cloud-computing/docker/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-docker-r3/" rel="">Docker</a> للمطورين تحزيم وتنفيذ التطبيقات على شكل حاويات (containers). وتعدّ الحاوية عملية (process) منعزلة تعمل على نظام تشغيل مشترك، وتوفر بديلاً أخفّ من الأجهزة الافتراضية (virtual machines) . رغم أن الحاويات ليست جديدة، إلا أن لها فوائد عديدة، من بينها عزل العمليات وتوحيد البيئة، وتزداد أهميتها نظرًا لتزايد إقبال المطورين على استخدام بنية التطبيقات الموزعة.
</p>

<p>
	عند بناء تطبيق وتوسيع نطاقه باستخدام Docker، تكون نقطة البداية عادةً هي إنشاء صورة للتطبيق، والتي يمكنك تنفيذها بعد ذلك في حاوية. تتضمن الصورة شيفرة التطبيق والمكتبات وملفات التكوين ومتغيرات البيئة ووقت التشغيل. ويضمن استخدام صورة ما أن تكون البيئة في حاويتك موحدة ومتضمّنة فقط لما هو ضروري لإنشاء التطبيق وتنفيذه.
</p>

<p>
	ستنشئ في هذا الدرس صورة تطبيق لموقع ويب ثابت يستخدم إطار عمل <a href="https://expressjs.com/" rel="external nofollow">Express</a> و <a href="https://getbootstrap.com" rel="external nofollow">Bootstrap</a>. وستنشئ بعد ذلك حاوية باستخدام تلك الصورة ورفعها إلى Docker Hub للاستخدام المستقبلي. أخيرًا، ستتمكّن من سحب الصورة المخزنة من مستودع <a href="https://hub.docker.com/" rel="external nofollow">Docker Hub</a> الخاص بك وتنشئ حاوية أخرى، مع توضيح كيف يمكنك إعادة إنشاء التطبيق وتوسيع نطاقه.
</p>

<h2>
	المتطلبات الأساسية
</h2>

<p>
	سوف تحتاج من أجل متابعة هذه السلسلة إلى العناصر التالية:
</p>

<ul>
<li>
		خادم Ubuntu 18.04 يمكنك إعداده باتباع <a href="https://academy.hsoub.com/devops/linux/%D8%A7%D9%84%D8%AA%D9%87%D9%8A%D8%A6%D8%A9-%D8%A7%D9%84%D8%A3%D9%88%D9%84%D9%8A%D8%A9-%D9%84%D8%AE%D8%A7%D8%AF%D9%85-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r431/" rel="">دليل إعداد الخادم الأولي</a>.
	</li>
	<li>
		تثبيت Docker على الخادم الخاص بك، باتباع الخطوتين 1 و 2 في دليل <a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04" rel="external nofollow">كيفية تثبيت واستخدام Docker على Ubuntu 18.04</a>.
	</li>
	<li>
		تثبيت Node.js و npm، باتباع هذه <a href="https://academy.hsoub.com/devops/linux/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-nodejs-%D8%B9%D9%84%D9%89-%D9%86%D8%B8%D8%A7%D9%85-%D8%A3%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r419/" rel="">الإرشادات</a> تحديدًا التّثبيت باستخدام أرشيف الحزم الشّخصي PPA المدار بواسطة NodeSource.
	</li>
	<li>
		حساب Docker Hub. لإلقاء نظرة عامة حول كيفية إعداده، راجع هذه <a href="https://docs.docker.com/docker-hub/" rel="external nofollow">المقدمة</a> عن بدء استخدام Docker Hub.
	</li>
</ul>
<h2>
	الخطوة الأولى: تثبيت الاعتماديات لتطبيقك
</h2>

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

<p>
	أنشئ في البداية مجلًدًا لمشروعك في المجلّد الرئيسي للمستخدم غير الجذري. سنستدعي <code>node_project</code> الخاص بنا، لكن يمكنك استبداله بشيء آخر:
</p>

<pre class="ipsCode">
$ mkdir node_project
</pre>

<p>
	انتقل إلى هذا المجلّد:
</p>

<pre class="ipsCode">
$ cd node_project
</pre>

<p>
	سيكون هذا هو المجلّد الرئيسي للمشروع.
</p>

<p>
	أنشئ بعد ذلك ملف <code>[package.json](https://docs.npmjs.com/files/package.json)</code> باعتماديات مشروعك ومعلومات التعريف الأخرى. افتح الملف باستخدام <code>nano</code> أو المحرر المفضل لديك:
</p>

<pre class="ipsCode">
$ nano package.json
</pre>

<p>
	أضف المعلومات التالية حول المشروع، بما في ذلك اسم المشروع وصاحبه والترخيص ونقطة الدخول والاعتماديات. تأكد من استبدال معلومات صاحب المشروع باسمك ومعلومات الاتصال الخاصة بك:
</p>

<ul>
<li>
		الملف ‎:~/node_project/package.json
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6733_6" style="">
<span class="pun">{</span><span class="pln">
  </span><span class="str">"name"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"nodejs-image-demo"</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"version"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"1.0.0"</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"description"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"nodejs image demo"</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"author"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Sammy the Shark &lt;sammy@example.com&gt;"</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"license"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"MIT"</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"main"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"app.js"</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"keywords"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">"nodejs"</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"bootstrap"</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"express"</span><span class="pln">
  </span><span class="pun">],</span><span class="pln">
  </span><span class="str">"dependencies"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="str">"express"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"^4.16.4"</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يحتوي هذا الملف على اسم المشروع وصاحبه والترخيص الذي تتم مشاركته بموجبه. ينصح npm بجعل اسم المشروع قصيرًا وذا دلالة وصفية مع تجنب التكرار في سجل npm. لقد أدرجنا <a href="https://opensource.org/licenses/MIT" rel="external nofollow">ترخيص MIT</a> في حقل الترخيص، مما يتيح الاستخدام المجاني لشيفرة التطبيق وتوزيعه.
</p>

<p>
	بالإضافة إلى ذلك، يحدد الملف العناصر التالية:
</p>

<ul>
<li>
		<code>"main"</code>: نقطة دخول التطبيق <code>app.js</code>، ستقوم بإنشاء هذا الملف بعد ذلك.
	</li>
	<li>
		<code>"dependencies"</code>: اعتماديات المشروع، في هذه الحالة، Express إصدار 4.16.4 أو أعلى منه.
	</li>
</ul>
<p>
	ورغم أن هذا الملف لا يحتوي على مستودعٍ، فيمكنك إضافته باتباع هذه <a href="https://docs.npmjs.com/files/package.json#repository" rel="external nofollow">الإرشادات</a> حول إضافة مستودع إلى ملف <code>package.json</code> الخاص بك. وتعدّ هذه إضافةً جيدةً إذا كنت تقوم بإصدار تطبيقك.
</p>

<p>
	احفظ الملف وأغلقه عندما تنتهي من إجراء التعديلات.
</p>

<p>
	لتثبيت اعتماديات مشروعك، نفّذ الأمر التالي:
</p>

<pre class="ipsCode">
$ npm install
</pre>

<p>
	سيؤدي ذلك إلى تثبيت الحزم التي أدرجتها في ملف <code>package.json</code> في مجلّد المشروع الخاص بك.
</p>

<p>
	يمكننا الآن الانتقال إلى بناء ملفات التطبيق.
</p>

<h2>
	الخطوة الثانية: إنشاء ملفات التطبيق
</h2>

<p>
	سنعمل على إنشاء موقع ويب يقدم للمستخدمين معلومات حول أسماك القرش. سيكون لدى لتطبيق نقطة دخول رئيسية و ملفّ <code>app.js</code> ومجلّد <code>views</code> يتضمن الأصول الثابتة للمشروع. ستوفر صفحة الهبوط <code>index.html</code> للمستخدمين بعض المعلومات الأولية ورابطًا نحو صفحة تحتوي على معلومات أكثر تفصيلًا عن أسماك القرش، <code>sharks.html</code>. سننشئ في مجلّد <code>views</code> كلًّا من صفحة الهبوط و الصفحة <code>sharks.html</code>.
</p>

<p>
	في البداية، افتح ملفّ <code>app.js</code> في مجلّد المشروع الرئيسي لتحديد مسارات المشروع:
</p>

<pre class="ipsCode">
$ nano app.js
</pre>

<p>
	سيعمل الجزء الأول من الملف على إنشاء تطبيق Express وكائنات الموجِّه، وتحديد المجلّد الأساسي والمنفذ كثوابت:
</p>

<ul>
<li>
		الملف ‎:~/node_project/app.js
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6733_8" style="">
<span class="kwd">const</span><span class="pln"> express </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'express'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> app </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> router </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">.</span><span class="typ">Router</span><span class="pun">();</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> path </span><span class="pun">=</span><span class="pln"> __dirname </span><span class="pun">+</span><span class="pln"> </span><span class="str">'/views/'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> port </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8080</span><span class="pun">;</span></pre>

<p>
	تحمّل الداّلة <code>require</code> الوحدة <code>express</code> التي نستخدمها فيما بعد لإنشاء الكائنات <code>app</code> و <code>router</code>. سيؤدي الكائن <code>router</code> وظيفة التوجيه الخاصة بالتطبيق، وعندما نحدد مسارات طرق HTTP، سنضيفها إلى هذا الكائن لتحديد كيفية تعامل التطبيق مع الطلبات.
</p>

<p>
	يعين هذا الجزء من الملف أيضًا ثابتتي المسار <code>path</code> والمنفذ <code>port</code>: *<code>path</code>: يحدد المجلّد الأساسي، والذي سيكون المجلّد الفرعي ل <code>views</code> داخل مجلّد المشروع الحالي.
</p>

<ul>
<li>
		<code>port</code>: يطلب من التطبيق الاستماع على المنفذ <code>8080</code>.
	</li>
</ul>
<p>
	بعد ذلك، حدّد مسارات التطبيق باستخدام الكائن <code>router</code>:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/app.js</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6733_10" style="">
<span class="pln">router</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">,</span><span class="pln">next</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'/'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> req</span><span class="pun">.</span><span class="pln">method</span><span class="pun">);</span><span class="pln">
  next</span><span class="pun">();</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

router</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">){</span><span class="pln">
  res</span><span class="pun">.</span><span class="pln">sendFile</span><span class="pun">(</span><span class="pln">path </span><span class="pun">+</span><span class="pln"> </span><span class="str">'index.html'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

router</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/sharks'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">){</span><span class="pln">
  res</span><span class="pun">.</span><span class="pln">sendFile</span><span class="pun">(</span><span class="pln">path </span><span class="pun">+</span><span class="pln"> </span><span class="str">'sharks.html'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	تحمّل الدالّة <code>router.use</code> دالّة وسيطة تعمل على تسجيل طلبات الموجه وتمررها إلى مسارات التطبيق. تُحدّد هذه المسارات في الدوالّ الموالية، والتي تنصّ على أن تنفيذ الأمر GET على عنوان URL للمشروع الأساسي يجب أن يُرجع الصفحة <code>index.html</code>، بينما يجب أن يُرجع تنفيذ الأمر GET على المسار <code>sharks/</code> الصفحة <code>sharks.html</code>.
</p>

<p>
	ختامًا، صل بين البرمجية الوسيطة <code>router</code> والأصول الثابتة للتطبيق واجعل التطبيق يستمع على المنفذ <code>8080</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6733_12" style="">
<span class="pun">~</span><span class="str">/node_project/</span><span class="pln">app</span><span class="pun">.</span><span class="pln">js
</span><span class="pun">...</span><span class="pln">

app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="pln">express</span><span class="pun">.</span><span class="kwd">static</span><span class="pun">(</span><span class="pln">path</span><span class="pun">));</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> router</span><span class="pun">);</span><span class="pln">

app</span><span class="pun">.</span><span class="pln">listen</span><span class="pun">(</span><span class="pln">port</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'Example app listening on port 8080!'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	سيبدو ملف <code>app.js</code> النهائي كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6733_14" style="">
<span class="kwd">const</span><span class="pln"> express </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'express'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> app </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> router </span><span class="pun">=</span><span class="pln"> express</span><span class="pun">.</span><span class="typ">Router</span><span class="pun">();</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> path </span><span class="pun">=</span><span class="pln"> __dirname </span><span class="pun">+</span><span class="pln"> </span><span class="str">'/views/'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> port </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8080</span><span class="pun">;</span><span class="pln">

router</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">,</span><span class="pln">next</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'/'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> req</span><span class="pun">.</span><span class="pln">method</span><span class="pun">);</span><span class="pln">
  next</span><span class="pun">();</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

router</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">){</span><span class="pln">
  res</span><span class="pun">.</span><span class="pln">sendFile</span><span class="pun">(</span><span class="pln">path </span><span class="pun">+</span><span class="pln"> </span><span class="str">'index.html'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

router</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/sharks'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln">res</span><span class="pun">){</span><span class="pln">
  res</span><span class="pun">.</span><span class="pln">sendFile</span><span class="pun">(</span><span class="pln">path </span><span class="pun">+</span><span class="pln"> </span><span class="str">'sharks.html'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="pln">express</span><span class="pun">.</span><span class="kwd">static</span><span class="pun">(</span><span class="pln">path</span><span class="pun">));</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">use</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> router</span><span class="pun">);</span><span class="pln">

app</span><span class="pun">.</span><span class="pln">listen</span><span class="pun">(</span><span class="pln">port</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'Example app listening on port 8080!'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	احفظ الملف وأغلقه عند الانتهاء.
</p>

<p>
	بعد ذلك، دعنا نضيف بعض المحتوى الثابت إلى التطبيق. ابدأ بإنشاء المجلد <code>views</code>:
</p>

<pre class="ipsCode">
$ mkdir views
</pre>

<p>
	افتح ملف صفحة الهبوط <code>index.html</code>:
</p>

<pre class="ipsCode">
$ nano views/index.html
</pre>

<p>
	أضف الشيفرة التالية إلى الملف، الذي سيعمل على استيراد Bootstrap وإنشاء مكوّن <a href="https://getbootstrap.com/docs/4.0/components/jumbotron/" rel="external nofollow">jumbotron</a> مع رابط إلى صفحة المعلومات المفصّلة <code>sharks.html</code>:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/views/index.html</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6733_16" style="">
<span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">
</span><span class="tag">&lt;html</span><span class="pln"> </span><span class="atn">lang</span><span class="pun">=</span><span class="atv">"en"</span><span class="tag">&gt;</span><span class="pln">

</span><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="tag">&lt;title&gt;</span><span class="pln">About Sharks</span><span class="tag">&lt;/title&gt;</span><span class="pln">
    </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">charset</span><span class="pun">=</span><span class="atv">"utf-8"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"viewport"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"width=device-width, initial-scale=1"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"</span><span class="pln"> </span><span class="atn">integrity</span><span class="pun">=</span><span class="atv">"sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="pun">=</span><span class="atv">"anonymous"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"css/styles.css"</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"https://fonts.googleapis.com/css?family=Merriweather:400,700"</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text/css"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/head&gt;</span><span class="pln">

</span><span class="tag">&lt;body&gt;</span><span class="pln">
    </span><span class="tag">&lt;nav</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"navbar navbar-dark bg-dark navbar-static-top navbar-expand-md"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"button"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"navbar-toggler collapsed"</span><span class="pln"> </span><span class="atn">data-toggle</span><span class="pun">=</span><span class="atv">"collapse"</span><span class="pln"> </span><span class="atn">data-target</span><span class="pun">=</span><span class="atv">"#bs-example-navbar-collapse-1"</span><span class="pln"> </span><span class="atn">aria-expanded</span><span class="pun">=</span><span class="atv">"false"</span><span class="tag">&gt;</span><span class="pln"> </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"sr-only"</span><span class="tag">&gt;</span><span class="pln">Toggle navigation</span><span class="tag">&lt;/span&gt;</span><span class="pln">
            </span><span class="tag">&lt;/button&gt;</span><span class="pln"> </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"navbar-brand"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"#"</span><span class="tag">&gt;</span><span class="pln">Everything Sharks</span><span class="tag">&lt;/a&gt;</span><span class="pln">
            </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"collapse navbar-collapse"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"bs-example-navbar-collapse-1"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="tag">&lt;ul</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"nav navbar-nav mr-auto"</span><span class="tag">&gt;</span><span class="pln">
                    </span><span class="tag">&lt;li</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"active nav-item"</span><span class="tag">&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"nav-link"</span><span class="tag">&gt;</span><span class="pln">Home</span><span class="tag">&lt;/a&gt;</span><span class="pln">
                    </span><span class="tag">&lt;/li&gt;</span><span class="pln">
                    </span><span class="tag">&lt;li</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"nav-item"</span><span class="tag">&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/sharks"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"nav-link"</span><span class="tag">&gt;</span><span class="pln">Sharks</span><span class="tag">&lt;/a&gt;</span><span class="pln">
                    </span><span class="tag">&lt;/li&gt;</span><span class="pln">
                </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
            </span><span class="tag">&lt;/div&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;/nav&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"jumbotron"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;h1&gt;</span><span class="pln">Want to Learn About Sharks?</span><span class="tag">&lt;/h1&gt;</span><span class="pln">
            </span><span class="tag">&lt;p&gt;</span><span class="pln">Are you ready to learn about sharks?</span><span class="tag">&lt;/p&gt;</span><span class="pln">
            </span><span class="tag">&lt;br&gt;</span><span class="pln">
            </span><span class="tag">&lt;p&gt;&lt;a</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"btn btn-primary btn-lg"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/sharks"</span><span class="pln"> </span><span class="atn">role</span><span class="pun">=</span><span class="atv">"button"</span><span class="tag">&gt;</span><span class="pln">Get Shark Info</span><span class="tag">&lt;/a&gt;</span><span class="pln">
            </span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"row"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-6"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="tag">&lt;h3&gt;</span><span class="pln">Not all sharks are alike</span><span class="tag">&lt;/h3&gt;</span><span class="pln">
                </span><span class="tag">&lt;p&gt;</span><span class="pln">Though some are dangerous, sharks generally do not attack humans. Out of the 500 species known to researchers, only 30 have been known to attack humans.
                </span><span class="tag">&lt;/p&gt;</span><span class="pln">
            </span><span class="tag">&lt;/div&gt;</span><span class="pln">
            </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-6"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="tag">&lt;h3&gt;</span><span class="pln">Sharks are ancient</span><span class="tag">&lt;/h3&gt;</span><span class="pln">
                </span><span class="tag">&lt;p&gt;</span><span class="pln">There is evidence to suggest that sharks lived up to 400 million years ago.
                </span><span class="tag">&lt;/p&gt;</span><span class="pln">
            </span><span class="tag">&lt;/div&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span><span class="pln">

</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	يتيح شريط التنقل في الأعلى للمستخدمين المرور بين الصفحة الرئيسية وصفحة أسماك القرش. في المكون الفرعي <code>navbar-nav</code>، نستخدم الصنف <code>active</code> في Bootstrap للإشارة إلى الصفحة الحالية للمستخدم. لقد حددنا أيضًا الطرق المؤدية إلى الصفحات الثابتة لدينا، والتي تتوافق مع الطرق التي حددناها في <code>app.js</code>:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/views/index.html</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6733_18" style="">
<span class="pln">...
</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"collapse navbar-collapse"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"bs-example-navbar-collapse-1"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;ul</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"nav navbar-nav mr-auto"</span><span class="tag">&gt;</span><span class="pln">
      </span><span class="tag">&lt;li</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"active nav-item"</span><span class="tag">&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"nav-link"</span><span class="tag">&gt;</span><span class="pln">Home</span><span class="tag">&lt;/a&gt;</span><span class="pln">
      </span><span class="tag">&lt;/li&gt;</span><span class="pln">
      </span><span class="tag">&lt;li</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"nav-item"</span><span class="tag">&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/sharks"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"nav-link"</span><span class="tag">&gt;</span><span class="pln">Sharks</span><span class="tag">&lt;/a&gt;</span><span class="pln">
      </span><span class="tag">&lt;/li&gt;</span><span class="pln">
   </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span><span class="pln">
...</span></pre>

<p>
	بالإضافة إلى ذلك، أنشأنا رابطًا إلى صفحة معلومات سمك القرش في زر jumbotron الخاص بنا:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/views/index.html</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6733_20" style="">
<span class="pln">...
</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"jumbotron"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">
      </span><span class="tag">&lt;h1&gt;</span><span class="pln">Want to Learn About Sharks?</span><span class="tag">&lt;/h1&gt;</span><span class="pln">
      </span><span class="tag">&lt;p&gt;</span><span class="pln">Are you ready to learn about sharks?</span><span class="tag">&lt;/p&gt;</span><span class="pln">
      </span><span class="tag">&lt;br&gt;</span><span class="pln">
      </span><span class="tag">&lt;p&gt;&lt;a</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"btn btn-primary btn-lg"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/sharks"</span><span class="pln"> </span><span class="atn">role</span><span class="pun">=</span><span class="atv">"button"</span><span class="tag">&gt;</span><span class="pln">Get Shark Info</span><span class="tag">&lt;/a&gt;</span><span class="pln">
      </span><span class="tag">&lt;/p&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span><span class="pln">
...</span></pre>

<p>
	يوجد أيضًا رابط إلى ورقة أنماط مخصصة في عنصر الترويسة header:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/views/index.html</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6733_22" style="">
<span class="pln">...
</span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"css/styles.css"</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="tag">&gt;</span><span class="pln">
...</span></pre>

<p>
	سننشئ ورقة الأنماط هذه في نهاية هذه الخطوة.
</p>

<p>
	احفظ الملف وأغلقه عند الانتهاء.
</p>

<p>
	يمكننا، من خلال صفحة الهبوط، إنشاء صفحة معلومات أسماك القرش <code>sharks.html</code>، والتي ستوفر للمستخدمين المهتمين مزيدًا من المعلومات حول أسماك القرش.
</p>

<p>
	افتح الملف:
</p>

<pre class="ipsCode">
$ nano views/sharks.html
</pre>

<ul>
<li>
		الملف <code>‎~/node_project/views/sharks.html</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6733_24" style="">
<span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">
</span><span class="tag">&lt;html</span><span class="pln"> </span><span class="atn">lang</span><span class="pun">=</span><span class="atv">"en"</span><span class="tag">&gt;</span><span class="pln">

</span><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="tag">&lt;title&gt;</span><span class="pln">About Sharks</span><span class="tag">&lt;/title&gt;</span><span class="pln">
    </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">charset</span><span class="pun">=</span><span class="atv">"utf-8"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"viewport"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"width=device-width, initial-scale=1"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"</span><span class="pln"> </span><span class="atn">integrity</span><span class="pun">=</span><span class="atv">"sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="pun">=</span><span class="atv">"anonymous"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"css/styles.css"</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"https://fonts.googleapis.com/css?family=Merriweather:400,700"</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text/css"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/head&gt;</span><span class="pln">
</span><span class="tag">&lt;nav</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"navbar navbar-dark bg-dark navbar-static-top navbar-expand-md"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"button"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"navbar-toggler collapsed"</span><span class="pln"> </span><span class="atn">data-toggle</span><span class="pun">=</span><span class="atv">"collapse"</span><span class="pln"> </span><span class="atn">data-target</span><span class="pun">=</span><span class="atv">"#bs-example-navbar-collapse-1"</span><span class="pln"> </span><span class="atn">aria-expanded</span><span class="pun">=</span><span class="atv">"false"</span><span class="tag">&gt;</span><span class="pln"> </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"sr-only"</span><span class="tag">&gt;</span><span class="pln">Toggle navigation</span><span class="tag">&lt;/span&gt;</span><span class="pln">
        </span><span class="tag">&lt;/button&gt;</span><span class="pln"> </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"navbar-brand"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/"</span><span class="tag">&gt;</span><span class="pln">Everything Sharks</span><span class="tag">&lt;/a&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"collapse navbar-collapse"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"bs-example-navbar-collapse-1"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;ul</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"nav navbar-nav mr-auto"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="tag">&lt;li</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"nav-item"</span><span class="tag">&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"nav-link"</span><span class="tag">&gt;</span><span class="pln">Home</span><span class="tag">&lt;/a&gt;</span><span class="pln">
                </span><span class="tag">&lt;/li&gt;</span><span class="pln">
                </span><span class="tag">&lt;li</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"active nav-item"</span><span class="tag">&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/sharks"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"nav-link"</span><span class="tag">&gt;</span><span class="pln">Sharks</span><span class="tag">&lt;/a&gt;</span><span class="pln">
                </span><span class="tag">&lt;/li&gt;</span><span class="pln">
            </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/nav&gt;</span><span class="pln">
</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"jumbotron text-center"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;h1&gt;</span><span class="pln">Shark Info</span><span class="tag">&lt;/h1&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"row"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-6"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;p&gt;</span><span class="pln">
                </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"caption"</span><span class="tag">&gt;</span><span class="pln">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.
                </span><span class="tag">&lt;/div&gt;</span><span class="pln">
                </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"Sawshark"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-lg-6"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;p&gt;</span><span class="pln">
                </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"caption"</span><span class="tag">&gt;</span><span class="pln">Other sharks are known to be friendly and welcoming!</span><span class="tag">&lt;/div&gt;</span><span class="pln">
                </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://assets.digitalocean.com/articles/docker_node_image/sammy.png"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"Sammy the Shark"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span><span class="pln">

</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	لاحظ أنه في هذا الملف، نستخدم مرة أخرى الصنف <code>active</code> للإشارة إلى الصفحة الحالية.
</p>

<p>
	احفظ الملف وأغلقه عند الانتهاء.
</p>

<p>
	ختامًا ، أنشئ ورقة الأنماط المخصصة CSS التي ربطتها بالصفحتين <code>index.html</code> و <code>sharks.html</code>، وذلك بإنشاء ملف <code>css</code> أولاً في المجلّد <code>views</code>:
</p>

<pre class="ipsCode">
$ mkdir views/css
</pre>

<p>
	افتح ورقة الأنماط:
</p>

<pre class="ipsCode">
nano views/css/styles.css
</pre>

<p>
	أضف الشيفرة التالية التي ستحدد اللون والخط المطلوب لصفحاتنا:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/views/css/styles.css</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_6733_26" style="">
<span class="pun">.</span><span class="pln">navbar </span><span class="pun">{</span><span class="pln">
    margin</span><span class="pun">-</span><span class="pln">bottom</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

body </span><span class="pun">{</span><span class="pln">
    background</span><span class="pun">:</span><span class="pln"> </span><span class="com">#020A1B;</span><span class="pln">
    color</span><span class="pun">:</span><span class="pln"> </span><span class="com">#ffffff;</span><span class="pln">
    font</span><span class="pun">-</span><span class="pln">family</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Merriweather'</span><span class="pun">,</span><span class="pln"> sans</span><span class="pun">-</span><span class="pln">serif</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

h1</span><span class="pun">,</span><span class="pln">
h2 </span><span class="pun">{</span><span class="pln">
    font</span><span class="pun">-</span><span class="pln">weight</span><span class="pun">:</span><span class="pln"> bold</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

p </span><span class="pun">{</span><span class="pln">
    font</span><span class="pun">-</span><span class="pln">size</span><span class="pun">:</span><span class="pln"> </span><span class="lit">16px</span><span class="pun">;</span><span class="pln">
    color</span><span class="pun">:</span><span class="pln"> </span><span class="com">#ffffff;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">.</span><span class="pln">jumbotron </span><span class="pun">{</span><span class="pln">
    background</span><span class="pun">:</span><span class="pln"> </span><span class="com">#0048CD;</span><span class="pln">
    color</span><span class="pun">:</span><span class="pln"> white</span><span class="pun">;</span><span class="pln">
    text</span><span class="pun">-</span><span class="pln">align</span><span class="pun">:</span><span class="pln"> center</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">.</span><span class="pln">jumbotron p </span><span class="pun">{</span><span class="pln">
    color</span><span class="pun">:</span><span class="pln"> white</span><span class="pun">;</span><span class="pln">
    font</span><span class="pun">-</span><span class="pln">size</span><span class="pun">:</span><span class="pln"> </span><span class="lit">26px</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">.</span><span class="pln">btn</span><span class="pun">-</span><span class="pln">primary </span><span class="pun">{</span><span class="pln">
    color</span><span class="pun">:</span><span class="pln"> </span><span class="com">#fff;</span><span class="pln">
    text</span><span class="pun">-</span><span class="pln">color</span><span class="pun">:</span><span class="pln"> </span><span class="com">#000000;</span><span class="pln">
    border</span><span class="pun">-</span><span class="pln">color</span><span class="pun">:</span><span class="pln"> white</span><span class="pun">;</span><span class="pln">
    margin</span><span class="pun">-</span><span class="pln">bottom</span><span class="pun">:</span><span class="pln"> </span><span class="lit">5px</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

img</span><span class="pun">,</span><span class="pln">
video</span><span class="pun">,</span><span class="pln">
audio </span><span class="pun">{</span><span class="pln">
    margin</span><span class="pun">-</span><span class="pln">top</span><span class="pun">:</span><span class="pln"> </span><span class="lit">20px</span><span class="pun">;</span><span class="pln">
    max</span><span class="pun">-</span><span class="pln">width</span><span class="pun">:</span><span class="pln"> </span><span class="lit">80</span><span class="pun">%;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

div</span><span class="pun">.</span><span class="pln">caption</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">float</span><span class="pun">:</span><span class="pln"> left</span><span class="pun">;</span><span class="pln">
    clear</span><span class="pun">:</span><span class="pln"> both</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بالإضافة إلى تعيين الخط واللون، يحدّد هذا الملف أيضًا حجم الصور بتحديد عرض أقصى يبلغ 80٪. هذا سيمنعها من شغل مساحة في الصفحة أكبر مما نريد.
</p>

<p>
	احفظ الملف وأغلقه عند الانتهاء.
</p>

<p>
	بعد إنشاء ملفات التطبيق وتثبيت اعتماديات المشروع، تكون جاهزًا لتشغيل التطبيق.
</p>

<p>
	إذا كنت قد تابعت دليل إعداد الخادم الأولي المذكور في المتطلبات الأساسية، فسيكون لديك جدار حماية نشط يسمح فقط بحركة مرور <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr>. للسماح بحركة المرور عبر المنفذ <code>8080</code>، نفّذ الأمر التالي :
</p>

<pre class="ipsCode">
$ sudo ufw allow 8080
</pre>

<p>
	لتشغيل التطبيق، تأكد من وجودك في المجلد الرئيسي للمشروع:
</p>

<pre class="ipsCode">
$ cd ~/node_project
</pre>

<p>
	ابدأ تشغيل التطبيق باستخدام <code>node app.js</code>:
</p>

<pre class="ipsCode">
$ node app.js
</pre>

<p>
	انتقل بمتصفّحك إلى <code>http://your_server_ip:8080</code>. وستظهر لك صفحة الهبوط التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33610" href="https://academy.hsoub.com/uploads/monthly_2020_02/landing_page.png.f71f88206ef08fd3cff0a08b837846af.png" rel=""><img alt="landing_page.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33610" data-unique="dr0qz9j3i" src="https://academy.hsoub.com/uploads/monthly_2020_02/landing_page.thumb.png.48bd52b344956cf7e33629d9977d5396.png"></a>
</p>

<p>
	انقر على زر الحصول على معلومات القرش Get shark info. وستظهر لك صفحة المعلومات التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33611" href="https://academy.hsoub.com/uploads/monthly_2020_02/sharks.png.0c8d8892c0e717adad0026c5dbc493f5.png" rel=""><img alt="sharks.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33611" data-unique="4ahyv61fa" src="https://academy.hsoub.com/uploads/monthly_2020_02/sharks.thumb.png.6cab02afc37919bf544b828c22bdbc59.png"></a>
</p>

<p>
	لديك الآن تطبيق قيد التشغيل. عندما تكون جاهزًا، أوقف الخادم بكتابة <code>CTRL+C</code>. يمكننا الآن الانتقال إلى إنشاء ملف Dockerfile الذي سيتيح لنا إعادة إنشاء هذا التطبيق وتوسيع نطاقه حسب الرغبة.
</p>

<h2>
	الخطوة الثالثة: كتابة ملف Dockerfile
</h2>

<p>
	يحدد ملف Dockerfile الخاص بك ما سيتم تضمينه في حاوية التطبيق عند تنفيذه. ويتيح لك استخدام هذا الملفّ تحديد بيئة الحاوية وتجنب التناقضات مع الاعتماديات أو إصدارات وقت التشغيل.
</p>

<p>
	باتباع هذه <a href="https://www.digitalocean.com/community/tutorials/building-optimized-containers-for-kubernetes" rel="external nofollow">الإرشادات</a> حول إنشاء حاويات محسّنة، سنجعل صورة التطبيق أكثر فاعلية قدر الإمكان عن طريق تقليل عدد طبقات الصورة وتحديد وظيفة الصورة في غرض واحد هو إعادة إنشاء ملفات التطبيق والمحتوى الثابت.
</p>

<p>
	في المجلّد الرئيسي لمشروعك، أنشئ الملف Dockerfile:
</p>

<pre class="ipsCode">
$ nano Dockerfile
</pre>

<p>
	تُنشَأ صور Docker باستخدام سلسلة متتالية من الصور ذات الطبقات التي تعتمد على بعضها بعضًا. ستكون خطوتنا الأولى هي إضافة الصورة الأساسية للتطبيق والتي ستشكل نقطة انطلاق إنشاء التطبيق.
</p>

<p>
	لنستخدم <a href="https://hub.docker.com/_/node/" rel="external nofollow">الصورة <code>node:10-alpine</code></a>. ويمكننا الحصول على الصورة <code>alpine</code> من مشروع <a href="https://alpinelinux.org/" rel="external nofollow">Alpine Linux</a> لكي تساعدنا في تقليل حجم الصور لدينا.
</p>

<p>
	أضف تعليمات <code>FROM</code> التالية لتعيين الصورة الأساسية للتطبيق:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/Dockerfile</code>:
	</li>
</ul>
<pre class="ipsCode">
FROM node:10-alpine
</pre>

<p>
	تتضمن هذه الصورة <code>Node.js</code> و <code>npm</code>. ويجب أن يبتدئ كل ملفّ Dockerfile بتعليمات <code>FROM</code>.
</p>

<p>
	بشكل افتراضي، تشتمل صورة Docker Node على مستخدم Node غير جذري يمكنك استخدامه لتجنب تشغيل حاوية التطبيق باستخدام الحساب الجذري. إنها ممارسة أمان موصى بها لتجنب تشغيل الحاويات باستخدام root وتقييد الصلاحيات داخل الحاوية في تلك المطلوبة فقط لتنفيذ عملياتها. لذلك، سوف نستخدم المجلّد الرئيسي لمستخدم Node كمجلّد العمل لتطبيقنا ونعيّنه كمستخدم داخل الحاوية. لمزيد من المعلومات حول أفضل الممارسات عند العمل مع صورة Docker Node، راجع <a href="https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md" rel="external nofollow">دليل أفضل الممارسات هذا</a> إذا كانت لغتك الانجليزية جيدة.
</p>

<p>
	لضبط الأذونات على شيفرة تطبيقنا في الحاوية، دعنا ننشئ المجلّد الفرعي <code>node_modules</code> في <code>‎/home/node</code> رفقة المجلّد <code>app</code>. سيضمن إنشاء هذه المجلّدات أنها تتوفّر على الأذونات التي نريدها، والتي ستكون مهمة عندما ننشئ وحدات node محلية في الحاوية باستخدام <code>npm install</code>. بالإضافة إلى إنشاء هذه المجلّدات، سنعطي ملكيتها للمستخدم node: -الملف <code>‎~/node_project/Dockerfile</code>:
</p>

<pre class="ipsCode">
...
RUN mkdir -p /home/node/app/node_modules &amp;&amp; chown -R node:node /home/node/app
</pre>

<p>
	عيّن بعد ذلك مجلّد العمل للتطبيق على <code>‎/home/node/app</code>:
</p>

<ul>
<li>
		الملف <code>‎</code>~/node_project/Dockerfile :
	</li>
</ul>
<pre class="ipsCode">
...
WORKDIR /home/node/app
</pre>

<p>
	إذا لم يتم تعيين مجلّد عمل <code>WORKDIR</code>، فسوف يُنشئ Docker واحدًا افتراضيًا، لذلك من الجيد تعيينه بشكل صريح.
</p>

<p>
	بعد ذلك، انسخ ملفات <code>package.json</code> و <code>package-lock.json</code> (بالنسبة لملفات الإصدار الخامس npm فما فوق):
</p>

<ul>
<li>
		الملف <code>‎~/node_project/Dockerfile</code>:
	</li>
</ul>
<pre class="ipsCode">
...
COPY package*.json ./
</pre>

<p>
	تتيح إضافة تعليمة <code>COPY</code> قبل تنفيذ <code>npm install</code> تثبيت أو نسخ شيفرة التطبيق الاستفادة من آلية التخزين المؤقت لـ Docker. في كل مرحلة من مراحل البناء، سيقوم Docker بالتحقق مما إذا كان يحتوي على طبقة تم تخزينها في ذاكرة التخزين المؤقت لتلك التعليمات المحددة. إذا غيّرنا الحزمة <code>package.json</code>، فسيُعاد بناء هذه الطبقة، لكن إذا لم نفعل ذلك، فسوف تسمح هذا التعليمة لـ Docker باستخدام طبقة الصورة الحالية وتخطي إعادة تثبيت وحدات node.
</p>

<p>
	للتأكد من أن جميع ملفات التطبيق مملوكة للمستخدم node غير الجذري، بما في ذلك محتويات المجلّد <code>node_modules</code>، حوّل المستخدم إلى node قبل تنفيذ <code>npm install</code>:
</p>

<ul>
<li>
		الملف <code>‎-/node_project/Dockerfile</code>:
	</li>
</ul>
<pre class="ipsCode">
...
USER node
</pre>

<p>
	بعد نسخ اعتماديات المشروع وتبديل مستخدمنا، يمكننا تنفيذ <code>install npm</code>:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/Dockerfile</code>:
	</li>
</ul>
<pre class="ipsCode">
...
RUN npm install
</pre>

<p>
	بعد ذلك، انسخ شيفرة تطبيقك مع الأذونات المناسبة إلى مجلّد التطبيق على الحاوية:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/Dockerfile</code>:
	</li>
</ul>
<pre class="ipsCode">
...
COPY --chown=node:node . .
</pre>

<p>
	سيضمن هذا أن ملفات التطبيق مملوكة من قبل مستخدم node غير الجذري.
</p>

<p>
	أخيرًا، اعرض المنفذ <code>8080</code> على الحاوية وابدأ تشغيل التطبيق:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/Dockerfile</code>:
	</li>
</ul>
<pre class="ipsCode">
...
EXPOSE 8080

CMD [ "node", "app.js" ]
</pre>

<p>
	لا ينشر الأمر <code>EXPOSE</code> المنفذَ، ولكنه يعمل بدلاً من ذلك كوسيلة لتوثيق المنافذ على الحاوية التي سيتم نشرها في وقت التشغيل. يقوم <code>CMD</code> بتنفيذ الأمر لبدء التطبيق، في هذه الحالة، <code>node app.js</code>. لاحظ أنه يجب أن يكون هناك تعليمة <code>CMD</code> واحدة فقط في كل Dockerfile. إذا ضمّنت أكثر من واحدة، فستُفعّل الأخيرة فقط.
</p>

<p>
	هناك العديد من الأشياء التي يمكنك القيام بها باستخدام Dockerfile. للحصول على قائمة كاملة بالتعليمات، يرجى الرجوع إلى <a href="https://docs.docker.com/engine/reference/builder/" rel="external nofollow">التوثيق المرجعي لملفات Dockerfile</a>.
</p>

<p>
	يكون الملفّ Dockerfile الكامل على هذا النحو:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/Dockerfile</code>:
	</li>
</ul>
<pre class="ipsCode">
FROM node:10-alpine

RUN mkdir -p /home/node/app/node_modules &amp;&amp; chown -R node:node /home/node/app

WORKDIR /home/node/app

COPY package*.json ./

USER node

RUN npm install

COPY --chown=node:node . .

EXPOSE 8080

CMD [ "node", "app.js" ]
</pre>

<p>
	احفظ الملف وأغلقه عند الانتهاء من التحرير.
</p>

<p>
	قبل بناء صورة التطبيق، دعنا نضيف ملف <code>‎.dockerignore</code> ونظرًا لأنه يعمل بطريقة مشابهة لملف <code>.gitignore</code>، فإن ملف <code>‎.dockerignore</code> يحدّد ماهي الملفات والمجلّدات الموجودة في مجلّد مشروعك والتي لا ينبغي نسخها إلى حاويتك.
</p>

<p>
	افتح الملف <code>dockerignore.</code>:
</p>

<pre class="ipsCode">
$ nano .dockerignore
</pre>

<p>
	أضف داخل الملف وحدات node المحلية وسجلات npm وملف Dockerfile وملف <code>dockerignore.</code>:
</p>

<ul>
<li>
		الملف <code>‎~/node_project/.dockerignore</code>:
	</li>
</ul>
<pre class="ipsCode">
node_modules
npm-debug.log
Dockerfile
.dockerignore
</pre>

<p>
	إذا كنت تعمل باستخدام Git، فستحتاج أيضًا إلى إضافة مجلّد <code>git.</code> وملف <code>gitignore.</code>
</p>

<p>
	احفظ الملف وأغلقه عند الانتهاء.
</p>

<p>
	أنت الآن جاهز لإنشاء صورة التطبيق باستخدام الأمر <code>docker build</code>. سيسمح لك استخدام الراية <code>t-</code> مع <code>docker build</code> بتعليم الصورة باسم سهل التذكّر. ونظرًا لأننا سنقوم بنقل الصورة إلى Docker Hub، فلنضمّن اسم مستخدم Docker Hub الخاص بنا في العلامة. سنعلّم الصورة باستخدام <code>nodejs-image-demo</code>، ولكن لا تتردد في استبدالها باسم تختاره. تذكر أيضًا استبدال <code>your_dockerhub_username</code> باسم مستخدم Docker Hub الخاص بك:
</p>

<pre class="ipsCode">
$ docker build -t your_dockerhub_username/nodejs-image-demo .
</pre>

<p>
	تحدّد النقطة <code>.</code> أن موضع البناء هو المجلّد الحالي.
</p>

<p>
	سوف يستغرق الأمر دقيقة أو دقيقتين لبناء الصورة. بمجرد اكتمال الأمر، يمكنك التحقق من صورك:
</p>

<pre class="ipsCode">
$ docker images
</pre>

<p>
	سيظهر لك في المخرجات ما يلي:
</p>

<pre class="ipsCode">
output
REPOSITORY                                         TAG                 IMAGE ID            CREATED             SIZE
your_dockerhub_username/nodejs-image-demo          latest              1c723fb2ef12        8 seconds ago       73MB
node                                               10-alpine           f09e7c96b6de        3 weeks ago        70.7MB
</pre>

<p>
	أصبح الآن من الممكن إنشاء حاوية بهذه الصورة باستخدام <code>docker run</code>. وسنضمّن ثلاث علامات مع هذا الأمر:
</p>

<ul>
<li>
		<code>‎-p</code> : تنشر هذه الراية المنفذ على الحاوية وتقدّمه كمنفذ على المضيف host. سنستخدم المنفذ <code>80</code> على المضيف، ولكن يجب ألا تتردد في تعديل هذا عند الضرورة إذا كان لديك عملية أخرى تعمل على هذا المنفذ. لمزيد من المعلومات حول كيفية عمل هذا، راجع هذه النقاش في توثيقات Docker حول ربط المنافذ.
	</li>
	<li>
		<code>‎-d</code> : تشغّل هذه العلامة الحاوية في الخلفية.
	</li>
	<li>
		<code>‎-name</code> : هذا يتيح لنا إعطاء الحاوية اسمًا سهل التذكر.
	</li>
</ul>
<p>
	نفّذ الأمر التالي لبناء الحاوية:
</p>

<pre class="ipsCode">
docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo
</pre>

<p>
	بمجرد تشغيل حاويتك، يمكنك فحص قائمة الحاويات قيد التشغيل باستخدام <code>docker ps</code>:
</p>

<pre class="ipsCode">
$ docker ps
</pre>

<p>
	سيظهر لك الإخراج التالي:
</p>

<pre class="ipsCode">
Output
CONTAINER ID        IMAGE                                                   COMMAND             CREATED             STATUS              PORTS                  NAMES
e50ad27074a7        your_dockerhub_username/nodejs-image-demo               "node app.js"       8 seconds ago       Up 7 seconds        0.0.0.0:80-&gt;8080/tcp   nodejs-image-demo
</pre>

<p>
	بعد تشغيل حاويتك، يمكنك الآن الولوج إلى تطبيقك بالانتقال بمتصفحك إلى <code>http://your_server_ip</code>. ستظهر لك صفحتك الهبوط مرة أخرى:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33610" href="https://academy.hsoub.com/uploads/monthly_2020_02/landing_page.png.f71f88206ef08fd3cff0a08b837846af.png" rel=""><img alt="landing_page.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33610" data-unique="rkod83g6h" src="https://academy.hsoub.com/uploads/monthly_2020_02/landing_page.thumb.png.48bd52b344956cf7e33629d9977d5396.png"></a>
</p>

<p>
	الآن وبعد بناء صورة لتطبيقك، يمكنك رفعها إلى Docker Hub للاستخدام المستقبلي.
</p>

<h2>
	الخطوة الرابعة: استخدام مستودع للعمل بالصور
</h2>

<p>
	برفعك لصورة التطبيق الخاصة بك إلى سجلّ مثل Docker Hub، فأنت تجعلها متاحة للاستخدام المستقبلي عندما تكون بصدد بناء حاوياتك وتوسيع نطاقها. سنوضح كيف يعمل هذا عن طريق رفع صورة التطبيق إلى مستودع ثم استخدام الصورة لإعادة إنشاء حاويتنا.
</p>

<p>
	الخطوة الأولى لرفع الصورة هي تسجيل الدخول إلى حساب Docker Hub الذي أنشأته في المتطلبات الأساسية:
</p>

<pre class="ipsCode">
$ docker login -u your_dockerhub_username 
</pre>

<p>
	أدخل كلمة مرور حساب Docker Hub، وسيؤدي التسجيل بهذه الطريقة إلى إنشاء ملف <code>‎~/.docker/config.json</code> في المجلّد الرئيسي لمستخدمك بالبيانات الاعتمادية لDocker Hub.
</p>

<p>
	يمكنك الآن رفع صورة التطبيق إلى Docker Hub باستخدام العلامة التي أنشأتها مسبقًا، <code>your_dockerhub_username/nodejs-image-demo</code>
</p>

<pre class="ipsCode">
$ docker push your_dockerhub_username/nodejs-image-demo
</pre>

<p>
	دعنا نختبر الآن أهمّية سجلّ الصور بتدمير حاوية التطبيق الحالية والصورة وإعادة بنائها باستخدام الصورة التي في مستودعنا.
</p>

<p>
	استعرض أولاً حاوياتك التي توجد قيد التشغيل:
</p>

<pre class="ipsCode">
$ docker ps
</pre>

<p>
	سيظهر لك الإخراج التالي:
</p>

<pre class="ipsCode">
Output
CONTAINER ID        IMAGE                                       COMMAND             CREATED             STATUS              PORTS                  NAMES
e50ad27074a7        your_dockerhub_username/nodejs-image-demo   "node app.js"       3 minutes ago       Up 3 minutes        0.0.0.0:80-&gt;8080/tcp   nodejs-image-demo
</pre>

<p>
	باستخدام <code>CONTAINER ID</code> الظاهر في المخرجات، أوقف حاوية التطبيق قيد التشغيل. تأكد من استبدال المعرّف أدناه بمعرّف الحاوية <code>CONTAINER ID</code>:
</p>

<pre class="ipsCode">
$ docker stop e50ad27074a7
</pre>

<p>
	اعرض قائمة صورك باستخدام الراية <code>‎-a</code> :
</p>

<pre class="ipsCode">
$ docker images -a
</pre>

<p>
	سيظهر لك الإخراج التالي مع اسم صورتك، <code>your_dockerhub_username/nodejs-image-demo</code>، إلى جانب صورة node وباقي الصور الأخرى الخاصة ببنائك:
</p>

<pre class="ipsCode">
Output
REPOSITORY                                           TAG                 IMAGE ID            CREATED             SIZE
your_dockerhub_username/nodejs-image-demo            latest              1c723fb2ef12        7 minutes ago       73MB
&lt;none&gt;                                               &lt;none&gt;              2e3267d9ac02        4 minutes ago       72.9MB
&lt;none&gt;                                               &lt;none&gt;              8352b41730b9        4 minutes ago       73MB
&lt;none&gt;                                               &lt;none&gt;              5d58b92823cb        4 minutes ago       73MB
&lt;none&gt;                                               &lt;none&gt;              3f1e35d7062a        4 minutes ago       73MB
&lt;none&gt;                                               &lt;none&gt;              02176311e4d0        4 minutes ago       73MB
&lt;none&gt;                                               &lt;none&gt;              8e84b33edcda        4 minutes ago       70.7MB
&lt;none&gt;                                               &lt;none&gt;              6a5ed70f86f2        4 minutes ago       70.7MB
&lt;none&gt;                                               &lt;none&gt;              776b2637d3c1        4 minutes ago       70.7MB
node                                                 10-alpine           f09e7c96b6de        3 weeks ago         70.7MB
</pre>

<p>
	احذف الحاوية المتوقفة وجميع الصور، بما في ذلك الصور غير المستخدمة أو المعلّقة، باستخدام الأمر التالي:
</p>

<pre class="ipsCode">
$ docker system prune -a
</pre>

<p>
	اكتب <code>y</code> في المحثّ عند الإخراج لتأكيد رغبتك في إزالة الحاوية والصور المتوقفة. وينبغي التوضيح أن هذا سيؤدي أيضًا إلى حذف ذاكرة التخزين المؤقت للبناء.
</p>

<p>
	لقد حذفت الآن كلًا من الحاوية التي تشغّل صورة التطبيق والصورة نفسها. لمزيد من المعلومات حول إزالة حاويات Docker والصور، يرجى الاطلاع على <a href="https://academy.hsoub.com/devops/cloud-computing/docker/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%AD%D8%A7%D9%88%D9%8A%D8%A7%D8%AA-docker-r310/" rel="">كيفية التعامل مع الحاويات</a>.
</p>

<p>
	بعد حذف كل الصور والحاويات الخاصة بك ، يمكنك الآن سحب صورة التطبيق من Docker Hub:
</p>

<pre class="ipsCode">
$ docker pull your_dockerhub_username/nodejs-image-demo
</pre>

<p>
	اعرض قائمة صورك مرة أخرى:
</p>

<pre class="ipsCode">
$ docker images
</pre>

<p>
	ستظهر لك صورة تطبيقك:
</p>

<pre class="ipsCode">
Output
REPOSITORY                                     TAG                 IMAGE ID            CREATED             SIZE
your_dockerhub_username/nodejs-image-demo      latest              1c723fb2ef12        11 minutes ago      73MB
</pre>

<p>
	يمكنك الآن إعادة بناء حاويتك باستخدام الأمر التالي من الخطوة 3:
</p>

<pre class="ipsCode">
docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo
</pre>

<p>
	اعرض قائمة الحاويات قيد التشغيل:
</p>

<pre class="ipsCode">
$ docker ps
</pre>

<pre class="ipsCode">
Output
CONTAINER ID        IMAGE                                                   COMMAND             CREATED             STATUS              PORTS                  NAMES
f6bc2f50dff6        your_dockerhub_username/nodejs-image-demo               "node app.js"       4 seconds ago       Up 3 seconds        0.0.0.0:80-&gt;8080/tcp   nodejs-image-demo
</pre>

<p>
	تصفّح <code>http://your_server_ip</code> مرة أخرى لعرض التطبيق قيد التشغيل.
</p>

<h2>
	الخلاصة
</h2>

<p>
	في هذا الدرس، عملت على بناء تطبيق ويب ثابت باستخدام Express و Bootstrap، بالإضافة إلى صورة Docker لهذا التطبيق. استخدمت هذه الصورة لإنشاء حاوية ورفعت الصورة إلى Docker Hub. بعد ذلك، تمكنت من تدمير صورتك وحاوياتك وإعادة إنشائها باستخدام مستودع Docker Hub.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-build-a-node-js-application-with-docker" rel="external nofollow">How To Build a Node.js Application with Docker</a> لصاحبته Kathleen Juell
</p>
]]></description><guid isPermaLink="false">809</guid><pubDate>Wed, 05 Feb 2020 06:30:24 +0000</pubDate></item></channel></rss>
