لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 12/25/21 في كل الموقع
-
1 نقطة
-
ما هي أفضل طريقة لتمثيل البيانات الفئوية في Seaborn، أعلم أنه يمكن الرسم من خلال FacetGrid لكن هل توجد طريقة أفضل؟ وكيف؟1 نقطة
-
عندما أستعمل الدالة url_for بالشكل التالي: url_for('index') أحصل على " / " فقط، ولكن ما أريد الحصول عليه هو http://localhost:5000/ وليس مجرد علامة / فقط. هل يمكن التعديل على هذه الدالة للقيام بهذا الأمر أم توجد طريقة أخرى لتنفيذ هذه المهمة في فلاسك Flask؟1 نقطة
-
لدي الكود التالي الذي يعرض مخطط بيانات: import seaborn as sns import pandas as pd import numpy as np import matplotlib.pyplot as plt plt.rcParams["figure.figsize"] = [7.50, 3.50] plt.rcParams["figure.autolayout"] = True df = pd.DataFrame(np.random.random((5, 5)), columns=["a", "b", "c", "d", "e"]) sns_pp = sns.pairplot(df) وأحتاج إلى حفظ الشكل الناتج كصورة، لذا كيف أقوم بذلك؟1 نقطة
-
سلام عليكم انا من غزة بقالي سنة ونص بتعلم برمجة لغاية لما دخلت انترفيو واكتشفت اني مستوايا مش كويس وبدي فت عدس عشان اوص وعندي مشكلة بالبروبلم سولفنج للاسف السبب اني اشتركت مع مراكز ما بتخاف الله وانا دراستي الاساسية ملهاش دعوة بالبرمجة الفكرة اني سبت تخصصي انا حاليا معنديش اي دخل او مهارة ونفسيتي تعبانة، انا فتاة ي جماعة ووالدي وضعه صعب والعيشة طاحنة مش قادرة اصدق اني داخلة ع 26 ومعنديش مصدر دخل وكل اشي بدخل فيه بفشل فيه الحمدلله بداوم على القران والذكر لكن محلك سر ومحدش حاسس فيا1 نقطة
-
رفض التوظيف عدم قبولك في مقابلة توظيف لا تعني عدم وجود المهارات الكافية للدخول ضمن سوق العمل، استفيدي من تحديد نقاط الضعف لديك وحاولي العمل عليها وتطوير مهاراتك، اذا كان الهدف الحصول على وظيفة ضمن أحد الشركات فيجب التركيز على تقوية مهارة حل المشاكل التي تطرح ضمن المقابلات عادةً هناك مصادر عديدة للأسئلة الشائع سؤالها ضمن تلك المقابلات. وحتى بعد تقوية تلك المهارة قد يتم رفضك من عدة جهات لأسباب مختلفة الأساس هو التركيز على تطوير المهارات المطلوبة ضمن سوق العمل وستجدين الفرصة المناسبة. العمل الحر يمكن الاعتماد على العمل الحر كمصدر دخل قد يوازي أحيانا العمل الوظيفي أو أكثر، ركزي على تطوير مهارات مطلوبة ضمن السوق والمحاولة بالقيام ببعض الأعمال المجانية بدايًة لتتمكني من عرضها في معرض أعمالك وبدء التعامل مع الزبائن، يوجد الكثير من المقالات والنصائح بهذا الخصوص هنا في الأكاديمية ضمن قسم مقالات العمل الحر، هذه المقالة تعتبر بداية جيدة: الدعم النفسي قد تشعري بالتحسن عند طلب النصيحة وسماع آراء أشخاص مختلفين من وجهة نظر محايدة، حاولي نشر طلب للنصيحة ضمن مجتمع انصحني، يمكن نشر سؤالك كمجهول إن أردت، مراجعة الطبيب النفسي هي أولوية في حال تفاقم الوضع النفسي السيء.1 نقطة
-
البرمجة كائنية التوجه هامة في أي لغة برمجة وهي ضرورية لإستيعاب مفاهيم برمجية مثل أنماط التصميم بالإضافة إلى أن البرمجة كائنية التوجه لها حالات إستخدامها الخاصة التي تكون الأفضل فيها بالإضافة لوجود عدد من أطر البيانات في الجافاسكريبت المبنية على البرمجة كائنية التوجه مثل إطار عمل nest js المُستخدم في برمجة الواجهات الخلفية وأيضًا يوجد لغة typescript والتي تعد نسخة مطورة من الجافاسكريبت والتي تعتمد بشكلٍ أساسي على البرمجة كائنية التوجه ويمكنك إستخدامها في React وتعمل بشكل أساسي في أطر عمل أخرى مثل angular1 نقطة
-
حاولت تشغيل الكود التالي على خادم وكان يعمل بدون مشكلة: from flask_wtf import FlaskForm from wtforms import Form, StringField, PasswordField, validators, ValidationError from wtforms.fields.html5 import EmailField class BaseUserForm(FlaskForm): name = StringField('Name', [validators.DataRequired(), validators.Length(min=2, max=30)]) email = EmailField('Email', [validators.DataRequired(), validators.Email()]) ولكن عندما أقوم بتشغيل نفس المشروع على الحاسوب محليًا يظهر لدي الخطأ التالي: Exception: Install 'email_validator' for email validation support. كيف يمكنني حل هذه المشكلة؟1 نقطة
-
ما معنى السطر من الكود re.search("(.)\1{3,}",password) السؤال كان اذا في كلمة المرور اللي ادخلها المستخدم كان فيها حرف تكرر اكتر من 4 مرات يطبعله مسج انه لازم ما يتكرر لكن شو شرح هاي الرموز؟؟؟1 نقطة
-
الأقواس الدائرية تمثل مجموعة محارف () النقطة تمثل ظهور أي محرف (رقم أو حرف) \ تمثل محرف هروب escape أي أن الرمز الذي سيأتي بعده سيتم أخذه كما هو بدون معناه ضمن السياق مثل + * ؟ في حال وجود \ أماها ستعامل كمحارف الأقواس المجعدة {min,max} تحدد مجال لتكرار النمط الذي يسبقها 1\ يدعى backreference سيقوم بربط التعبير الذي قبله بالذي بعده مما يضمن تكرار الجزء الأول محد أدنى 3 مرات في مثالك أعتقد أن الحل السليم سيكون بهذه الطريقة re.search("(.)\1{4,}",password) re.search سيبحث عن النمط إن كان مكررا في كلمة السر أم لا، هنا نريد التحقق من 4 أيضاً إن أعاد البحث True هذا يعني أن هنالك تكرار1 نقطة
-
Thank you but how toGet department, total salary for each department from employee table order by total salary descending1 نقطة
-
يمكنك بواسطة تعليمة لايك التي تقوم بالتعامل مع النصوص ويمكنك استخدامها بالطريقة التالية حيث اشارة النسبة المؤية بعد المحرف تعني انه يبدأ بهذا المحرف اما بين علامتين مؤيتين تعني أنه لايهم موضعه ولكن يجب أن يكون موجودا Select * //تحديد كل الأعمدة FROM Employee // من جدول الموظفين WHERE First_name LIKE 'J%' // واعرض السطر الذي يطابق الشرط الأول OR First_name LIKE '%Ch%' //او الشرط الثاني1 نقطة
-
1 نقطة
-
يمكنك ذلك باستخدام هذه التعليمة SELECT * //تحديد كل الأعمدة FROM Employee // من جدول الموظفين WHERE First_name = 'John'; // واعرض السطر الذي يطابق الشرط التالي1 نقطة
-
تخيل أنك استيقظت ووجدت نفسك فجأةً في غرفة تحكم محطة الفضاء العالمية، وليس لديك أدنى فكرة عن معنى الأضواء الوامضة، أو عن عمل أيٍّ من الأزرار ومفاتيح التبديل، وليس لديك فكرة عما يجب عليك فعله. هذا ما يشعر به مستخدمو المنتج الجديد عندما يستخدمون تطبيقك للمرة الأولى. ربما تكون هذه مبالَغة، لكن إطلاق أداة أو تطبيق أو موقع إلكتروني للمستخدمين بدون دليل استخدام يجعلهم يشعرون وكأنهم تائهون في الفضاء. إذ سيبدو منتجك الجديد مشابهًا لقمرة القيادة في المكوك الفضائي Endeavor بالنسبة للمستخدمين عندما لا تهيئ واجهة المستخدم لهم. ينسى المصممون في كثير من الأحيان أنهم بخلاف المستخدمين، يجرون الأبحاث ويختبرون الواجهات ويرسمون خرائط المسارات، فقد لا يعلم الوافد الجديد إلى موقعك أو تطبيقك كيف تجري الأمور أو كيف يجد ما يريد كما هو الحال بالنسبة للمصمم أو لفريق المنتج، وهنا يجب عليك حماية مستخدمي تطبيقك أو موقعك من الشعور بالارتباك والإحباط، وذلك بمد يد العون إليهم وتأمين الأرضية التي يقفون عليها، وذلك من خلال تضمن عدم رميهم لتطبيقك في سلة المهملات. تهيئة المستخدم تُعَد تهئية المستخدم سلسلةً من الواجهات والبُنى التي تتيح للمستخدم الدخول بسهولة في تجربة المنتج، وقد تكون ببساطة الترحيب والشرح فحسب، أو أكثر تعقيدًا بحيث يجب على المستخدم إتمام سلسلة من المهام حتى يتمكن من استخدام تصميمك، وطالما تزود مستخدميك بتفاصيل تصاعدية عن ميزات منتجك، فأنت بذلك تُعِدُّهم للنجاح. إذا دخلت إلى تطبيق جديد لأول مرة ورأيت سلسلة شاشاتٍ تحوي عبارات قصيرة وودودة تشرح وظيفة التطبيق، فمن المرجح جدًا أنك ستشعر بالألفة مع ما ستجد عليه التطبيق حتى قبل أن تبدأ باستخدامه، حيث يرشدك تطبيق جديد كليًا لوسائل التواصل الاجتماعي مثلًا خلال إنشاء حسابك وإعداد تفضيلاتك وإضافة بعض اهتماماتك، وبذلك سوف تبدأ تجربتك عند هذه المرحلة التي تخطت الصفر بخطوات قليلة. تنطلق تجربة استخدام تطبيق Hopper للمرة الأولى بهذه التهيئة اللطيفة للمستخدمين، وتقدم لهم هذه التهيئة قيمة التطبيق المتوقعة والطريقة التي يعمل بها التطبيق على تحسين حياتهم. تساعد التهيئة على منح المستخدم فكرةً عما يحتاج لفعله بهدف الحصول على ما يحتاج من المنتج أو التطبيق، وهي طريقة لبناء الثقة مع المستخدم، وهي المفتاح لتحقيق انتشار أكبر للتطبيق والحفاظ عليه، فضلًا عن تقديم المساعدة للمستخدم. أهمية التهيئة الانطباع الأول قوي جدًا، إذ سيهجر مستخدم من أربعة وسطيًا التطبيق بعد استخدامه للمرة الأولى، وبمجرد أن يجربوا تطبيقك ثم يتركوه، فلن يعودوا إليه مجددًا، لهذا السبب فإن التهيئة الكافية لمستخدمي منتجك هي أمر جوهري جدًا. عندما يبذل المستخدم وقتًا وجهدًا في تحميل تطبيق جديد، فسيتوقع على الأرجح أن التطبيق سيعزز حياته، عدا ذلك فإن لديه مبررًا كافيًا تمامًا لهجر التطبيق من أجل تجربة تطبيق آخر. استخدم مطورو تطبيق توين Twine الأبحاث لتحسين تهيئة واجهة المستخدم من أجل مستخدميهم، وتخفيض احتمال تراجع أعداد المستخدمين كثيرًا. لقد خفضّت منصة البرمجيات الشبكية توين احتمال تراجع أعداد المستخدمين الذي يبلغ 65% إلى أكثر من النصف، وذلك عن طريق دمج تهيئةٍ ذات معنى في تجربتهم، وقد استفادت المنصة من منهجٍ متعدد الشُّعَب في إثراء انطباع الزوار الأولي، ويتمثل هذا المنهج في الدروس والتهيئة المستمرة. تعزز التهيئة استمرار الخدمة لأمد طويل، ومن المهم إضافة ميزات وأدوات جديدة ومثيرة لمنتجك أو خدمتك، ولكن إذا لم يعلم الناس عنها أو لم يعلموا كيف يستخدمونها، فهي غير نافعة. لقد كان لدى منصة wistia الشهيرة لمشاركة مقاطع الفيديو مثلًا ميزات تخصصية رائعة، ولكن لم يستفِد أغلب المستخدمين منها، ومع ذلك فقد قدموا مقطع فيديو لشرح استخدام هذه الميزات بعد أن أجروا أبحاثًا دقيقةً، مما أدى إلى زيادة لا تصدق في الاستخدام وصلت إلى 30% من المستخدمين. أنماط ومنهجيات تهيئة واجهة المستخدم أنواع التهيئة تهدف عدة طرق إلى تهيئة المستخدمين لتطبيق أو منتجٍ إلكتروني، ويوظف معظم المنتجين تجميعات من عدة أنماط للتهيئة بهدف تحقيق احتياجات المستخدمين الجدد والمحافظة عليهم في المستقبل. جولة حول التطبيق The Nickel Tour وهو نمط شائع مستخدم بكثرة في تطبيقات الهواتف النقالة، حيث حالما يطلق المستخدم التطبيق للمرة الأولى، فسيظهر له عدد من النوافذ السريعة التي تحدد الخطوط العريضة عن فائدة التطبيق وبعض الأساسيات حول كيفية البدء باستخدامه. تفيد هذه المقدمة البسيطة والثابتة مثل بساط ترحيب للمستخدمين الذين لا يألفون التطبيق، ويجب ألا تتجاوز بضع عبارات قصيرة مصحوبة برسومات بسيطة، حيث لا يريد أحد قراءة دليل استخدام بالغ الطول. يقدم تطبيق الهواتف النقالة Slack نفسه للمستخدمين الجدد بنظرة عامة مكونة من أربع نوافذ، كما يوظف المسار التمهيدي بعضًا من أفضل الممارسات مثل نقاط التقدم وخيار التخطي الواضح. ويُعَد تزويد هذه النوافذ بمؤشرات للتقدم إلى جانب خيار الخروج أو التخطي، هو من أفضل الممارسات، فبهذه الطريقة سوف يتمكن المستخدمون من إدراك كم من النوافذ تبقى للمستخدم حتى ينتهي من المقدمة بالإضافة إلى عدم شعوره بأنه محتجَز فيها. علامات التدريب وتلميحات الأدوات والإرشادات وهي طرق شائعة جدًا تحتاج جهدًا صغيرًا نسبيًا لتهيئة المستخدمين ببداية تجربتهم للتطبيق وخلالها. يستخدم "توين" أنماط تلميحات الأدوات وعلامات التدريب لتوفير جولة سريعة في لوحة معلومات المستخدم، بدون إثقال المستخدمين بالتعليمات. تُعَد تجهيزات واجهة المستخدم البسيطة التي تلفت الانتباه إلى مناطق تفاعلية وأزرار أو مواقع القوائم التي تساعد على تنبيه المستخدم بوجود مكونات مفيدةً في التطبيق أو الموقع الإلكتروني، وهي مفيدة خصوصًا في الواجهات الأكثر تعقيدًا، حيث تكون هذه المكونات غير ظاهرة للعيان مباشرةً أو صعبة الفهم. عندما صممت واجهة موقع Metrie -وهو موقع للتهيئة الثلاثية الأبعاد للغرف-، وضعتُ طبقةً من تلميحات التدريب القابلة للتبديل ودمجتُها مع نافذة التحميل. يُعَد هذا النوع من أنماط حواشي تهيئة المستخدم مفيدًا جدًا، ولكن حذارِ من مفاجأة المستخدم بظهور كل هذه النوافذ الصغيرة دفعةً واحدةً. قرر متى وأين تكون أدوات التلميحات وتلميحات التدريب أكثر فائدةً، وأرشد المستخدمين لمكون واحد في كل مرة، وتجنب الإكثار من الشرح للمكون الواضح. التوجيه بإتمام المهام لعل أفضل طريقة لجعل أمر يعلق في ذهن المستخدم هي دفعه لممارسة العمل بنفسه غالبًا، وهي طريقة لدفع المستخدمين باتجاه التفاعل مع المنتج من خلال سلسلة خطوات، وهو أمر شائع جدًا عندما يطلب المنتج من المستخدمين إنشاء حساب أو ضبط معالم إضفاء الطابع الشخصي في بداية الاستخدام. يُعَد التوجيه بإتمام المهام فرصةً ممتازةً لمساعدة المستخدمين في تثقيف أنفسهم بخصوص المتحكمات وجميع جوانب منتجك فور إتمامها، حيث ترتفع بشدة فرص تجربة المستخدم للتطبيق مرةً أخرى عندما تساعده على تعلم كيفية استخدام التطبيق مبكرًا. توجِّه تجربة مستخدم لأول مرة في منصة إدارة الفرق Basecamp المستخدمين من خلال إتمامهم لمهمةٍ معينة، وذلك لكي يثقفوا أنفسهم بخصوص ميزات وقدرات التطبيق، وتُعَد هذه الفكرة جيدةً في منح المستخدمين القدرة على تخطي هذا النوع من التهيئة عندما يكون ذلك ممكنًا. انظر إذا كان بإمكانك تصميم مهمة إنشاء حساب قابلة للتخطي بوصفها تجربةً، وأخرى لا تملك هذه القابلية، وذلك لاختبار أيهما أفضل بالنسبة لمستخدمي التطبيق. متى يجب تهيئة المستخدمين من الأهمية بمكان اتخاذ القرار بشأن اختيار نوع نمطٍ لتهيئة تجربة المستخدم في أي جزء من تطبيقك، وهو أمر جوهري لتحديد الحجم المناسب لتصميم تجربة المستخدم. ابحث عن الفرص المناسبة لمد يد العون للمستخدمين خلال رحلتهم مع التطبيق، بدايةً من إطلاق التطبيق وحتى الاستخدام الكامل. تهيئة من لم يألف التطبيق أبدا الانطباعات الأولية مهمة جدًا، وهي الأمر الجوهري في الوصول إلى النجاح، فقد لا تملك فرصةً ثانيةً بعدها، حيث سيهجر العديد من المستخدمين المنتج مباشرةً في المرة الأولى لاستخدامه كما ذُكر سابقًا. يطلق تطبيق الصحافة Dailyo تجربة المرة الأولى لمستخدميه بمقدمة لطيفة تشرح أهمية التطبيق لمستخدميه، وتمنحهم نصائح حول كيفية تحقيق أعلى فائدة للمستخدم. طبّق الأبحاث والاختبارات الصارمة لمعرفة ما إذا كان النهج الصحيح لسياق المنتج هو منح المستخدمين مقدمةً تعليميةً قصيرةً، أم تجربةً توجيهيةً عميقةً عند أول استخدامٍ لمنتجك. التهيئة التدريجية لقد صُمِّمَت هذه التقنية بهدف عدم توقف تهيئة المستخدمين بمجرد انتهاء مسار تهيئتهم الأول، إذ لديك العديد من الفرص لمواصلة مساعدتهم وتثقيفهم وإمتاعهم. فكر بالأمر كما لو أنك ترفع مستوى تصميم لعبة للمستخدمين. سوف يدفع تطبيق Duolingo المستخدمين لتحديد مستوى خبرتهم ثم اختبار كفاءتهم، وذلك متى ما أرادوا تعلم لغة جديدة، حتى يتجنبواالإحباط بسبب المبالغة في تقدير قدراتهم واحتمال استسلامهم. احرص على إعادة مزج أنماط التهيئة بين حين وآخر خلال علاقة المستخدم بالتطبيق، وذَكِّر من استخدم التطبيق طوال أسبوع بإنجاز مهمة أكثر تقدمًا قد يكون غافلًا عنها، وأعلن عن انقضاء كل خطوة مهمة في التطبيق باستخدام إشعار بسيط. يشير استطلاع آراء المستخدمين حول تجربتهم بعد أسابيع قليلة من بدايتها بأنك مهتم بهم. التهيئة لمهمة جديدة وهو مزج بين تهيئة المستخدم الجديد والتهيئة التدريجية لمستخدم ممارس للعمل على التطبيق، فعندما تُطلِق ميزةً جديدةً أو تغير تغييرًا جوهريًا في التجربة، فتأكد من علم المستخدمين بهذه الميزة أو التغيير وكيفية الاستفادة من هذا الأمر. عندما أدخَلَ موقع فيسبوك مثلًا ميزةً جديدةً إلى تجربة المستخدم في تطبيقه، أعلَمَ مستخدميه بالأمر من خلال أداة تلميح مرئية واضحة، وقد شرحت أداة التلميح طريقة استخدام هذه الميزة الفائقة القوة من خلال رسالة بسيطة. أفضل الممارسات والنصائح لتهيئة واجهة المستخدم يجب عليك فهم المستخدم سيكون نمط التهيئة لمنتج جديد كليًا ذي تقنية حديثةمختلفًا على الأرجح عن أي أمر مألوف كما هو الحال بالنسبة لتقويم زمني أو تطبيق لحفظ الملاحظات. انظر إلى وصف الشخصيات الذي أعده الفريق، وقرِّر ما قد يكون منطقيًا بالنسبة للمستخدمين. حدد الحجم المناسب من تهيئة التجربة من خلال فهم المستخدمين، وهيئ تجربة المستخدم لتناسب الشخصيات المستهدفة. استكشف واستفد من النماذج العقلية للمستخدمين الموجودين من أجل المساعدة في سد أي فجوات في توقعات المستخدمين من التطبيق أو الموقع الإلكتروني، وتعرف على المؤشرات التي يستند إليها تصميمك بمقابل الابتكارات التي تبدو مربكةً للوهلة الأولى. يشير تطبيق Basecamp إلى حالات الاستخدام الجوهرية للمستخدمين الجدد في تهيئته لتجربتهم، وذلك عبر عرض لوحة خيارات بسيطة ودليل استخدام لطيف. تساعد الأبحاث المطبقة على المستخدمين على بناء التعاطف مع الجمهور الأساسي، كما تساعد اختبارات المستخدمين الدورية وتحاليل قابلية الاستخدام فريقك أثناء بنائه للمنتج ليس في تحسين التصميم بأكمله فقط، بل كذلك في تغطية معلومات عن الأمور التي يجب التركيز عليها في تهيئة المستخدم. وازن بين بحث المستخدم النوعي والمقاييس التي سوف تساعد في التنبيه على أي مشكلة قد تطرأ خلال عملية تهيئة المستخدم، فإذا لاحظت مثلًا أن هناك عددًا كبيرًا من المستخدمين يهجرون التطبيق عند مرحلة إعداد التفضيلات خلال تهيئة التجربة، فتواصل مع المستخدمين، فربما تكون التجربة ثقيلةً جدًا عليهم أو شخصيةً جدًا بالنسبة لهم، وربما يريدون الوصول إلى ما يريدون بسرعة، وبذلك يمكن لك تدارك ذلك وإجراء تعديلات على المسار. اربط بين التهيئة والقيمة التي يحتاجها المستخدم يجب أن تركز تهيئة تجربة المستخدم للمستخدمين الجدد على إيصال المستخدم إلى لحظة مذهلة من الرضا بسهولة قدر الإمكان. حدِّد اقتراحًا للقيمة الجوهرية من أجل مستخدمك، وأوجد طريقةً لإيصاله إلى هذه القيمة أولًا. استخدم تهيئة مقدمة الميزات لتذكر المستخدم بسبب كون تطبيقك أو منتجك هو الأفضل لتلبية حاجة معينة، وإذا كان مسار التهيئة في تطبيقك يشمل إضفاء طابع شخصي، فاشرح للمستخدمين سبب سؤالك لهم حول تفضيلاتهم الشخصية أو حالتهم، واشرح كيف لذلك أن يعزز تجربتهم. لدى تطبيق Inbox by Gmail مقدمة طويلة ضمن تهيئته لتجربة المستخدم، ولكن كل حالة تشير إلى كيفية جعل حياتهم أسهل باستخدام هذه الوظائف. يمكنك أن تقدم لاحقًا في التطبيق التهيئة أو التعليمات التي لا ترتبط مباشرةً بالقيمة التي تهم المستخدم، مثل الميزات الأنيقة وغير المهمة بالنسبة للمستخدم، وذلك من خلال تهيئة ذات أثر خفيف في بداية الاستخدام، فمن الجيد إعلام المستخدم بالميزات الإضافية، لكن ليس من الضروري تقديمها إذا لم تكن من ضمن التجربة الجوهرية. اجعل التهيئة سريعة وسهلة يجب عليك ألا تجبر المستخدم على تحمل تعليمات متعددة الخطوات بحيث يشعر وكأنه ينجز عمله، كما يجب عليك عدم تركه في حقل مبهم من الأزرار ومفاتيح التبديل بين الخيارات. هل هناك أحد يقرأ كتيبات التعليمات بعد الآن؟ هل سيقضي أي شخص وقتًا في قراءة كل هذه التعليمات؟ ناهيك عن تذكرها؟ يخرق تطبيق Morningstar Financial مثلًا المعايير الأساسية لممارسة التهيئة الجيدة لمستخدميه من حيث جعل الأمور أسهل. مجددًا، يجب أن تحدد مدى ثقل التجربة اعتمادًا على رؤى أبحاث المستخدم ومدى تعقيد منتجك، فآخر شيء تريده أن تسبب ملل المستخدم أو خوفه باستخدامك لمقدمةٍ طويلة جدًا، حتى لو كانت تقنيةً حديثةً جدًا وإبداعيةً، وهنا ستكون مقدمة سريعة وترحيب؛ كافيين على الأرجح إذا كان التطبيق أو المنتج بسيطَيْن. اعتمد التهيئة التدريجية إذا كان هناك حاجة إلى التعمق أكثر والتي تمدد التهيئة على كامل التجربة مع التطبيق، ويجب التعمق أكثر أو أقل بحسب الحاجة لتأمين الدليل والأرضية اللازمة للمستخدم. اسمح للمستخدمين بتخطي تهيئتهم أو تأخيرها إذا أرادوا ذلك، فإذا كانت مقدمة تطبيقك هي عبارة عن 4 نوافذ أو أكثر من ذلك ويجب على المستخدم المرور خلالها جميعًا؛ فقد يحدث زر التخطي فرقًا كبيرًا. اجعل التهيئة قابلة للتكرار لا تنسَ منح المستخدمين فرصةً لإعادة المرور خلال أي دليل إرشاد أو جولة قدمتها لهم، خصوصًا إذا كنت قد اتبعت أفضل ممارسات تهيئة تجربة المستخدم في جعل البرنامج تعليميًا في المقدمة، أو أي من أنماط التهيئة قابلًا للتخطي. لا يمكنك التصميم على اعتبار أن المستخدم يرفض مطلقًا المرور على مقاطع الفيديو التعليمية أو الجولات التعريفية لواجهة التطبيق. افرض أنه قد نسي إحدى النصائح الذكية التي أسديتها له أثناء تهيئته عند استخدامه الأول للتطبيق، أو أنه وجد نفسه تائهًا بعد تخطي كامل المقدمة عن طريق الخطأ. يُعطَى المستخدم القدرة على تشغيل أو إيقاف تلميحات المدرب عند حاجته لذلك عبر تطبيق Metrie's Room Styler لتصميم المظهر الثلاثي الأبعاد للغرف، ويمكِّن هذا المستخدم من تلقي التوجيه في أي وقت يريد. أدرج قسمًا للمساعدة بين خيارات التنقل والذي يحتوي على مسار لإعادة أي تهيئة قد يكون المستخدم غافلًا عنها. لا تجعل الأمر شخصيا جدا القوالب الطويلة التي تطرح عددًا كبيرًا من الأسئلة على المستخدم هي من أسباب نفور المستخدمين، ولذلك فتشجيع المستخدم الجديد على تقديم بعض المعلومات التي تساعد على إضفاء طابع شخصي على تجربته هو أمر لطيف، لكن من المهم عدم جعل الأمر يبدو غريبًا بطرح الأسئلة عن عدد كبير من التفاصيل. يجب عليك ألا تطرح عددًا كبيرًا من الأسئلة عندما تكون الخصوصية أمرًا نادرًا وشخصيًا، خصوصًا عند بداية استخدام التطبيق. ومع ذلك تفرض بعض التطبيقات على المستخدم إعداد تفضيلاته أو اتخاذ قرارات قبل السماح له باستخدام التطبيق، وهذه فكرة كارثية. يطلب تطبيق Pinterest مثلًا من مستخدميه الجدد عناوين بريدهم الإلكتروني وهو أمر منطقي، كما يطلب منهم اختيار بعض الاهتمامات، وهو ما قد يساعد على إضفاء طابع شخصي على تجربتهم، ولكن سؤالهم عن أعمارهم يبدو شخصيًا قليلًا، وهذا ما قد يسبب ترددهم في متابعة الاستخدام. تذكر أنه يمكنك دائمًا تجنب هذا النوع من جمع المعلومات خلال التجربة في المراحل المتقدمة. ابنِ الثقة مع المستخدمين عن طريق دعوتهم والسماح لهم بتفقد التطبيق واستكشاف مزيد من المعلومات، حيث لن تتمكن من جمع المعلومات من مستخدم هجر التطبيق عند دخوله إليه. في السابق عينتني منصة تسوق للمساعدة في إعادة تشكيل تهيئة تجربتها من أجل تحسين التحولات، وكان واضحًا أن انسحاب المستخدمين كان أثناء المرور خلال النوافذ التي تطالب المستخدمين بإعطائها عددًا كبيرًا جدًا من المعلومات الشخصية، وقد تبين ذلك من خلال موازنة مسار تجربة المستخدم الجديد مع بيانات التحليلات، بالإضافة إلى إلزام المستخدم باتخاذ بعض القرارات قبل بداية استخدام التطبيق على ما يبدو. كان المستخدمون يتركون التطبيق عند صفحة تسجيل الدخول، بالرغم من أن هذه المعلومات كانت قيمةً للموقع من أجل إضفاء طابع شخصي على تجربتهم، ولذلك اتخذنا قرارًا باختصار جمع المعلومات في طلب عنوان البريد الإلكتروني فقط، كما خفضنا أسئلة تفضيلات التسوق من 8 إلى 3 أسئلة، ومنحنا المستخدم خيارات متعددةً بالإضافة إلى خيار التخطي، مما أدى إلى انخفاض فوري في معدل ارتداد المستخدمين وصل إلى 30%. لا تعتمد على الدروس التعليمية للتغطية على تجربة المستخدم السيئة تذكر أنه يجب على تطبيقك أو منتجك أن يكون منطقيًا وواضحًا قدر الإمكان بالرغم من وجود التهيئة، فالتهيئة هي أرضية للمستخدمين وليست عكازًا يتكئ عليه التصميم السيئ. حاولت الكثير من التطبيقات والمنتجات المربكة والسيئة تغطية قرارات تصميمها السيئ عبر إمطار المستخدم بوابل من التعليمات الطويلة أو من تلميحات الأدوات، هذه الممارسة التصميمية ليست جيدة، كما لن تضمن عودة المستخدمين لاستخدام التطبيق مرةً أخرى. إذا وجدت أن تطبيقك أو منتجك استمر بكونه غير مفيد مع اعتمادك على الإفراط في استخدام أنماط تهيئة، فقد حان الوقت للنظر بموضوعية وهدوء في تصميمك الجوهري والبدء بتحسينه. خدمات التهيئة إذا تناولت مع فريقك الهندسي مجموعةً من الأفكار حول إضافة إتمام المهام الموجه إلى مشروعك، فمن المحتمل أنك ستواجه قدرًا كبيرًا من المقاومة، حيث تتطلب أنماط الهيئة المعقدة الكثير من جهود التطوير، وقد تظهر حجمًا كبيرًا من مخاوفهم التقنية. هناك عدد متزايد من الخدمات والمنصات التي تقدم تهيئةً سهلةً لتجربة المستخدم لحسن الحظ، إليكم بعضها: Walkme هي خدمة معروفة بتقديمها عددًا كبيرًا جدًا من الأدوات لبناء المسارات والدروس التعليمية وتتبع مسار أداء التهيئة بطبيعة الحال. تمنح Appcues فرق التطبيقات أدوات لاعتماد تهيئة تجربة لمنتجهم مع الكثير من التتبع والتخصيص. تساعدك Nickelled في بناء جولات موجهة ونظرة عامة عن موقعك الإلكتروني أو خدمتك، وذلك باستخدام تلميحات الأدوات وتلميحات المدرب والنماذج والمزيد. استثمار بعض الوقت والبحث في صناعة الأنماط المناسبة لتهيئة خبرة المستخدم من أجل مستخدميك هو فكرة جيدة، وإدراج التهيئة الصحيحة لتجربة المستخدمين الجدد أو الموجودين على حد سواء هو أمر ضروري للمحافظة على المستخدمين وتلبية حاجاتهم. ليست التهيئة فقط لدقيقة واحدة بل هي رحلة لتأسيس الثقة مع الجمهور والمحافظة عليها، حيث ستساعد تهيئة التجربة الرائعة مستخدميك لبناء عادات قائمة على ميزات تطبيقك، والتي ستكون جزءًا من حياتهم اليومية. فهم الأساسيات تهيئة التجربة تُعَد تهيئة التجربة طريقةً لتعريف المستخدمين بميزة أو تطبيق أو منتج جديد، وتهيئة تجربة المستخدم هي تصميم مسارٍ أو سلسلة من المسارات التي تمنح المستخدم مقدمةً توجيهيةً للمنتج، وضبط بعض التفضيلات الأولية أو إظهار عناصر واجهة المستخدم المهمة. مسار التهيئة مسار تهيئة واجهة المستخدم الجديد هو ما يعرّف المستخدم بالمنتج أو التطبيق أو الميزة، وقد يشمل توجيه المستخدم لإتمام بعض المهام، مثل إعداد حساب أو إعداد التفضيلات. تهيئة المستخدم هي عملية استخدام أنماط تهيئة تجربة المستخدم لتعريفه بالميزة أو المنتج أو التطبيق الجديد، ويأمل المصممون بتوفير قابلية الاستخدام للتطبيق والمحافظة على مستخدميهم، وذلك من خلال توفير تجربة أولى جيدة للمستخدمين. ترجمة -وبتصرّف- للمقال First Impressions – A Guide to Onboarding UX لصاحبته BREE CHAPIN. اقرأ أيضًا كيفية تحسين إعدادات تطبيق بناء على تجربة المستخدم تصميم تجربة تهيئة المستخدم User Onboarding الكتابة لتجربة المستخدم UX Writing أساس التهيئة الفعالة للواجهات1 نقطة
-
لدي الكود التالي الذي يولد تمثيلاً بيانياً لمعدلات النمو في بعض الولايات: import seaborn as sns import pandas as pd import numpy as np import matplotlib.pyplot as plt State = ["NewMexico", "NewYork", "Albany","Gorgenia"] growth = [860280, 994163, 308245, 266684] df = pd.DataFrame({"State": State, "Growth": growth}) sns.barplot(x='State', y="Growth", data=df,palette="hsv_r") والخرج: ما أحتاجه هو ترتيب أعمدة البيانات هذه ضمن المخطط؟1 نقطة
-
المشكلة هي في فتح الاتصال بقاعدة البيانات من Thread ثم التعامل معها من thread اخر و الحل هو فتح الاتصال في الدالة نفسها ثم أداء التعاملات مع القاعدة ثم غلقها في الدالة @app.route('/api/v1/register', methods=['POST']) def register(): form = RegisterForm(request.form) if form.validate(): name = form.name.data email = form.email.data username = form.username.data password = form.password.data conn = sql.connect("database-name.db") cur = conn.cursor() cur.execute("INSERT INTO users(name,email,username,password) VALUES(?,?,?,?)", [name, email, username, password]) conn.commit() conn.close() أو يمكنك الحاق المعامل check_same_thread=False عند انشاء المحرك الخاص بقاعدة البيانات engine = create_engine( 'sqlite:///restaurantmenu.db', connect_args = { 'check_same_thread': False } )1 نقطة
-
ليس من الضرورة تعلم البرمجة الكائنية، فيمكن تنفيذ المشاريع بدون الاستعانة بالبرمجة الكائنية بشكل كبير والاعتماد على البرمجة الوظيفية، لكن بحسب مجال عملك فقد تضطر للتعامل مع مكتبات أو أطر عمل تتبع الطريقة كائنية التوجه في عملها فلا بد من معرفة ولو بسيطة عن هذا المجال. يمكنك القراءة عن البرمجة كائنية التوجه في المقال التالي: يمكنك قراءة المقال التالي الذي يقدم مدخلًا إلى طريقة استخدام البرمجة الكائنية التوجه في جافاسكريبت1 نقطة
-
يمكن حل هذه المشكلة بأكثر من طريقة على النحو التالي: الطريقة الأولى هي فتح إتصال بقاعدة البيانات مع تمرير المعامل check_same_thread بقيمة Flase لكي لا يظهر هذا الخطأ على الإطلاق، وهذه هي الطريقة الأسهل، لأنك لن تضطر إلى التعديل على الكود إلا في مكان واحد، كالتالي: conn = sqlite3.connect('database-name.db', check_same_thread=False) الطريقة الأخرى هي فتح إتصال بقاعدة البيانات داخل الدالة register نفسها بإستخدام الجملة with لكي يتم غلق الإتصال تلقائيًا بمجرد الإنتهاء منه: @app.route('/api/v1/register', methods=['POST']) def register(): # باقي كود الدالة هنا with sql.connect("database-name.db") as conn: name = "bob" cur = conn.cursor() cur.execute("INSERT INTO users(name,email,username,password) VALUES(?,?,?,?)", [name, email, username, password]) conn.commit() return "Successful" بهذا الشكل سوف يعمل كود SQLite بدون مشكلة.1 نقطة
-
لإضافة نصوص توضيحية نستخدم الوسيط annot ونمرر له قائمة تحتوي العبارات التوضيحية للخلايا بالترتيب كما يلي: import seaborn as sns import matplotlib.pyplot as plt import numpy as np data = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]]) text = np.array([['A', 'B', 'C', 'D', 'E'], ['F', 'G', 'H', 'I', 'J'], ['K', 'L', 'M', 'N', 'O']]) fig, ax = plt.subplots() ax = sns.heatmap(data, annot=text, fmt="") الخرج: الآن للدمج بين data و ال text يمكنك استخدام الطريقة التالية: import seaborn as sns import matplotlib.pyplot as plt import numpy as np data = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]]) text = np.array([['A', 'B', 'C', 'D', 'E'], ['F', 'G', 'H', 'I', 'J'], ['K', 'L', 'M', 'N', 'O']]) # نقوم بدمجهم يدوياً formatted_text = (np.asarray(["{0}\n{1:.2f}".format( text, data) for text, data in zip(text.flatten(), data.flatten())])).reshape(3, 5) fig, ax = plt.subplots() ax = sns.heatmap(data, annot=formatted_text, fmt="") الخرج:1 نقطة
-
للقيام بالأمر يمكنك أن تستخدام كُلاً من الدالة axvline التي تقوم برسم خط عمودي والدالة axhline التي تقوم برسم خط أفقي.حيث نقوم برسم خطين أفقين وخطين عموديين وبالتالي نشكل إطار. سنرسم الخط الأفقي الأول عند النقطة y=0، والخط الأفقي الثاني عند y=عدد الصفوف في مجموعة البيانات الخاصة بك. سنرسم الخط العمودي عند x=0 و الثاني عند x=عدد الأعمدة في مجموعة البيانات. import seaborn as sns import matplotlib.pyplot as plt example = sns.load_dataset("flights") example = example.pivot("month", "year", "passengers") res = sns.heatmap(example) # الخطين الافقيين res.axhline(y = 0, color='c',linewidth = 10) res.axhline(y = example.shape[1], color = 'c', linewidth = 10) # العموديين res.axvline(x = 0, color = 'c', linewidth = 10) res.axvline(x = example.shape[0], color = 'c', linewidth = 10) plt.show() هنا أضفنا إطار لونه أزرق فاتح (سمائي).1 نقطة
-
نعم تحتوي seaborn على العديد من لوحات التلوين: CMRmap, CMRmap_r, Dark2, Dark2_r, GnBu, GnBu_r, Greens, Greens_r, Greys, Greys_r, OrRd, OrRd_r, Oranges, Oranges_r, PRGn, PRGn_r, Paired, Paired_r, Pastel1, Pastel1_r, Pastel2, Pastel2_r, PiYG, PiYG_r, PuBu, PuBuGn, PuBuGn_r, PuBu_r, PuOr, PuOr_r, PuRd, PuRd_r, Purples, Purples_r, RdBu, RdBu_r, RdGy, RdGy_r, RdPu, RdPu_r, RdYlBu, RdYlBu_r, RdYlGn, RdYlGn_r, Reds, Reds_r, Set1, Set1_r, Set2, Set2_r, Set3, Set3_r, Spectral, Spectral_r, Wistia, Wistia_r, YlGn, YlGnBu, YlGnBu_r, YlGn_r, YlOrBr, YlOrBr_r, YlOrRd, YlOrRd_r, afmhot, afmhot_r, autumn, autumn_r, binary, binary_r, bone, bone_r, brg, brg_r, bwr, bwr_r, cividis, cividis_r, cool, cool_r, coolwarm, coolwarm_r, copper, copper_r, cubehelix Accent, Accent_r, Blues, Blues_r, BrBG, BrBG_r, BuGn, BuGn_r, BuPu, BuPu_r, ويمكنك استخدام أيّاً منها من خلال الوسيط palette كما يلي: data_df = df.melt(var_name='Pulses', value_name='Tons Consumed') sns.boxplot(x="Pulses", y="Tons Consumed", data=data_df, palette="Set1") كما يمكنك إنشاء لوحة ألوان خاصة بك لتلوين ال boxplot كما يلي: # تعريف قائمة تحتوي الألوان بالترتيب my_colors = [ "#3498db","#9b59b6","#2ecc71", "#006a4e"] # ونمرر لها قائمة الألوان set_palette نستخدم الدالة sns.set_palette( my_colors ) # boxplot الآن نستدعي ال sns.boxplot( x = "Pulses", y = "Tons Consumed", data = data_df)1 نقطة
-
ليست هناك قواعدُ تنجح بالنسبة لجميع الناس؛ وبما أني عملتُ مستقلًا على نحو متقطع لأكثر من عشر سنوات، فقد أنشأتُ قائمةً تتضمن أفضل النصائح حول كيفية تحقيق النجاح في هذا المجال. ربما تكون أيها القارئ تطبّق فعلًا بعضَ تلك النصائح أو أمورًا مشابهة لها، وهذا عظيم، ويَحدُوني أملٌ في أن تعثرَ على نصيحة على الأقل، أو على ثلاث، يمكن أن تساعدك على النجاح فيما تفعله. وبهذا الصدد، إليك أهم نصيحة على الإطلاق في هذا الشأن: أنت الآن في عصر صناعة تصميم الويب سريعةِ التغيُّر، وهذا يجعل لزامًا عليك ألا تتوقف عن التعلُّم، ولكنّ في نفس الوقت عليك أن تُحِبَّ ما تفعله للنجاح فيه؛ وعندما تحقق ذلك النجاح، ستتمكن من تقديم خدماتٍ نهائية أعلى مستوىً لعملائك، وتضاغف بفضل ذلك ما تتفاضاه من مال لقاء عملك مستقلًا في نهاية المطاف. 1. أنشئ خطة تجارية أو تسويقية هذا أول ما عليك فعلُه؛ وحتى لو جمّعت في ذهنك الأفكارَ المطلوبة، فستحقق كتابتُها على الورق الكثيرَ من التقدم، وستستحق بلا شك الجهدَ الإضافي المبذول لهذا الغرض، فإنجاز ذلك لا "يدفعُكَ" فقط إلى التفكير مليًّا في مختلف المسائل المهمة ذات الصلة، وفي استشراف التحديات المحتمَلِ ظهورُها قبل أن تحدُث، ولكنه أيضًا قد يسهِّلُ عليك كثيرًا الحصولَ على المساعدة المطلوبة من الشركاء أو المستثمرين التجاريين المحتملين عندما تكون بحوزتك خطة تجارية جيدة تعرضها عليهم. عليك معرفة كيف ستعثر على عملاء، وأن تمتلك خطةً قابلةً للتطبيق. 2. خطط لأيامك مسبقا خصِّص لنفسك ساعةً أو ما شابه عند بداية كل أسبوع عمل، أو في آخر ساعة عمل من الأسبوع، وذلك للتخطيط للأسبوع المقبِل. بذلك سيسهُل عليك التخطيطُ للكيفية التي ستُمضي فيها ذلك الوقت بهدف التقيّد بالمواعيد النهائية المستقبلية المحدَّدة لإنهاء العمل. تزداد أهميةُ ذلك بازدياد المشاريع المستمرة التي تعمل عليها. 3. استخدم برمجيات مجانية ولكن اشتر بعض الأدوات الفاخرة التي ستجعلك أكثر إنتاجية قد يمثّلُ البدءُ بالعمل بصفتك مستقلًا تحدّيًا من الناحية الاقتصادية؛ ومن شأن انتقائك لبرمجيات مجانية وجيدة أن يوفّر عليك كثيرًا من التكاليف دون أن تضطرّ بالضرورة إلى التخلّي عن كثير من المقومات الوظيفية. فمجانيةُ البرمجيات لا تعني دائمًا أنها غير جيدة، وهناك المزيد والمزيد من الخيارات المتاحة كل يوم؛ لذا فلتحرِص على التحقق مما يمكن استخدامه منها بشأن عملك. وعندما تشتري جهاز حاسوب أو كاميرا أو جهازًا لوحيًا أو طابعة، تحقق أيضًا من البرمجيات التي تأتي مع كل من تلك الأجهزة؛ فقد تكون بصدد تلقّي مفاجأة إيجابية. لا تحاول شراء كل شيء، بل اشترِ فقط الأدوات الفاخرة التي سوف تستخدمها كل يوم؛ فأنا مثلًا لا أستخدم إطلاقًا قوالبًا مجانيةً عند تأسيس موقع إلكتروني؛ بل أختار دائمًا قوالب وإطارات عمل ووردبريس ذات جودة. ولكن، أكرر القول إنك لا تحتاج إلى تكبُّد النفقات على ما تحدثنا عنه في المثال السابق إذا كنت تعمل في تصميم الرسومات مثلًا؛ أما إن كنت تصمم مواقعًا إلكترونيةً بانتظام لعملائك، فيهمّك كثيرًا فعلُ ذلك لتزيد إنتاجيتك بعشرة أضعاف. 4. صمم شعارا جذابا يتطلب تكريسُ هُوية احترافية فريدة لنفسك تضمنُ لك التميُّزَ، ضرورة بذلَ جهد شاقّ لكي تظهر بمظهر احترافي وتجذبَ العملاء المحتملين، فتصميمك لشعار جذّاب (أو الطلب من مختصٍ إنجاز ذلك لك، إذا لم يكن لديك المهارات اللازمة لفعله بنفسك) مِن شأنه جعلُك تبدو أكثر احترافيةً وأسهل اكتشافًا من جانب العملاء المحتملين، فامتلاك شعار مميز، واستخدامه على بطاقات العمل Business Cards، والمواقع الإلكترونية وغير ذلك، سيمنحك تلك الإطلالة الاحترافية التي قد تُكمِل النقصَ المطلوب للحصول على عملاء جدد. 5. تعلم أن تقول لا إن لم يكن لديك الوقت الكافي لعميل آخر في الوقت الحالي، فمن المهم أن تدرك ذلك وتقول لا؛ فذلك هو الخيار الأنسب لك، وللعميل الذي تُنجِز له عملًا في الوقت الحالي، وللعميل أو العملاء الذين يقصدونك للحصول على خدماتك. ومن أسوأ الخيارات أن تقبل العمل لصالح عدة عملاء في آن معًا، بحيث يتضرر العميل أو العملاء الذين تنجز لهم عملًا في ذلك الوقت. إذًا عليك الحرص دائمًا على تكريس وقت كافٍ لتقدّم أفضل ما تستطيع من خدمة لعملائك الحاليين؛ فعملُك لعدد كبير من العملاء في الوقت ذاته قد يُضعِف جودة أدائك في جميع تلك المهام التي تنجزها. 6. أنشئ مدونة أو موقعا إلكترونيا في عصر الإنترنت الذي نعيش فيه، يمكن أن يضيف امتلاكُك موقعًا إلكترونيًا الكثير إلى عملك، فلا يجعلك ذلك تبدو أكثر احترافيةً فحسب، بل يفتح لك الباب أيضًا إلى جذب عملاء جدد، فالكثير من العملاء يتصفحون الإنترنت بحثًا عن أشخاص ينجزون لهم مشاريعهم المستقبلية، وإذا لم يجدوك هناك، فلن يعلم بك أحد. 7. حدث موقعك الإلكتروني بانتظام هل تمتلك بالفعل مدوَّنة أو موقعًا إلكترونيًا؟ عظيم إن كان جوابك هو نعم، ولكن ذلك لا يكفي؛ بل عليك تحديث ذلك الموقع أو المدوّنة بانتظام إن أردت زيادة قيمة أيٍّ منهما، فإذا زار عميلٌ موقعكَ الإلكتروني، ثم وجد أنك لم تحدّّثه منذ زمن طويل جدًا، فقد يدفعه ذلك إلى اختيار مستقلٍ غيرك لإنجاز عمله. يتطلب تحديث موقعك الإلكتروني حوالي ساعة من وقتك بين الفينة والأخرى، لكنه يمكن أن يعود عليك بنتائج ممتازة تتمثّل في اجتذاب عملاء جدد. 8. امنح زوارك على الإنترنت شيئا مجانيا من الجيد دائمًا أن تمنح مزايا إضافية لزائري موقعك الإلكتروني، فإذا كنت تعمل في مجال التصميم، يمكنك التفكير في إضافة ملمس بصري أو أزرار مجانًا؛ فمن شأن ذلك أن يجذب مزيدًا من الزوّار إلى موقعك الإلكتروني، وقد يستقطب أيضًا عملاء جدد يطلبون الحصول على خدماتك. أو ما رأيك في أن تمنح خصمًا -في حدود نسبة مئوية محددة- لكل مَن يزور موقعك الإلكتروني على أول طلب يكلّفك بإنجازه له؟ نؤكد لك مجددًا أن ذلك قد يجعلك تغدو مميزًا بحيث تجذب عملاء جدد. 9. استخدم وسائل التواصل الاجتماعي باتت وسائلُ التواصل الاجتماعي في يومنا هذا مكانًا تُنسَج فيه العلاقات بين الأشخاص؛ فباستخدام تلك المنصات يمكنك التواصل مع عملاء وشركاء محتملين من حول العالم بصرف النظر عن مكان إقامتك. ومن الأساسيّ أن تمتلك حسابًا على تويتر Twitter، كما عليك التفكير بإنشاء حساب على فيسبوك Facebook، والاشتراك بمنتديات ذات صلة بالخدمة التي تقدّمها والعمل الذي تمارسه بوصفك مستقلًا. وإذا كنت تعمل في مجال التصميم، فلتطلع على يوتيوب YouTube، وعلى الشبكة الاجتماعية ديفيانت آرت deviantArt أيضًا. بوسعك الترويج لعملك على العديد من وسائل التواصل الاجتماعي مثل التي أتينا على ذِكرها أعلاه، بشرط ألا تُرسل عددًا كبيرًا من الرسائل على تلك المنصات لأشخاص لم يطلبوها، كما هو الحال بالنسبة لرسائل البريد الإلكتروني المزعجة غير المرغوب فيها Spam. 10. اعثر على حلفاء قد يعني الكثيرَ وجودُ حلفاء لك؛ فالتواصل مع الآخرين عبر وسائل التواصل الاجتماعي، أو حتى نشرُ سمعة حسنة لعملك من خلال أفراد أسرتك وأصدقائك، قد يروّج لعملك على النحو الذي تحتاج إليه، كما قد يُفيدك إنشاءُ علاقات مع أشخاص بوسعهم تقديم خدمات للعملاء لا يمكنك أنت تقديمُها؛ إذ تغدو بذلك قادرًا على توفير حزمة خدمات أوسع يحتاج إليها عملاؤك. فإذا أحلتَ أحد عملائك إلى شخص تعرفه وبوسعه تقديم خدمة مناسبة لذلك العميل، فقد يأتي يومٌ تجد فيه أن أحد أولئك الحلفاء وصَلَك بعميل يحتاج إلى خدمتك. 11. ادخر للأيام الصعبة رغم أن عملك قد يسير على خير ما يُرام، فلا بد كل فترة من أن يمرّ شهر أو اثنان لا يكون الوضع فيهما كذلك. فكونُك مستقلًا يعني أنك ستتأثر بالتغيرات التي تطرأ على السوق، ونصيحتي لك هنا أن تدخر جزءًا من المال الذي تجنيه كل شهر؛ ادّخر ذلك المال في حساب توفيرٍ خاص بك تجعله بمثابة حاجز أمانٍ مالي عندما تمر فترات لا تحصل فيها على عمل. وتأكّد أنك لن تندم على فعل ذلك؛ إذ لا يليق بك أن تُفسِدَ عليك بعضُ الفواتير القليلة كلَ شيء في حياتك في شهر لا تحصل فيه على عمل. 12. كن مبدعا هناك عدة طرق لتكون مبدعًا، ولتحصل على عملاء جدد، ولتحقيق استغلال أفضل للتجهيزات والمساحة المكتبية. تتضمن بعضُ الأمثلة الإبداعية تحديثَ حاسوبك إذا لم تكن قادرًا على شراء واحد جديد، أو إعادة ترتيب غرفتك في المنزل لتحصل على مساحة كافية للعمل إذا لم تستطع تحمل تكاليف استئجار مكتب خارج منزلك، أضف منتجًا أو خدمةً جديدةً إلى القائمة الحالية التي تتضمن المنتجات والخدمات التي تقدمها، أو اسأل أفراد أسرتك وأصدقاءك إذا كانوا يعرفون أحدًا بحاجة إلى خدماتك. وهنا ستكون أمامك خيارات عديدة، وكل ما تحتاج إليه أن تفكّر بإبداع. 13. كافئ العملاء ذوي الولاء في سوق تشهد تنافسًا مستعِرًا، عليك بذل جهدك لضمان أن يعود إليك العملاء الذين قدّمتَ لهم خدمات طالبين الاستعانة بك مجددًا. إن التعامل بودٍّ مع العملاء، وتبنّي ذهنية تقديم الخدمات على نحو يترك انطباعًا حسنًا لديهم، شرطان ينبغي توافرهما لديك دائمًا، ولا تنازُلَ عنهما بأي شكل، لكن ما رأيك بتقديم حسم للعميل الذي يقصدك مرةً أخرى طالبًا خدماتك؟ أو ما رأيك بإرسال عروضٍ خاصة لهم متعددة الأنواع؟ استخدِم خيالك، وطبِّق هذه الأمور ضمن خطة العمل الخاصة بك. اجعل العميل راغبًا في العودة إليك؛ وستحظى بأفضل فرص الاستمرارية الممكنة. 14. عامل كل عميل كما لو أنه الوحيد لديك من المهم إذًا تقديم عروض لعملائك كما أشرنا في النصيحة السابقة، ولكن تذكَّر أن عليك أن تتبنى ذهنية تقديم الخدمات لعملائك على نحو يجعلهم راضين؛ فإذا أحسَّ العميل بأنه مُحاطٌ باهتمام وتقدير، فسيغدو ذا ولاء لك. استخدِم لغةً إيجابيةً لدى الحديث مع العميل أو الكتابة له. ولا تخشَ القول له إنك ستبذل جهودًا استثنائيةً لضمان أن تحظى الخدمة أو المنتج الذي تقدمه له برضاه التام، واحرص على إشعار عميلك بأنك تقدّر التقييم والملاحظات التي يوجهها لك. إنّ اتباعك لما سبق ذِكره يتيح لك جعلَ خدماتك جذّابة، ويحقق رضا عملائك. ولا تنسَ أنّ عملاءك الحاليّين قد يمثّلون أفضَل مَن يروِّج لك. 15. لا تشتت نفسك في وقت العمل إذا قررتَ العمل من الساعة الثامنة صباحًا إلى الرابعة بعد الظهر مثلًا، فلتنفّذ ذلك، وإذا كانت هناك حوائج عليك قضاؤها، أو حسابات بريدية خاصة تود تفقّدها، أو مكالمات هاتفية شخصية أو غيرها، فمن شأن تلك الأمور أخذ كثير من وقتك الذي أنت بحاجة ماسّة إليه في عملك. تعهّد لنفسك بألا تفعل ذلك إلا عندما لا يكون لديك عمل، أو قبل البدء به أو بعد الانتهاء منه، أو أثناء استراحة الغداء. قد لا يبدو ذلك عبئًا ثقيلًا عليك، ولكنني رأيتُ العديد من المستقلين الناجحين الذين تُفسد الفوضى يومهم لأنهم لم يكونوا ماهرين في إدارة وقتهم على نحو صحيح. 16. اعرف متى تبدأ ومتى تتوقف لا يقل أهميةً عما ذكرناه في الفقرة السابقة، أن تبدأ عندما يجب أن تبدأ، وتتوقف عندما ينبغي لك أن تتوقف. قد يكون عليك الاستعداد للعمل لساعات إضافية بين الفينة والأخرى للحفاظ على استمرارية عملك، ولكنّ من الضروري أن تخصص لنفسك وقت فراغ أيضًا؛ فأنت بحاجة إلى التعافي، وإشغال ذهنك بأمور أخرى، وإلا أُصِبتَ بالاحتراق الوظيفي burnout وأفسدتَ حياتك. فكما طالت ساعاتُ عملك في كل مرة، قلَّت إنتاجيتُك. لذا احرص على اتّباع قواعدك الخاصة حول توقيت بدء العمل من جهة والتوقف عنه من جهة أخرى. 17. رتب أمورك المالية يبدو تحقيق ذلك سهلًا، ويمكن أن يكون كذلك فعلًا ما دمتَ تراقب أمورك المالية بانتظام. وبصرف النظر عن حجم المشروع التجاري أو العمل الذي تُديره، فستقع في مأزق إن كنت لا تنفق المال على دفع فواتيرك وحساباتك إلا مرةً أو مرتين في السنة. حدد مواعيدًا تدفع فيها الفواتير المترتبة عليك، وأخرى ترسل فيها فواتيرَ إلى عملائك، وتواريخَ تعدّ فيها ميزانيتك الشهرية. إن التزامك بذلك لن يسهّل الأمور عليك طول العام فحسب، بل من شأنه أيضًا أن يمكّنك من تصحيح الأخطاء على نحو أسرع، وإجراء التعديلات كلما دعتِ الحاجة. 18. لا تنس أن تتنفس هل سمعتني؟ أقول "تتنفس"؛ وأقصد بذلك أنك بحاجة إلى الاعتناء بنفسك. قد تكون تنجز عملك الحر باستخدام حاسوب أو اثنين، أو كاميرا، أو غير ذلك من أدوات؛ لكن الأداة الأهم من ذلك كله هو "أنت". لا تنسَ قضاء وقتٍ تمارس فيه هواياتك، والالتقاء بأصدقائك وأفراد عائلتك، حتى ولو كان جدول عملك يغُصُّ بالمهام. 19. اخرج من منزلك بين الحين والآخر (خاصة إن كنت تعمل من المنزل) إذا كان منزلك هو مكان عملك، فمن المهم أن تخرج منه من وقت لآخر. رتِّب بعضَ اجتماعاتك في مكان آخر، والتقِ بشركاء العمل خارجًا على الغداء، أو اعمل لساعة أو ساعتَين من مكتبة أو مقهى باستخدام حاسوبك المحمول إن أمكنك ذلك؛ فتغيير المشاهد المحيطة بك يمكن أن يعزز مستوى طاقتك وإبداعك، ويعيد لك كثيرًا مما فقدتَ. 20. اصنع خيطا تحفيزيا لا تستمرُّ الأيامُ العصيبة أبدًا، بل تأتي وتذهب. وبهذه البساطة، فإنّ وجود شيء ما حولك، يذكّرك بالسبب الذي تعمل من أجله بهذا الجِدّ. قد يكون كل ما تحتاج إليه للحصول على طاقة إضافية في أحد تلك الأيام الصعبة، لذا كوِّن ذلك الخيط التحفيزي. خذ قطعة خيط واستخدم لوحَ فلّين أو لوحًا أبيضًا حسب المتوفر لديك. ضع صورةً لأطفالك أو للوجهة التي تود قضاء العطلة فيها والتي تدّخر المال من أجلها، أو ربما للسيارة التي تحلم في شرائها. أضِف بعض الاقتباسات أو الصور التحفيزية، أو أي شيء من شأنه أن يمدك بذلك التحفيز حقًا؛ وها أنت ذا قد كوّنتَ ذلك الخيط التحفيزي الذي يصنعُ العجائبَ النظرُ إليه في كل مرة تكون فيها على وشك الاستسلام، أو عندما تمرّ بيوم ترزح فيه تحت ضغطٍ هائل. 21. تحل بالتواضع لم يُولَد أحدٌ خبيرًا أو بطلًا للعالم؛ فإذا سارت الأمور معك جيدًا أو شعرتَ بأنك تسيطر على الوضع، فمن السهل أن تكتسب ثقةً زائدةً بنفسك، وهو ما يمكن أن يسيئ إلى سُمعتك وإلى وجودة عملك أيضًا. عليك دائمًا التحلّي بالتواضع، والإصغاء إلى عملائك حول ما يريدون منك. أعطهم رأيك الاحترافي عند الحاجة، ولكنّ هُم مَن يضمنون استمرارية حصولك على أجر. احرص دائمًا على طلب نصيحة من زملائك أو غيرهم ممن لهم باعٌ طويل نسبيًا في السوق التي تعمل فيها. 22. اظهر بمظهر احترافي بكل الطرق الممكنة بات الآن لديك شعارٌ وموقع إلكتروني وغيرهما، وبدأت الأمور تبدو على ما يُرام بالنسبة لك. احرص على معاملة عملائك باحترام والظهور بمظهر لائق، وكن مهذَّبًا؛ فأن تكون مديرَ نفسِك، لا يعني أنّ بوسعك التحدُّث أو التصرُّف بأي طريقة كانت والمحافظة على عملائك في الوقت ذاته. لا تنسَ ذلك؛ فعدم مراعاة ما سبقَ ذِكرُه كفيلٌ بجعل عملائك يَنفضُّون من حولك ويبحثون عن مستقل غيرك. 23. اطلب تقييما لا يكفي أن تحصل على تعلقيات تتيح إبداءها على موقعك الإلكتروني؛ لكن عليك طلب تقييمات من أصدقائك أو أفراد أسرتك أو حلفائك حول عملك. والأهم من ذلك كله هو أن تطلب من عميلك الذي أنهيتَ له مشروعًا ما أن يخبرك برأيه في عملك على ذلك المشروع بالتحديد؛ فذلك لا يعطيك فرصةً ممتازةً لتطوير نفسك فحسب، بل ويُشعِر العميلَ بالأهمية وبأنك تُفرِد لرأيه مساحةً مهمة. ومن الجيد أيضًا أن تأخذ دائمًا رأيَ شخص آخر غير المذكورين أعلاه، وهو ما من شأنه مساعدتك في أن تغدوَ أكثر نجاحًا. 24. احمل دفترا معك حيثما ذهبت عليك دائمًا حملُ دفترٍ معك؛ سواءٌ أكان دفترًا ورقيًا، أو باستخدام هاتفك الجوال، أو غيره من الصور الرقمية للدفتر، وتذكّر أن تدوّن عليه ملاحظات. ولذلك أسباب عديدة؛ إذ لا تقتصر فائدته على أنك قد تصادف عميلًا محتملًا أو حاليًا، بل قد تخطر ببالك أفكار قيّمة عندما تكون مستقلًا الحافلة، أو على متن الطائرة، أو في أي مكان آخر، فقد خطرت لي أفكار عظيمة في مرات عديدة، ثم نسيتُها لأنني لم أكن أحمل دفترًا، وتفاجأت بأنّ أحدًا غيري استخدم تلك الأفكار في مكان ما بعدها بسنة. 25. خذ ما تحتاج إليه من وقت هذه نصيحة بالغة الأهمية، ولا يمكن الاكتفاء بالتشديد عليها؛ فمثلما هو الحال بالنسبة للنصيحة التي تعلّمك أن تقول لا، التي ذكرناها أعلاه؛ عليك عندما تستلم مشروعًا أن تحرص كل الحرص على أخذ الوقت المطلوب لتقديم أفضل ما لديك في سبيل إنجازه، فتسليم مشروعٍ بجودةٍ دون المطلوبة لن يجعل العميل يمتنع عن تسليمك مشاريع مستقبليةً فقط، بل وسيضرّ بسمعتك إلى حد بعيد، فعملاؤك هم أهم جهة مرجعية حولك مستقبلًا، ولا أحد يريد العمل مع مستقل لا يُنهي عمله على النحو الذي يفترَض به تقديمه. وفي الخلاصة، أضمن لك أن اتباعك لما سبق مِن نصائح سيوفر عليك كثيرًا من العناء المرتبط بالعمل المستقل، وستتلمس الأثر الذي يتركه اتباعُ كل نصيحة منها في تحسين جودة عملك وحياتك عمومًا. ترجمة وبتصرف للجزء اﻷول من مقال How To Become a Freelancer That Is On Track Of Success. اقرأ أيضًا كيف تُدير وقتك لتتقن عملك كعامل مُستقل كيف تصبح كاتبًا مستقلًا مدفوع الأجر كيف تبدو الشّهور الأولى من العمل ككاتبٍ مستقل؟ الأدوات والخطوات اللّازمة لانطلاقة صحيحة في عالم العمل الحر ما هو العمل الحر وما هي أهم منصّات العمل للمُستقلّين1 نقطة
-
يمكنك استخدام الوسيط cbar_kws للقيام بذلك حيث نمرر له قاموساً يحتوي المفتاح shrink ومن خلال قيمة هذا المفتاح يمكننا التحكم بحجمه، فبشكل افتراضي يكون 1، وبالتالي أي قيمة أقل من 1 تؤدي لتصغيره وأي قيمة أكبر من واحد تؤدي لتكبيره. import numpy as np; np.random.seed(0) import seaborn as sns; sns.set_theme() uniform_data = np.random.rand(10, 12) ax = sns.heatmap(uniform_data, cbar_kws={'shrink': 0.5}) الخرج:1 نقطة
-
يمكنك تغييرها من خلال استخدام الوسيط rc ضمن الدالة set حيث نمرر له قاموساً مفاتيحه هي axes.facecolor وقيمته تمثل لون ال axes (أي لون المكان الذي يتم فيه رسم الشكل البياني) و figure.facecolor وقيمته تمثل لون ال figure (الحاوية الكلية). import seaborn as sns import matplotlib.pyplot as plt # loading dataset data = sns.load_dataset("iris") # draw lineplot sns.lineplot(x="sepal_length", y="sepal_width", data=data) # هنا سنجعل اللون أحمر للمحور وأزرق للحاوية sns.set(rc={'axes.facecolor':'red', 'figure.facecolor':'blue'}) plt.show() الخرج: حل آخر من خلال الدالة set_style التي تأخذ القيم التالية ticks - white - dark - darkgrid - whitegrid: import seaborn as sns import matplotlib.pyplot as plt # loading dataset data = sns.load_dataset("iris") # draw lineplot sns.lineplot(x="sepal_length", y="sepal_width", data=data) sns.set_style("dark") plt.show() الخرج:1 نقطة
-
يمكنك القيام بذلك من خلال الدالة plt.ylim للمحور العمودي و plt.xlim للمحور الأفقي، حيث نمرر له القيمة الصغرى والعليا. from matplotlib import pyplot as plt import seaborn as sns plt.rcParams["figure.figsize"] = [7.50, 3.50] plt.rcParams["figure.autolayout"] = True sns.set_style("whitegrid") tips = sns.load_dataset("tips") ax = sns.boxplot(x="day", y="total_bill", data=tips) plt.ylim(5, 50) plt.show() الخرج: أو من خلال ax.set_ylim و ax.set_xlim: from matplotlib import pyplot as plt import seaborn as sns plt.rcParams["figure.figsize"] = [7.50, 3.50] plt.rcParams["figure.autolayout"] = True sns.set_style("whitegrid") tips = sns.load_dataset("tips") ax = sns.boxplot(x="day", y="total_bill", data=tips) ax.set_ylim(5, 50) plt.show() والنتيجة نفسها.. أو من خلال ax.set(ylim=(5, 50)).1 نقطة
-
1 نقطة
-
يمكنك التحكم بحجم الخط من خلال sns.set والوسيط fontsize كما في المثال التالي: import pandas as pd import matplotlib.pyplot as plt df = pd.DataFrame({"Day 1": [7,1,5,6,3,10,5,8], "Day 2" : [1,2,8,4,3,9,5,2]}) import seaborn as sns sns.set() # نستخدمها قبل الرسم لضبط كل شيء على الحالة الافتراضية p = sns.lineplot(data = df) p.set_xlabel("X-Axis", fontsize = 20) # تحديد حجم تسمية المحور الأفقي p.set_ylabel("Y-Axis", fontsize = 20) # تحديد حجم تسمية المحور العمودي p.set_title("Plot", fontsize = 20) # تحديد حجم العنوان plt.legend(labels=["Legend_Day1","Legend_Day2"], fontsize = 20) # legend تحديد حجم ال الخرج:1 نقطة
-
يمكنك تغيير موقعه من خلال ضبط الوسيط legend في الدالة factorplot على false (لكي لايقوم بعملية إضافة تلقائية له). ثم استخدام الدالة plt.legend لإضافته في الموقع المطلوب: import seaborn as sns import matplotlib.pyplot as plt sns.set(style="whitegrid") titanic = sns.load_dataset("titanic") g = sns.factorplot("class", "survived", "sex", data=titanic, kind="bar", size=6, palette="muted", legend=False) g.despine(left=True) plt.legend(loc='upper left') # في الزاوية العليا اليسارية g.set_ylabels("survival probability") ويمكن تمرير القيم التالية أيضاً: 'upper left', 'upper right', 'lower left', 'lower right' 'upper center', 'lower center', 'center left', 'center right' الخرج:1 نقطة
-
يمكنك وضع عنوان عام من خلال fig.suptitle كما يلي: # plt.xticks(rotation=45) # ax.tick_params(axis='x', rotation=90) import seaborn as sns tips = sns.load_dataset('tips') rp = sns.relplot(data=tips, x='total_bill', y='tip', col='sex', row='smoker', kind='scatter') rp.fig.subplots_adjust(top=0.9) rp.fig.suptitle('ONE TITLE FOR ALL') والخرج: وكحل آخر يمكنك استخدام plt.suptitle كما يلي: import seaborn as sns import matplotlib.pyplot as plt tips = sns.load_dataset('tips') rp = sns.relplot(data=tips, x='total_bill', y='tip', col='sex', row='smoker', kind='scatter') rp.fig.subplots_adjust(top=0.9) plt.suptitle("Title")1 نقطة
-
إن أتممت تعلم اللغة نفسها، ستحتاج إلى التأكد من إتقانك للغة من خلال عمل مشاريع وبرامج بسيطة للغاية، لأنه عمل برامج بسيطة سوف يساعدك على التأكد من فهمك للغة نفسها وسيساعدك على إكتساب مهارة حل المشاكل Problem Solving، كما ستتعلم أشياء جديدة في كل مشروع تقوم به. تستطيع أن تبدأ بعمل برامج بسيطة للغاية، وتقوم هذه البرامج بحل مشكلات تواجهك أنت أو مشكلة تواجهة بعض الأشخاص بشكل عام، على سبيل المثال، تستطيع عمل برنامج بسيط يقوم بتوليد كلمات مرور عشوائية، ويمكن للمستخدم أن يقوم بإختيار ما إذا كانت كلمة السر التي سيتم توليدها تحتوي على رموز أو لا، أو يمكنك أن تقوم بعمل برنامج بسيط يعرض حالة الطقس لأيام الأسبوع المقبل .. إلخ، (يمكنك البحث عن "أفكار لبرامج بسيطة" في جوجل وسوف تجد عشرات الأفكار التي يمكنك القيام بها). بالتأكيد قد تجد نفسك لا تعرف من أين تبدأ أو كيف تقوم بعمل البرنامج ككل، وهنا يكمن جزء التعلم، حيث يجب أن تقوم بالبحث بنفسك عن كيفية حل المشاكل التي تواجهك والبحث عن معلومات أضافية في مكتبات اللغة وكيفية إستخدامها لحل مشكلة معينة، وبذلك سوف تحصل على القدرة على البحث وإكتساب مزيد من المعرفة. بعد أن تقوم بعمل الخطوات السابقة، وبعد إتمام عدد من المشاريع، يمكنك أن تقوم بالبحث عن مشاريع حقيقة تقوم بها، مثل إنشاء Backend لمدونة من خلال إطار عمل مثل Flask أو Django أو ربما تبدأ في تعلم الذكاء الإصطناعي أو مجال تحليل البيانات الضخمة .. إلخ، وهنا سوف تتعلم المزيد من الأمور قبل أن تبدأ في تعلم المجال نفسه، مما سيزيد من معرفتك وقدرتك على إنشاء المزيد من البرامج .. إلخ.1 نقطة
-
يجب أن تقوم أولًا بجلب البيانات التي تريدها من قاعدة البيانات، وهذه العملية تتم داخل المتحكم Controller، كالتالي: $users = User::where('name', 'Sameh')->get(); return view('view-name', compact('users'); بهذا الشكل تم جلب البيانات من قاعدة البيانات وتم تمريرها إلى الملف view-name.blade.php يمكنك الآن أن تقوم بعمل حلقة تكرار foreach لطباعة بيانات المستخدمين في الملف view-name.blade.php، على النحو التالي: @foreach ($users as $user) <div> <span>Name: {{ $user->name }}</span> <span>Phone: {{ $user->phone }}</span> </div> @endforeach1 نقطة
-
يمكنك إستخراج البيانات بشكل بسيط ومرتب من خلال تحديد كل الكتب ثم المرور على كل كتاب وإستخراج بياناته، كالتالي: from bs4 import BeautifulSoup import pandas as pd content = open("books.xml",'r', encoding="utf-8").read() soup = BeautifulSoup(content, features='lxml') # هنا سيتم تخزين بيانات كل كتاب data = [] # نحدد كل الكتب books = soup.find_all('book') # الآن نقوم بالمرور على كل كتاب وتخزين بياناته في القائمة data for book in books: book_d = {} # بيانات الكتاب الواحد book_d['author'] = book.find('author').get_text() book_d['title'] = book.find('title').get_text() book_d['genre'] = book.find('genre').get_text() book_d['price'] = book.find('price').get_text() book_d['publish_date'] = book.find('publish_date').get_text() book_d['description'] = book.find('description').get_text() data.append(book_d) # الآن نقوم بتحويل القائمة data إلى dataFrame df = pd.DataFrame(data) # لا نحتاج إلى تحديد الأعمدة لأننا أستخدمنا قائمة من القواميس dictionaries print(df) وستكون النتيجة كالتالي: author title genre price publish_date description 0 Gambardella, Matthew XML Developer's Guide Computer 44.95 2000-10-01 An in-depth look at creating applications with... 1 Ralls, Kim Midnight Rain Fantasy 5.95 2000-12-16 A former architect battles corporate zombies, ... 2 Corets, Eva Maeve Ascendant Fantasy 5.95 2000-11-17 After the collapse of a nanotechnology society... 3 Corets, Eva Oberon's Legacy Fantasy 5.95 2001-03-10 In post-apocalypse England, the mysterious age... 4 Corets, Eva The Sundered Grail Fantasy 5.95 2001-09-10 The two daughters of Maeve, half-sisters, batt... 5 Randall, Cynthia Lover Birds Romance 4.95 2000-09-02 When Carla meets Paul at an ornithology confer... 6 Thurman, Paula Splish Splash Romance 4.95 2000-11-02 A deep sea diver finds true love twenty thousa... 7 Knorr, Stefan Creepy Crawlies Horror 4.95 2000-12-06 An anthology of horror stories about roaches,c... 8 Kress, Peter Paradox Lost Science Fiction 6.95 2000-11-02 After an inadvertant trip through a Heisenberg... 9 O'Brien, Tim Microsoft .NET: The Programming Bible Computer 36.95 2000-12-09 Microsoft's .NET initiative is explored in det... 10 O'Brien, Tim MSXML3: A Comprehensive Guide Computer 36.95 2000-12-01 The Microsoft MSXML3 parser is covered in deta... 11 Galos, Mike Visual Studio 7: A Comprehensive Guide Computer 49.95 2001-04-16 Microsoft Visual Studio 7 is explored in depth...1 نقطة
-
يمكنك أن تقوم بعمل عنصر جديد من خلال التابع new_tag ثم تقوم بإضافة العنصر العناصر الأبناء إليه، كالتالي: from bs4 import BeautifulSoup soup = BeautifulSoup('<p> sometexthere </p>', features='lxml') # إنشاء العناصر div_element = soup.new_tag('div', **{"class":"container"}) # يمكنك أن تضيف خصائص أيضًا من هنا i_element = soup.new_tag('i') # إحاطة النص بالعنصر i soup.p.string.wrap(i_element) # إضافة كل العناصر إلى العنصر div الذي قمنا بإنشائه body_children = list(soup.body.children) for child in body_children: div_element.append(child) # إزالة كل العناصر من جسم الصفحة soup.body.clear() # إضافة العنصر div الذي يحتوي على كل العناصر إلى جسم الصفحة soup.body.append(div_element) print(soup.prettify()) """ <html> <body> <div class="container"> <p> <i> sometexthere </i> </p> </div> </body> </html> """1 نقطة
-
يمكنك إستخراج كل الروابط في صفحة ما وتقسيم هذه الروابط إلى روابط داخلية internal links (روابط لصفحات أخرى أو أماكن مختلفة في نفس الصفحة) وروابط خارجية external links (روابط تؤدي إلى مواقع آخرى)، على النحو التالي: # لعمل الطلبات import requests # لإستخرج الروابط من مستند HTML from bs4 import BeautifulSoup # لإستخرج نطاق الموقع domain من الروابط import urllib.parse if __name__ == '__main__': user_input_url = "https://github.com" domain = urllib.parse.urlparse(user_input_url).netloc # فحص إتصال الإنترنت try: website_content = requests.get(user_input_url.strip()).text except: check_internet = requests.get('https://google.com').status_code if check_internet != requests.codes.ok: raise ConnectionError("ERROR: Check internet connection.") _soup = BeautifulSoup(website_content, features='lxml') internal_url_links = [] external_url_links = [] for link in _soup.find_all('a', href=True): if link.get('href'): url_domain = urllib.parse.urlparse(link.get('href')).netloc # Absolute links if domain == url_domain: internal_url_links.append(link.get('href')) # Relative links # كل الروابط النسبية تبدأ بأحد الرموز التالية elif link.get('href')[0] in ['/', '#', '?']: internal_url_links.append(urllib.parse.urljoin(user_input_url, link.get('href'))) # external url # إذا كان طول الرابط أقل من 3 أحرف فهو رابط غير صالح elif domain != url_domain and len(link.get('href')) > 3: external_url_links.append(link.get('href')) print(internal_url_links, '\n') print(external_url_links, '\n')1 نقطة
-
نتخذ قرارات آنيةً حول الثقة في الناس، وينطبق الشيء نفسه على الثقة في المنتجات الرقمية، حيث يمكن للشركات تطوير ثقة وصدق المنتج عبر الإنترنت باستخدام التصميم للإشارة إلى أن الموقع الإلكتروني أو التطبيق آمن ولا يمكن اختراقه. كيف نقرر بمن أو بماذا نثق؟ ولماذا الثقة مهمة؟ لقد نوقشت أهميتها ودراستها اجتماعيًا في العلاقات والعمل والحكومة لوقت طويل، وهناك أمر واحد واضح، وهو أنه من غير المرجح أن يقضي المستهلكون الكثير من الوقت -ناهيك عن المال- على منتجٍ رقميٍّ لا يثقون فيه تمامًا، وقد وجدت دراسة أجرتها شركة Edelman العالمية للعلاقات العامة 2020 أن أكثر من 80% من العملاء يقولون إن المخاوف بشأن خصوصيتهم تجعلهم يثقون في العلامة التجارية التي يتعاملون معها، بينما لا يستغرق تكوين انطباع عن موقع إلكتروني سوى جزء من عشرين من الثانية، وفي البداية سيقطع التصميم الهادف إلى الثقة شوطًا طويلًا لطمأنة المستخدمين بأن التطبيق أو الموقع الإلكتروني يستحق وقتهم واهتمامهم وأموالهم. التصميم بهدف التناسق يُرسي تناسق التصميم الثقة على العديد من المستويات، فهو -في جوهره الأساسي- يطمئن المستخدمين بأنهم يتفاعلون مع الموقع الذي يقصدونه، ويشير الشكل والمظهر المتسقان إلى أن الشركة منظمة وأن موظفيها وأنظمتها تتمتع بالكفاءة. هناك عدد متزايد من الشركات التي توفر أنظمة تصميم ومكتبات قوالب تحكم جميع عناصر التصميم والتطوير، وذلك بدءًا من لوحة الألوان المراد استخدامها إلى حجم الأيقونات، وصولًا إلى الصوت والنغمة التي يجب أن يكتسبها المحتوى. وحتى بغياب نظام تصميم، يجب على المصممين التأكد من صياغة مجموعة من القواعد والالتزام بها، مثل جعل أزرار الدعوة لعمل متماثلة اللون عبر جميع الصفحات، أو التأكد من أن نماذج التقويم تبدو متشابهةً في جميع أجزاء الموقع. كوين بايس هو مثال عن شركة تستخدم التناسق في جميع منتجاتها ومن الأهمية بمكان التصميم مع وضع توقعات المستخدم في الحسبان، بالإضافة إلى الوعي بالنماذج العقلية التي طورها المستخدمون عبر سنوات من التفاعل عبر الإنترنت، لذا فمن المهم طرح الأسئلة التالية: هل يتوقع المستخدمون العثور على أيقونة عربة التسوق في الركن الأيمن العلوي من الصفحة؟ وهل يتوقعون رؤية روابط تحتها خط؟ ومع ذلك، فإن التناسق هو أكثر من مجرد لوحة ألوان أو شعار، حيث يمتد ليشمل كل شيء، بما في ذلك كيفية تنقل المستخدم عبر الموقع أو التطبيق، فمثلًا يجب أن تكون آلية الانتقال بين الشاشات هي نفسها في جميع أجزاء الموقع، كما يضمن تقديم تجربة موثوقة عدم حاجة المستخدمين إلى تعلم كيفية التفاعل مع الموقع في كل مرة يزورونه فيها. يجب أن ينصبّ تفكير المصممين -الذين يبنون تصميمهم على واجهة المستخدم وخبرة المستخدم- كليًّا على خبرة العميل، وهنا تبرز أسئلة من قبيل: كيف يتناسب عمله مع رؤية الشركة الأوسع لما يجب أن تبدو عليه الرحلة في الموقع؟ وهل يتوافق مع توقعات الشركة لرحلة العميل ككل؟ لإنشاء تجربة تصميم متناسقة وجديرة بالثقة، يجب على مصممي خبرة المستخدم إشراك ذوي العلاقة الأساسيين، والإجابة على هذه الأسئلة في بداية عملهم. تجنب الأنماط المخادعة صاغ الباحث البريطاني هاري بريجنول هذا المصطلح منذ أكثر من عقد من الزمن، وهو خبير في علم النفس وعلم الإدراك، ويشير المصطلح إلى العديد من الطرق التي يمكن من خلالها توظيف التصميم لخداع المستخدم وإجباره على القيام بشيء عن غير قصد، بالاستفادة من حقيقة أن الناس يميلون إلى تصفح النص وعدم القراءة بعناية، وذلك كما في الأمثلة التالية: جعل إلغاء الاشتراك في إحدى الخدمات ومنع تلقي رسائل البريد الإلكتروني المستقبلية شبه مستحيل تقريبًا. استخدام "x"، الرمز العالمي لإغلاق نافذة، بصفته عنصرًا يؤدي إلى تحميل برنامج جديد. إنشاء خلفيات داكنة وأزرار يصعب قراءتها. دفع عنصر لم يطلبه المشتري إلى عربة التسوق قصدًا. قد تسبب هذه الأساليب زيارات إضافيةً لموقع الشركة الإلكتروني، بل قد تسبب أرباحًا إضافيةً على المدى القصير، وربما حتى على المدى الطويل، ومع ذلك إذا كان الهدف العام هو تصميم منتج يهدف إلى تعزيز الثقة، فيجب ترك الأنماط المظلمة خارج معادلة التصميم. كن صادقا بشأن أذونات التطبيق يظهر مربع حوار يطلب من المستخدم منح التطبيق حق الوصول إلى كاميرا الهاتف عند تصميم واجهة أذونات التطبيق، لذا كن واضحًا ومباشرًا بشأن سبب نقر المستخدم فوق "نعم". كيف تُعَد هذه الأذونات ضروريةً لتجربة استخدام التطبيق؟ يمكن أن تشجع إتاحة التفسير المستخدمين على منح الإذن؛ وقد وجدت إحدى الدراسات أن احتمال موافقة المستخدم تزيد بنسبة 12% إذا أُعلِم بسبب منح ذلك الإذن. كذلك يجب تصميم الواجهة بحيث تظهر طلبات الأذونات بعد أن يبدأ المستخدم العمل مباشرةً، بحيث يكون الغرض واضحًا، ويمكن برمجة تطبيق مطعم ليسأل عن موقع المستخدم فقط في المرة الأولى التي يبحث فيها عن أماكن لتناول الطعام في مكان قريب، ويجب أن يوضِّح السياق فوائد منح الإذن. كن في موضع المسؤولية يجب أن تملك الشركات الكبيرة والصغيرة خططًا للتواصل مع المستخدمين بعد انقضاء الخدمة أو في حال اختراق البيانات، وهذا محتمَل بصورة متزايدة، حيث تقوم الشركات عادةً بعد وقوع أي حادث بتوظيف فِرَق علاقات عامة للرد على دواعي قلق العميل؛ ويمكن للمصممين التعاون مع هذه الفِرَق من أجل تصميم قوالب للبريد الإلكتروني والإشعارات ومنشورات وسائل التواصل الاجتماعي لإعلام المستخدمين بآخر التحديثات التي تخص الموقف الحاصل. وعلى المصممين إنشاء بيئة إلكترونية، مثل صفحة إلكترونية متخصصة، وذلك لتوضيح المشكلة بصدق وشفافية، بما في ذلك كيفية حدوثها ومن تعرض لها وكيف حصل ذلك، وماذا سيحدث لاحقًا، لذا تأكد من أن هذا الشرح مرئيًا في أماكن متعددة، أو من تواجد رابط واضح للعثور عليه في جميع أنحاء الموقع أو التطبيق. تأكد من من وجود جهة خارجية ميزاتها تتبع تعليمات العلامة التجارية يضيف المطورون ميزات جهة خارجية -في تطبيق أو موقع- تتيح للمستخدمين المزيد من الوظائف، فمثلًا تعني إتاحة دردشة أو تطبيق دفع في منتج، عدم القلق بشأن تصميم هذه الميزات من البداية، بالإضافة إلى جعل المنتج الأساسي متكاملًا، ولكن عند إضافة هذه الصفحات أو التطبيقات، فمن المهم التأكد من أن التصميم يمثل استمرارًا واضحًا للعلامة التجارية والمنتج، وقد لا يرغب العميل في التفاعل مع ميزة دردشة خدمة العملاء التي من الواضح أنها مدعومة من قبل مخدِّم خارجي، ويمكن أن يؤدي تقديم أيقونة مرئية -أو بطريقة أخرى تأكيد وجود العلامة التجارية- إلى قطع شوط طويل نحو طمأنة المستخدمين بأن التطبيق الذي يستخدمونه هو التطبيق الذي يعتزمون التعامل معه وأنه تطبيق آمن. دفع المستخدمين إلى تأمين حساباتهم التنبيه أو الدفع في علم السلوك هو تذكير غير مباشر مصمم للتأثير على السلوك، ويمكن للمصممين تشجيع المستخدمين على حماية بياناتهم من خلال ابتكار طرق إبداعية لإتاحة هذه التنبيهات، فمثلًا نظرًا لأن 80% من خروقات البيانات يكون سببها كلمات مرور ضعيفةً أو معادة الاستخدام؛ يمكن للمصممين تزويد صفحة تسجيل الدخول بمقياس أمان لكلمة المرور يشجع المستخدمين على إنشاء كلمات مرور أقوى، أو يمكنهم إرسال تذكيرات تدفع المستخدمين باتجاه تفعيل المصادقة الثنائية أو المتعددة العوامل على حساباتهم، حيث إنها واحدة من أفضل وسائل الحماية. تعرِض بعض الشركات -مثل متداول العملات المشفرة بتكوين- للمستخدمين علامةً لا يمكن تجاهلها، بحيث لن تسمح لهم بالمتابعة حتى يُعِدون مصادقة ثنائية، ويمكن للشركة تأمين بيانات عملائها وإثبات أنها تأخذ خصوصية عملائها وأمان معلوماتهم على محمل الجد بفعّالية من خلال التصميم الذكي والإبداعي. يجمع هذا التنبيه الأمني بين الأيقونات واللون والتنبيهات المصغرة للتعبير عن الحاجة الملحة لحماية بيانات المستخدم. التصميم الجدير بالثقة يشير إلى النجاح وفقًا لدراسة وردت في مجلة هارفارد بيزنس ريفيو، من المرجح أن يخاطر العملاء من خلال مشاركة معلوماتهم الخاصة أو من خلال الشراء عبر الإنترنت مثلًا، إذا كانت هناك درجة عالية من الثقة، وقد أصبح لدى المستخدمين في الوقت الحالي أسباب لتوخّي الحذر من المنتجات الرقمية أكثر من أي وقت مضى، ففي الأشهر التسعة الأولى من عام 2020، هاجم القراصنة أجهزة الكمبيوتر كل 39 ثانية؛ وتعرض حوالي 36 مليار سجل لاختراق البيانات في جميع أنحاء العالم؛ وتنذر الإحصاءات بالخطر ويبدو أنه لا نهاية لها، كما تظهر الدراسات أن قرارات الأشخاص بشأن مكان وضع ثقتهم لا تستند إلى عملية اتخاذ قرارات منطقية بقدر ما تستند إلى الحدس، ولأن اتخاذ العميل لهذا القرار فوري، فيمكن لاتباع مبادئ التصميم الجدير بالثقة أن يقطع شوطًا طويلًا نحو غرس الثقة في المستخدم. ترجمة -وبتصرّف- للمقال How to Design for Maximum Product Trust لصاحبه MAYANK SHARMA. اقرأ أيضًا أفضل المبادئ والتطبيقات لتصميم لوحات التحكم Dashboard Design قواعد تصميم الهوية البصرية لم المحتوى أهم من التصميم؟ دليل المصمم لإنشاء قصة العلامة التجارية النسخة الكاملة من كتاب أساسيات تصميم الرسوميات1 نقطة
-
تُعَد لوحات التحكم Dashboards طريقةً مميزةً وفعّالةً لعرض المعلومات المعتمدة على البيانات باستخدام أساليب التمثيل المرئي للبيانات، والتي تعرض البيانات ذات الصلة والقابلة للتطبيق، بالإضافة لإحصائيات التّتبع ومؤشرات الأداء الرئيسية KPIs. يجب أن تُعرض البيانات بصيغة سريعة وسهلة المسح البصري، متضمنة المعلومات الأكثر صلة والتي يمكن فهمها بلمحة. لقد وُجد المصطلح لأول مرة في لوحات القيادة التقليدية للسيارات، وطُوّرت لتؤدي الوظيفة ذاتها في العالم الرّقمي. يشرحها Stephen Few في كتابه كما يلي: لوحة بيانات للهاتف المحمول لـ Mixpanel مصممة من قبل Mason Yarnell سنناقش أمثلةً تحليليةً عملية ومعلوماتية، بالإضافة لمبادئ أساسية تدخل في تصميم لوحات التحكم مهما كان نوعها. يُعَدّ اتباع النهج الصحيح للتمثيل المرئي للبيانات ميزةً أساسيةً لترتيب عناصر لوحة بيانات ناجحة. حيث أن التمثيل المرئي للبيانات Data visualization هو عرض البيانات عبر رسومات وصور، هدفه الأساسي مساعدة صنّاع القرار على تمييز الأنماط واستيعاب المفاهيم الصعبة التي قد تكون غير واضحة في التطبيقات المعتمدة على النص المكتوب. يقول Noah Iliinsky وJulie Steele في كتابهما Data Visualization: الخصائص الأساسية للوحة بيانات مميزة تُظهر لوحة التحكم المميزة معلومات مفيدةً وقابلةً للتنفيذ بلمحة، فهي تبسّط البيانات المعقدة وتساعد المعنيّين على فهم وتحليل وعرض الإحصائيات الأساسية. لوحة بيانات لـ contractbook مصممة من قبل Wojciech Dobry لوحات التحكم الجيدة واضحة وسهلة وقابلة للتخصيص قادرة على إيصال المعلومات بسرعة. تعرض المعلومات بوضوح وكفاءة. تُظهر التغيّرات والتطورات التي تطرأ على البيانات بمرور الوقت. يمكن تخصيصها بسهولة. تعرض العناصر والبيانات الأكثر أهميةً بمساحة محدودة. تساعد قابلية التخصيص الأولية للبيانات المرئية وفق متطلبات المستخدِم الأساسية في تحسين الاستخدام وتلغي الحاجة لنماذج متعددة لتوافق أنماط المستخدمين. عناصر لوحة بيانات قابلة للتخصيص لـ contractbook مصممة من قبل Wojciech Dobry تقدم لوحات التحكم المميزة كل المعلومات بنقرة واحدة يمكن الوصول مباشرةً لكل المعلومات الأساسية. الأولوية للبيانات. تُعرض المعلومات بوضوح وبتسلسل مرئي في شاشة واحدة. يوفر التصميم نظرةً عامةً مترابطةً تتضمن بيانات أوليّة متعددة وواضحة مع إمكانية التعمق بالمزيد من تفاصيلها. تُعرض العناصر، مثل: المخططات، والجداول، والنماذج مصغّرةً مع إمكانية عرض المزيد من البيانات سواءً في نافذة رديفة، أو بالانتقال إلى صفحة أخرى تحمل المزيد من التفاصيل. يُحسّن التصميم الاستخدام بوجود مرشحات تسمح للمستخدِمين بتخصيص طريقة عرض البيانات، وتصفية المحتوى بناءً على العناوين، والتصنيفات ومؤشرات الأداء الرئيسية KPIs. بيانات تفصيلية عُرضت من لوحة بيانات رديف، مصممة من قبل Miklos Philips تقليل التعقيد يزيد الوضوح في عالم مليء بالبيانات، يُعَدّ عرض معلومات واضحة أحد أصعب الأهداف. فمن الأساسي عرض المعلومات الأكثر صلةً بلوحة التحكم، وكلما زادت المعلومات المعروضة، صَعُب على المستخدم إيجاد ما يبحث عنه. عندما يواجه المصمم الكثير من البيانات للاختيار منها، فعليه عرض المجموعات الأكثر صلةً فقط، وتحديد الأولويات وإزالة البيانات المبهمة وغير الواضحة بعناية. وتوجَّه القرارات التصميمية للوحة بيانات فعالة بـ: أهداف المشروع. طبيعة البيانات. حاجات المستخدمين. لوحة بيانات مصممة من قِبل Stelian Subotin يقول Noah Illinsky وJulie Steele في كتابهما Data Visualization: الهدف الأساسي للوحة التحكم هو جعل البيانات المعقدة متاحةً وسهلة الفهم، لذلك يجب أن تكون الواجهة التي تعرض البيانات مرتبةً ودقيقةً لتخفيف الحمل المعرفي على المستخدِم، واختصار الوقت الذي سيقضيه بالبحث. يجب أن تعرض المعلومات البيانات الأهم أولًا ثم توفر الوصول للبيانات الداعمة أو الثانوية. أي تصميم نظام عرض تدريجي يبدأ بنظرة عامة ثم يخوض بالتفاصيل مما يسهل تحديد الأولويات ويؤمّن الوضوح. لوحة بيانات مصممة للهاتف المحمول من قبل Jan Losert تحديد أهداف لوحة التحكم وعرض البيانات المناسبة عند تصميم لوحات التحكم، فإن المصمم الناجح يبدأ بأهداف مشروحة جيّدًا تركّز على المشكلة لحلّها وعلى الإحصاءات القابلة للتنفيذ التي يمكن للمستخدم أن يستخلصها من البيانات. تعزز أهداف التصميم الجيّدة التطبيق الفعّال والدقيق له، ولتحديد صفات هدفنا من التصميم نوظف إطار عمل يدعى S.M.A.R.T وهو اختصار لـ: Specific. Measurable. Actionable. Realistic. Time based. لتذكر تلك الصفات نجمعها بكلمة تحمل ذات المعنى "عبقري" ويذكرنا كل حرف بإحدى الصفات، فعبقري تشير إلى: عيّنه. بأبعاد. قابلة للتطبيق. راضخة للواقع. يقيدها الزمن. ويكون الهدف محدّدًا، قابلًا للقياس، والتنفيذ، واقعيًا، مستندًا إلى خطة زمنية. فيما يلي بعض الأسئلة المفتاحية لطرحها عند تحديد أهداف تصميم لوحة التحكم: كم خطوة يتّخذها المستخدم للوصول لنتيجة محددة؟ هل الواجهة واضحة بما يكفي لترشد المستخدم لهدفه؟ ما المعلومات التي يحتاجها المستخدم لتحقيق غايته بنجاح؟ لتحديد هدف لوحة بيانات محددة، اسأل نفسك "ما المشكلة المحددة التي سيحلًها التصميم للمستخدم؟". حيث تقدم الإجابة رؤيةً حول القياسات، والخصائص، والقيم، والمرئيات، والبيانات ذات الصلة. لوحة بيانات مصممة من قِبل Miklos Philips يركّز التصميم المُعتمد على الهدف على حل مشكلات حقيقية، وهو الأساس لكل تصميم جيّد للوحة بيانات. يبدأ بفهم واضح لأهداف العمل مع أخذ غاية المستخدمين بالحسبان، ثمّ إيصال المعلومات الأساسية اللازمة للمستخدم. المحتوى في تصميم لوحة التحكم أحد أكبر التحديات في تصميم لوحات التحكم هي أن تخدم الأنماط المختلفة من المستخدمين، وعندما تُحدد احتياج كل مستخدم، يصبح أساسيًا فهم متى تلتقي هذه الاحتياجات ومتى تتشعب. المبدأ الأساسي لكل تصميم ناجح للوحة بيانات هو تحقيق التواصل الفعال، ويسهم توقع الاحتمالات التي سيجد المستخدمون أنفسهم أمامها في فهم أفضل لوضعهم. أثناء التصميم ضع حالة المستخدم بالحسبان دومًا، وحدد خبرتهم التقنية ومدى إلمامهم بالنظام عمومًا، بالإضافة لأهدافهم وما إلى ذلك. لوحة بيانات مصممة من قبل Miklos Philips عند محاولتك لفهم وضع المستخدم وتفاعله، تأكد من الإجابة عن الأسئلة الآتية: هل يأخذ التصميم اتجاه القراءة الذي اعتاد عليه المستخدم بالحسبان؟ هل يتطلب التفاعل مع لوحة التحكم خبرة تقنية؟ هل يمكن للمستخدم إتمام معظم الإجراءات بعدد نقرات محدود؟ هل يناسب التصميم المستخدم بإضافة قوائم تفصيلية رديفة؟ وهل اعتمد التصميم على الرموز وقوائم الألوان color palettes؟ يجب أن تكون قائمة الألوان المستخدمة في تصميم لوحة التحكم مناسبةً للمحتوى، فالعديد من لوحات بيانات المنتجات لـ SaaS مصممة بواجهات مستخدم ذات طابع داكن Dark-themed، لأن استخدامها يكون لساعات طويلة متواصلة. بحيث تساعد واجهات المستخدم ذات الطابع الداكن على تقليل إجهاد العين وتدعم التباين ضمن الواجهة. لكن بكل الأحوال سيتطلب اتباعها تقييمًا دقيقًا لتوجّه التصميم والانتباه للإيجابيات والسلبيات بالإضافة للهفوات الممكنة. تصميم لوحة بيانات لواجهة مستخدِم من قِبل Alex Gilev. تبدو الإحصاءات والرسومات واضحةً بالطابع الداكن، لكنها تتطلب التأكد من أن التباين كافٍ. بحث المستخدم لتصميم أفضل للوحات التحكم يساعد بحث المستخدم على عرض البيانات ذات الصلة بإيجاز ووضوح على المستخدمين، كما يساعدهم ذلك في التركيز على المحتوى وعلى البيانات التي يبحثون عنها بدل التفكير في آلية الوصول إليها. يجب أن تكون بعض لوحات التحكم مناسبةً أو قابلةً للتخصيص بما يلائم مختلف المستخدِمين الذين ينظرون إلى اللوحة الأساسية ذاتها. يُعَد بحث المستخدم مهمًّا، حيث يساعد على تحديد أهداف المستخدم، وأساليب التفكير، والمحتوى العامن بالإضافة إلى نقاط الضعف، وهذه العناصر تؤثر كثيرًا على التصميم النهائي للوحة التحكم. لوحة بيانات مصممة من قِبل Stelian Subotin يُطلق المصمم لتجربة المستخدم والباحث والمؤلف Mike Kuniavsky على ذلك اسم "عملية فهم تأثير التصميم على الجمهور". وعلى المصمم أن يحدد الأنماط المختلفة للمستخدمين ويفهم أين تتلاقى أهدافهم وأين تختلف، وأي المعلومات قابلة للتطبيق لكل نمط من المستخدمين، كما عليه مراعاة إن كان هناك حاجة لتغيير واجهات اللوحة وفقًا لكل نمط، أو إن كان هناك حل لتصميم عام يخدم كافة المستخدمين. من الجيّد البدء بإطار أوليّ ثم الانتقال إلى نماذج بدئية قابلة للاختبار مع مستخدمين حقيقيين خلال مدة بحث المستخدم؛ فقد تخرج إحصاءات قيّمة من فترة بحث قصيرة جدًّا على خمسة مستخدمين فقط، وذلك يوفر الكثير من الوقت لاحقًا. إطار عمل للوحة بيانات مصمم من قِبل Aaron Sananes العرض التدريجي في تصميم لوحات التحكم يُستخدم العرض التدريجي مثل تقنية تحافظ على تركيز المستخدم بتقليل التشتيت، حيث يساهم بناء نظام بأسلوب عرض تدريجي في إنشاء بيئة تتمحور حول المستخدم، مما يساعد في إعطاء الأولوية لتركيزه، وتجنب الأخطاء، وتوفير الوقت. كما تسمح للمستخدم بالتركيز على الميزات الأساسية التي تهمّه، وبالتالي لا يكون مجبرًا على الاطلاع على كل الميزات بما فيها تلك التي لا يحتاجها أو ليس مهتمًّا بها. يسمح أسلوب العرض التدريجي في تصميم لوحات التحكم بتقليل معدّل الأخطاء إلى حد كبير، ويُسهم بتحسين الكفاءة ويساعد المستخدمين على تعميق فهمها عندما يعتمد على ترتيب الميزات وفقًا للأولوية. لوحة بيانات مصممة من قبل Jan Losert تُعَد الرسوم المتحركة طريقةً رائعةً لتلبية العديد من احتياجات المستخدِم إضافةً لأداء وظائف متنوعة. واستخدامها خيار جيّد أثناء تحميل البيانات والمرئيات. ويُعَد أحد حلول العرض التدريجي المتقدمة. الرسوم المتحركة هي إعطاء انطباع بالحركة، حيث توحي هذه الفعالية بالتقدم والمواكبة المستمرة للنتائج، مما يقلل من الشك لدى المستخدم ويحسّن الأداء. لوحة بيانات مصممة من قبل Virgil Pana ميزات استخدام أسلوب العرض التدريجي في لوحات التحكم: تقليل الشك والارتباك لدى المستخدم، وذلك بعرض التقدم، بحيث يتأكد المستخدم بأن كل شيء يعمل كما يجب. منح المستخدم شيئًا ينظر إليه مثل عرض البيانات جزئيًّا بدل جعله ينتظر. تزويد المستخدم بتصورات واضحة للخطوات القادمة، وفهمًا لآلية عرض المعلومات بالتسلسل. المشكلات المتوقعة أثناء العرض التدريجي وتحميل البيانات: استخدام المؤشرات والعرض بأسلوب غير ملائم؛ حيث تسبب الخطوات غير اللازمة بأوقات تحميل قصيرة الارباك للمستخدم وقد تكون ضد مبادئ سهولة الاستخدام. قد يؤدي التأخر في ظهور البيانات بدون مؤشر واضح عن التقدم، إلى ريبة المستخدم وزيادة معدلات التخلي عن المنتج. يمكن استخدام مؤشرات التقدم غير المتحركة مثل حل مقبول، لكنه لا يعطي معلومات كافية عن التقدم، مما قد يؤدي أيضًا إلى ريبة المستخدم وزيادة معدلات التخلي عن المنتج. لوحة بيانات مصممة من قبل Mason Yarnell الخلاصة تُعَد لوحات التحكم طريقةً فعّالةً في إيصال البيانات والمعلومات الأخرى، خاصةً التصميم المتمحور حول المستخدم والمعتمد على هدفه، والذي يوظف أفضل ممارسات تصميم لوحات التحكم والطريقة الصحيحة لعرضها. كل لوحة بيانات مختلفة عن الأخرى ولكل منها أهداف ومتطلبات وقيود مختلفة، إلا أنّ اتّباع المبادئ الأساسية الآتية يساعد في إنشاء لوحة بيانات مميزة بغضّ النظر عن التفاصيل: أولًا وقبل كل شيء، افهم أنماط المستخدمين وأهدافهم. انقل قصةً واضحةً للمستخدم، مستفيدًا من العناصر المرئية والعناوين وتقنيات العرض التدريجي بالإضافة للرسوم المتحركة. بسّط ما هو معقّد بتطبيق تقنيات بحث المستخدم. أظهر البيانات في الوقت المناسب، باستخدام واجهات رديفة. استخدم العرض المرئي للبيانات لإظهار المعلومات بطريقة ذات معنى. ترجمة وبتصرّف للمقال Dashboard Design - Considerations and Best Practices لصاحبه STELIAN SUBOTIN.1 نقطة
-
من القرارات المهمة التي على المديرين اتخاذُها باكرًا في سياق تخطيط الإنتاج، والعمليات؛ مكانُ تأسيس المنشأة، سواء أكانت معملًا، أو مكتب خدمة؛ فموقع المنشأة يؤثر في تكاليف العمليات، والشحن، حيث يؤثر ذلك في النهاية على المُنتَج، أوِ الخدمة، وعلى قدرة الشركة على المنافسة، هذا، ويمكن للأخطاء التي تُرتَكبً في هذه المرحلة أن تكون باهظة الثمن؛ إذ من الصعب، والمكلف، نقلُ مصنعٍ، أو مكتب خدمةٍ، بعدما يكون الإنتاج فيهما قد بدأ فعلًا، كما على الشركات أن تأخذ بالحسبانِ عددًا من العوامل؛ للوصول إلى اتخاذِ القرار الصحيح. في هذا المقال من سلسلة مقالات مدخل إلى عالم الأعمال سنتعرف على كيفية اختيار الشركات مكان منشآتها التصنيعية، وعلى الخيارات التي يجب اتخاذُها في عملية تصميم المنشأة الصورة 10.6: تحت تأثير المنافسة المحتدِمة من قبل شركات سياراتٍ أخرى، وانخفاضِ الطلب على سياراتها من قبل الزبائن في ألمانيا؛ افتتحت شركةُ بي إم دبليو BMW الألمانية (المعروفة -أيضًا- باسم شركة المحركات البافارية Bavarian Motor Works مصنعًا لها في سبارتنبرغ Spartanburg بولاية كارولينا الجنوبية في الولايات المتحدة، وكان ذلك في العام 1994، وقد وصلَ مؤخرًا العددُ الذي أنتجه ذلك المعمل من السيارات إلى أربعة ملايين سيارة، ويوظِّفُ حاليًا 9000 عامل ضمن ستة ملايين قدم مربعة، وهي مساحة ذلك المعمل. عوامل تحديد موقع الشركة توفر مدخلات الإنتاج مثلما ناقشنا سابقًا؛ تحتاجُ الشركاتُ إلى موارد محددة لصنع منتجات، وتقديم خدماتٍ، تستطيع بيعَها، ويعد الوصول إلى تلك الموارد، أو المدخلات؛ من المسائل شديدة الأهمية في اختيار الموقع؛ فعلى المسؤولين التنفيذيين تقييم توفُّرِ المواد الخام، وقطع الغيار، والمعدات، والقوى العاملة المتاحة بالنسبة لكل موقع قيد النظر، ويمكن أن تصل تكلفة شحن المواد الخام، والسلع النهائية إلى 25 % من إجمالي تكلفة الشركة المُصنِّعة، لذلك فإن تحديد موقع المصنع؛ حيث تكون هذه التكاليف، وغيرها، منخفضةً قدر الإمكان؛ يمكن أن يساهم مساهمة كبيرة في نجاح الشركة. وقد تختار الشركاتُ التي تستخدم المواد الخام الثقيلة، أو الضخمة، على سبيل المثال؛ أن تكون قريبة من مورِّديها؛ فشركات التعدين تريد أن تكون قريبة من الرواسب الخام، ومصافي تكرير النفط؛ بالقرب من حقول النفط، ومصانع الورق؛ بجانب الغابات، ومنشآت معالجة الأطعمة؛ بالقرب من المزارع، ويكتشف أصحابُ معامل تعبئة المياه، والعصائر؛ أن المجتمعات الريفية الغربية، في الولايات المتحدة، التي تحتاج إلى تنشيطٍ اقتصادي؛ تُعدُّ مصدرًا غنيًا للمياه، ففي مدينة لوس لوناس Los Lonas، التابعة لولاية نيو مكسيكو الأمريكية، كان من المنطقي بالنسبة لشركة نياغارا بيوريفايد درينكينغ ووتر Niagara Purified Drinking Water أن تُنتِج مياهًا نقية معبَّأة في زجاجات في مبنى مساحته 166.000 قدم مربع كان شاغرًا، وقد ساعدَ هذا المشروعُ التجاري في تنويع اقتصاد المدينة، ووفَّرَ 40 وظيفة كانت هناك حاجة ماسّة إليها. إنَّ توفُّر العمالة وتكلفتها، أمران حاسمان -أيضًا- لكل من شركات التصنيع، والخدمات، كما أنَّ تنظيم العمالة المحلية نقابيًا، هي نقطة أخرى يجب أخذها بالحسبان في العديد من الصناعات، ويمكن أن تختلف الرواتب اختلافًا كبيرًا من موقع إلى آخر؛ بسبب الاختلافات في تكلفة المعيشة، وفي عدد الوظائف المتاحة، وحجم القوة العاملة المحلية، ومهاراتها، وإنتاجيتها، ففي حالة شركة تعبئة المياه التي تحدثنا عنها أعلاه، كان هناك مجموعة جاهزة من العمالة غير المكلفة -نسبيًا- بسبب ارتفاع نسبة البطالة في تلك المناطق. عوامل التسويق على الشركات تقييم كيفية تأثير موقع المنشأة في قدرتها على خدمة زبائنها، فبالنسبة لبعض الشركات، قد لا يكون ضروريًا وجودُها بالقرب من الزبائن، ولكنها بالمقابل ستحتاج إلى تقييم صعوبة توزيع سلعها للزبائن من موقعها المختار، وتكاليف عملية التوزيع تلك، وقد تجد شركات أخرى أن إقامة موقعها قريبًا من الزبائن، يمكن أن يوفّر لها مزايا تسويقية؛ فعندما يكون المصنع، أو مركز الخدمة، قريبًا من الزبائن؛ يمكن للشركة -غالبًا- تقديمُ خدمة أفضل بتكلفة أقل، كما قد تكتسب شركاتٌ أخرى ميزة تنافسية من خلال اختيار موقعٍ لمنشآتها يُمَكِّنُ الزبائنَ من شراء منتجاتها، أو خدماتها بسهولة، وقد يكون موقع الشركات المنافسة أحد الأمور الأخرى التي تؤخَذ بالحسبان، كما قد تحتاج الشركات التي لديها أكثر من منشأة واحدة، إلى التفكير في مدى انتشار مواقعها من أجل زيادة تغطيتها للسوق. البيئة التصنيعية تُعد البيئة التصنيعية في موقع محتمل، إحدى العوامل الأخرى التي تؤخذ بالحسبان، إذ إنَّ هناك لدى بعض المنشآت قاعدة تصنيعٍ قوية موجودة، فعندما يكون عددٌ كبير من شركات التصنيع في مجالٍ صناعي ما، موجودًا بشكل مُسبَق في إحدى المناطق؛ فمن المحتمل أن توفر تلك المنطقة قدرًا أكبر من الموارد، مثل: عمال التصنيع، ووصولًا أفضلَ، إلى المورِّدين، ووسائل النقل، إضافة إلى عوامل أخرى؛ يمكن لها أن تزيد الكفاءة التشغيلية للمصنع. فشركة نستله Nestle تسعى إلى افتتاح مصنع جديد لتعبئة المياه في صحراء فينيكس Phoenix Desert بولاية أريزونا الأمريكية، وقد وفرتِ المصانعُ فرص عمل كثيرةً، كان الناسُ بحاجة ماسة إليها، وعوَّضت عن الوظائف التي خسروها في الكساد الاقتصادي الذي ساد عامَ 2008، هذا، وقد واجهت مدينةُ فينيكس معارَضةً لإنشاء ذلك المصنع، لاعتقاد بعض السكان المحليين أنَّ تحويل المياه من الصنابير إلى مياهٍ توفرها منشأةٌ ربحية، لم يكن فكرة مُستساغة، ولكنَّ المسؤولين في المدينة يؤكدون بأنَّ مصدر المياه هناك يكفي لعقودٍ قادمة. الحوافز المحلية يمكن للحوافز التي تقدمها السلطات في الدول، أو الولايات، أو المدن، أن تؤثر -أيضًا- في اختيار الموقع، وتعد التخفيضات الضريبية إحد الحوافز الشائعة، فقد تُخفِّضُ سُلطةٌ محلية، القيمة الضريبة التي على شركة ما دفعُها على أساس الدخل، أو العقارات، أو المرافق، أو الرواتب، وقد توفر الحكوماتُ المحلية مساعدةً مالية، وإعفاءاتٍ من إجراءات تنظيمية معينة، أو إحداهما، لجذب المنشآت الإنتاجية إلى مناطقها، أو للمحافظة على وجودها هناك، فعلى سبيل المثال، تتنافس العديد من مدن الولايات المتحدة؛ لتكون المقر الثاني لشركة أمازون Amazon، باﻹضافة إلى ترويج تلك المدن للمعالم المحلية لديها، وإظهار مزايا قوتها العاملة، ويقدِّم معظم تلك المدن مجموعة من الحوافز الضريبية. مواصفات تحديد الموقع الدولي غالبًا ما تكون هنالك أسباب مالية وجيهة للتفكير في تأسيس موقع في دولة أجنبية، وهناك دولٌ تكون تكاليفُ العمالة فيها أقلَّ بشكل ملحوظ من سواها، ومنها سنغافورة، والصين، والهند، والمكسيك، كما قد يكون لدى دولٍ أجنبية معينة، عدد أقل من الإجراءات التنظيمية الخاصة بكيفية تشغيل المصانع، وقد يؤدي تأسيسُ موقعٍ أجنبيٍّ -أيضًا- إلى تقريب اﻹنتاج من اﻷسواق الجديدة، فشركاتُ صناعة السيارات مثل: تويوتا Toyota، و بي إم دبليو BMW، وهيونداي Hyundai، هي أمثلةٌ على العديد من الشركات التي تبني مصانع في الولايات المتحدة لتقليل تكاليف الشحن. تصميم المنشأة بعد اتخاذ قرار تحديد موقع المنشأة، تتمثل الخطوةُ التالية في مخطط اﻹنتاج، في اختيار مخطط المنشأة، أو تصميمها، ويتمثلُ الهدف من ذلك، في تحديد التصميم اﻷكثر كفاءة، وفاعلية، بالنسبة لعملية اﻹنتاج المقصودة، فقد تختار شركةٌ مصنِّعةٌ خطَّ إنتاجٍ على شكل حرف U مثلًا، بدلًا من خطٍّ طويل، ومستقيم، للسماح للمنتجات، والعمال بالتحرك بسرعة أكبر من منطقة إلى أخرى. وعلى شركات الخدمة -أيضًا- مراعاةُ تخطيط المنشأة، أو تصميمها، ولكنّ اهتمامَ تلك الشركات يتركز تركيزًا أكبر على كيفية تأثيرها في سلوك زبائنها، فقد يكون أفضلَ بالنسبة لمستشفًى، وضعُ مصعدِ نقلِ حمولات المواد التي يحتاجها، في وسط المبنى مثلًا، ولكنَّ فعلَ ذلك قد يعيقُ حركة المرضى، والزوار، والطاقم الطبي بين الطوابق، واﻷقسام. وهنالك ثلاثة أنواع رئيسة لمخططات المنشآت، هي: مخطط العملية Process Layout، ومخطط المنتج Product Layout، ومخطط المكان الثابت Fixed-Position Layout، وجميعُها مبيَّنَةٌ في الصورة 10.7. ومن الأنواع الأخرى لتخطيط المنشآت مخطط التصنيع الخلوي، أو مخطط الخلايا Cellular Manufacturing Layout. الصورة 10.7: أنواع تصاميم المنشأة مخطط العملية Process Layout ينظِّمُ مخططُ العملية Process- Layout سيرَ العمل حول عملية الإنتاج، إذ يجري تجميعُ العمال كلهم؛ الذين يؤدون مهامَّ متماثلةً معًا، كما تنتقل المنتجات من محطة عمل إلى أخرى، (ولكن ليس بالضرورة إلى كل محطة عمل)، فعلى سبيل المثال: ستُجرى عمليات الطحن كافة في منطقة واحدة، وعمليات التجميع كافة في منطقة أخرى، وعمليات الفحص في منطقة أخرى كذلك، ويعد مخطط العملية اﻷفضلَ للشركات التي تنتج أعدادًا صغيرة من مجموعة واسعة ومتنوعة من المنتجات، وعادة ما تستخدمُ آلاتٍ ذات أغراض عامة، يمكن تغييرها بسرعة إلى عمليات جديدة؛ من أجل تصاميم منتجاتٍ مختلفة، ومن الأمثلة على شركات تستخدم مخطط العملية Process Layout شركةُ تصنيع آلاتٍ حسب الطلب Custom Machinery. مخطط المنتج Product Layout يُستخدَم ع المنتجات التي تتطلب عملية إنتاج مستمرة، أو متكررة مخططُ المنتج Product-Layout، أو مخطط خط التجميع Assembly-Line Layout، فعندما يكون معالجةُ كميات كبيرة من منتَجٍ ما بشكل مستمر ضروريًّا، يجري ترتيبُ محطات العمل، أو اﻷقسام، بالتوازي مع المنتجات التي تتحرك على طول الخط، وعادة ما يُستخدم مخططُ المنتج من قِبل مصنّعي السيارات، واﻷجهزة، ومصانع معالجة الأطعمة، كما قد تستخدم شركاتُ الخدمات -أيضًا- مخطط المنتج لعمليات المعالجة التقليدية اليومية (الروتينية). مخطط المكان الثابت Fixed-Position Layout لا يمكن وضع بعض المنتجات على خط التجميع، أو نقلها ضمن مصنع، ويأتي مخطط المكان الثابت Fixed-Position Layout ليسمح ببقاء المنتج في مكان واحد، بينما ينتقل العمال، واﻵلات، إليه حسب الحاجة، وعادة ما يجري تصنيعُ المنتجات التي يستحيلُ تحريكُها، مثل السفن، والطائرات، ومشاريع البناء، باستخدام مخطط المكان الثابت، وتعني المساحةُ المحدودة في موقع المشروع -غالبًا- أنه يجب تجميع أجزاء من المنتج في مواقع أخرى، ونقلها إلى الموقع الثابت، ثم تجميعها، كما أن مخطط المكان الثابت شائع -أيضًا- بالنسبة للخدمات التي تجري في الموقع، مثل خدمات تنظيف المنازل، ومكافحة اﻵفات، والحشرات، وتعديل المعالم الطبيعية. التصنيع الخلوي Cellular Manufacturing يجمع التصنيع الخلوي Cellular-Layout بين بعض جوانب كل من مخطط المنتج Product Layout ومخطط المكان الثابت Fixed-Position Layout، وخلايا العمل في التصنيع الخلوي؛ هي وحداتُ إنتاج صغيرة، وذاتُ احتواءٍ ذاتيّ، تتضمن عمالًا يجري تنظيمهم، وآلاتٍ متنوعةً تُرتَّبُ، ترتيبًا متراصًّا، وتسلسليًّا؛ وتؤدي كلُّ خلية المهام اللازمة منها تمامًا؛ ﻹكمال حصتها من عملية التصنيع، أو معظمها، وعادة ما يكون هناك من 5 إلى 10 عاملين في كل خلية، يُدرَّبون ليكونوا قادرين على تنفيذ أي خطوة من خطوات عملية اﻹنتاج، ويتمثل الهدف من ذلك في خلق بيئة فريقٍ يشارك أعضاؤه في عملية اﻹنتاج؛ من الألِف إلى الياء. ترجمة -وبتصرف- للفصل Achieving World-Class Operations Management من كتاب introduction to business1 نقطة
-
شهد مجال تطوير الوِب في السنوات الأخيرة تطورات هائلة على جميع المستويات والذي أدى إلى تحسنيات كبيرة على مستوى السرعة والجودة وقابلية الصيانة. ليس ذلك فحسب بل تعدى الأمر إلى إمكانية أتمتة بعض المهام الروتينية والتركيز على جودة العمل المُسلم ورفع الإنتاجية وذلك باستخدام أدوات مساعدة مثل Webpack، والتي تعدّ من أشهر الأدوات المساعدة بل إنها أصبحت عنصرًا أساسيًا في أي مشروع يُبنى بلغة جافاسكربت. حدثت بعض هذه التطورات على صعيد تطوير الواجهات الخلفية (Back-end) مثل ظهور Node.js والّتي تستخدم استخدامًا كبيرًا في هذه الأيام، وبعضها الآخر كان في تطوير الواجهات الأمامية (front-end)، ومن أبرز هذه التطورات هي النقلة النوعية للغة جافاسكربت ودعمها للعديد من المميزات والخصائص، والتي أدت في نهاية المطاف لجعلها واحدةً من أبرز الخيارات القوية في برمجة الوِب. بل وحتى إنها احتلت المرتبة الأولى في ترتيب أشهر لغات البرمجة شعبية لعام 2019 وذلك بحسب إحصائية موقع Stackoverflow. وكما أعلنت شركة Web3Techs أن لغة جافاسكربت مُستخدمة من قِبل حوالي 95% من مواقع العالم قاطبةً، وهي أيضًا على رأس قائمة "أكثر لغة مشهورة في برمجة الواجهات الأمامية" بحسب نفس الشركة. ولكن كيف جرت هذه التحولات السريعة والقوية بنفس الوقت لهذه اللغة؟ وما هي المراحل الأساسية الّتي مرت بها؟ وما هي الأدوات المختلفة الّتي ظهرت بالتزامن مع تطور هذه اللغة؟ وما هي أدوات البناء (مثل Gulp)؟ وما هو مجمع الوحدات (مثل Webpack)؟ ولماذا ظهر؟ وما هي مميزاته؟ سنحاول في هذا الدليل مرافقتكم في رحلة استكشافية للإجابة على هذه الأسئلة، ولنستعرض فيها أيضًا التاريخ العريق لهذه اللغة، ومعرفة الاسباب الرئيسية لتطورها وكيف احتلت بهذه السرعة المكانة العالية الّتي هي عليها اليوم. فهل أنت مستعد لمشاركتنا في هذه الرحلة؟ لمحة تاريخية بالعودة إلى زمن ما قبل الأدوات الحديثة كيف كان الحال آنذاك؟ في الحقيقة كانت الأمور بسيطة وسهلةً جدًا. سنبدأ رحلتنا بالتعرف على طرق استخدام لغة جافاسكربت في ملفات HTML. طرق استخدام لغة جافاسكربت يوجد طرقٌ عديدة يمكننا لتضمين الشيفرات البرمجية للغة جافاسكربت في ملفات HTML، يعتمد اختيارنا للطريقة بحسب حجم المشروع الّذي سنعمل عليه وسنذكر أهم الطرق المستخدمة من البداية وحتى يومنا الحالي. الشيفرة السطرية بدأت لغة جافاسكربت في كتابة شيفرتها البرمجية بهذه الطريقة البسيطة إذ أن الشيفرة البرمجية مكتوبة مباشرة في ملف HTML داخل وسم <script>. لا بدّ بأن معظمنا كتبَ شيفرة برمجية بهذه الطريقة في بداية تعلمه لهذه اللغة وذلك من كونها أسهل الطرق لتطبيق شيفرة برمجية معينة. في المثال التالي يحتوي الملف index.html على شيفرة جافاسكربت سطرية: <html> <head> <meta charset="UTF-8"> <title>Inline Example</title> </head> <body> <h1> The Answer is <span id="answer"></span> </h1> <script type="text/javascript"> function add(a, b) { return a + b; } function reduce(arr, iteratee) { var index = 0, length = arr.length, memo = arr[index]; for(index += 1; index < length; index += 1){ memo = iteratee(memo, arr[index]) } return memo; } function sum(arr){ return reduce(arr, add); } /* Main Function */ var values = [ 1, 2, 4, 5, 6, 7, 8, 9 ]; var answer = sum(values) document.getElementById("answer").innerHTML = answer; </script> </body> </html> هذه الطريقة جيدة جدًا للبدء إذ لا يوجد أي ملفات خارجية أو تبعية ناشئة بين الملفات، ولكن هذه هي الطريقة المثالية لبناء شيفرة برمجية غير قابلة للصيانة وذلك بسبب المشاكل التالية: عدم إمكانية إعادة استخدام الشيفرة البرمجية: فإذا احتجنا إلى إضافة صفحة أخرى وهذه الصفحة تحتاج إلى بعض الوظائف المحققة في الشيفرة البرمجية الّتي كتبناها سابقًا في الملف السابق فيجب علينا حينها نسخ الشيفرة البرمجية المطلوبة ولصقها في الصفحة المراد تحقيق الوظائف فيها. عدم وجود ثبات في التبعية بين الشيفرة البرمجية: أنت مسؤول عن تنسيق التبعية بين الدوال المستخدمة على سبيل المثال إن كان هنالك دالة معينة تعتمد في وظيفتها على نتيجة دالة أخرى محققة قبلها فيجب علينا حينها الانتباه لهذا الأمر وعدم تغيير ترتيب تواجد الدوال في الشيفرة البرمجية. التضارب في المتغيرات العامة (Global Variables): جميع الدوال والمتغيرات ستكون موجودة على نطاق عام (Global Scope) وهذا بدوره سيؤدي إلى تضارب في المتحولات، ويحدث هذا عند ازدياد ضخامة المشروع وكتابة شيفرة برمجية كبيرة مما يجعل إمكانية إعادة استخدام نفس أسماء المتحولات أمر وارد الحدوث بقوة، وخصيصًا إن كان هنالك أكثر من مبرمج يعمل على نفس المشروع. استخدام الملفات الخارجية الطريقة الأخرى المستخدمة في كتابة الشيفرة البرمجية للغة جافاسكربت هي استخدام ملفات منفصلة إذ سنجزّء الشيفرة البرمجية إلى أجزاء صغيرة ونحملها تباعًا في ملف index.html. وبهذه الطريقة يمكننا استدعاء مكتبات منفصلة والّتي تقدم لنا وظائف إضافية مثل مكتبة moment (والتي تتيح لنا التلاعب بالتواريخ وإمكانية إجراء تحويلات معينة من نمط تاريخٍ معين إلى نمطٍ آخر). وبالإضافة إلى ذلك أدى استخدام الملفات المنفصلة في الشيفرة البرمجية إلى إتاحة الفرصة لنا بإعادة استخدام الشيفرة البرمجية أكثر من مرة ومن أي مكان نريد، وبذلك نكون تخلصنا من فكرة نسخ الشيفرة البرمجية من مكان ما ولصقها في مكان آخر متى ما أردنا استخدام هذه الشيفرة. الملف index.html هو الملف الّذي سيستدعي جميع التبعيات (ملفات جافاسكربت) الّتي سيحتاجها ويكون محتواه على الشكل التالي: <html> <head> <meta charset="UTF-8"> <title>External File Example</title> <!-- الملف الرئيسي الّذي سيستدعي ملفات جافاسكربت --> </head> <body> <h1> The Answer is <span id="answer"></span> </h1> <script type="text/javascript" src="./add.js"></script> <script type="text/javascript" src="./reduce.js"></script> <script type="text/javascript" src="./sum.js"></script> <script type="text/javascript" src="./main.js"></script> </body> </html> إن هذا المثال يجمع عناصر المصفوفة الموجودة في الملف main.js ويظهرها في صفحة index.html ويكون محتوى الملفات على الشكل التالي: الملف add.js: function add(a, b) { return a + b; } الملف reduce.js function reduce(arr, iteratee) { var index = 0, length = arr.length, memo = arr[index]; index += 1; for(; index < length; index += 1){ memo = iteratee(memo, arr[index]) } return memo; } الملف sum.js function sum(arr){ return reduce(arr, add); } الملف main.js var values = [ 1, 2, 4, 5, 6, 7, 8, 9 ]; var answer = sum(values) document.getElementById("answer").innerHTML = answer; ولكن هذا الحل لم يكُ مثاليًا بل واجه المشاكل التالية: عدم وجود ثبات في التبعية بين الشيفرة البرمجية. التضارب في المتغيرات العامة مازالت موجودة. تحديث المكتبات أو الملفات المستدعاة سيكون يدويًا في حال ظهور نسخة جديدة للمكتبة (أو الملف). زيادة عدد طلبات HTTP بين المخدم والعميل: يؤدي زيادة الملفات المتضمنة في إلى زيادة الحمل على المخدم. فعلى سبيل المثال في الشيفرة السابقة سيحتاج كلّ ملف من الملفات الأربع طلب HTTP منفصل (أي أربع رحلات ذهاب وعودة من المخدم وإلى جهاز العميل) وبناءً عليه سيكون من الأفضل لو استخدمنا ملفًا واحدًا بدلًا من أربع ملفات منفصلة. كما في المثال التالي: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>External File Example</title> <!-- الملف الرئيسي الّذي سيستدعي ملفات جافاسكربت --> </head> <body> <h1> The Answer is <span id="answer"></span> </h1> <script src="/dist/bundle.js"></script> </body> </html> استخدام كائن الوحدات (Module Object) ونمط الوحدات (Module Pattern) باستخدام نمط الوحدات (والذي تحدثنا عنه في مقال مفصّل) يمكننا أن نقلل التضارب في المتغيّرات العامة. إذ إننا سنكشف عن كائن واحد للمجال العام (Global Scope) وهذا الكائن سيحتوي على كافة الدوال والقيم الّتي سنحتاج إليها في تطبيق الوِب خاصتنا. في المثال التالي سنكشف عن كائن واحد وهو myApp للمجال العام (Global Scope)، وكلّ الدوال ستكون متاحة عن طريق هذا الكائن. والمثال التالي سيُوضح الفكرة: الملف my-app.js: var myApp = {}; الملف add.js: (function(){ myApp.add = function(a, b) { return a + b; } })(); الملف reduce.js: (function () { myApp.reduce = function (arr, iteratee) { var index = 0, length = arr.length, memo = arr[index]; index += 1; for (; index < length; index += 1) { memo = iteratee(memo, arr[index]) } return memo; } })(); الملف sum.js: (function () { myApp.sum = function (arr) { return myApp.reduce(arr, myUtil.add); } })(); الملف main.js: (function (app) { var values = [1, 2, 4, 5, 6, 7, 8, 9]; var answer = app.sum(values) document.getElementById("answer").innerHTML = answer; })(myApp); الملف index.html: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JS Modules</title> </head> <body> <h1> The Answer is <span id="answer"></span> </h1> <script type="text/javascript" src="./my-app.js"></script> <script type="text/javascript" src="./add.js"></script> <script type="text/javascript" src="./reduce.js"></script> <script type="text/javascript" src="./sum.js"></script> <script type="text/javascript" src="./main.js"></script> </body> </html> لاحظ أن كلّ ملف من الملفات غُلّف بطريقة نمط الوحدات ما عدا my-app.js إذ أن طريقة التغليف العامة المتبعة في نمط الوحدات هي على الشكل التالي: (function(){ /*... your code goes here ...*/ })(); بهذه الطريقة نجد أن كلّ المتحولات المحلية ستبقى ضمن مجال الدالة المستخدمة فيه. وبذلك لن يكون هنالك أي احتمالية لحدوث تضارب في المتغيرات العامة. وهكذا نكون حللنا مشكلة التضارب في المتغيرات العامة. سيكون الوصول إلى الدوال المعرفة في الملفات مثل (add و reduce ..إلخ) عن طريق ربط اسم الدالة مع الكائن myApp كما في المثال التالي: myApp.add(1,2); myApp.sum([1,2,3,4]); myApp.reduce(add, value); كما يمكننا أيضًا تمرير الكائن myApp كوسيط مثل ما فعلنا في ملف main.js وذلك من أجل تصغير أسم الكائن وجعل الشيفرة البرمجية أصغر حجمًا. تعدّ هذه الطريقة تحسنًا ممتازًا بالموازنة مع المثال السابق وفي الحقيقة إن أشهر مكتبات جافاسكربت مثل jQuery تستخدم هذه الطريقة؛ إذ أنها فقط تكشف عن متغير عام وهو $ وكل التوابع تُستدعى عن طريق هذا الكائن. في الحقيقة إننا إلى هذه اللحظة لم نصل إلى الحل النهائي إذ أن الحل السابق لا يزال يعاني من بعض المشاكل مثل: عدم وجود ثبات في التبعية بين الشيفرة البرمجية: نلاحظ في ملف index.html الملفات لا تزال بحاجة إلى وضعها وفق ترتيب معين يحافظ على التبعية بين الملفات إذ أن الملف myApp.js يجب أن يأتي قبل أي ملف وملف main.js يجب أن يأتي بعد كلّ الملفات. التضارب في المتغيّرات العامة: صحيح أننا قللنا عدد المتغيّرات العامة إلى الواحد ولكنها لا تزال موجودة. تحديث المكتبات: إن تحديث المكتبات (أو التبعيات أو أي ملف عمومًا) المستدعاة سيكون يدويًا في حال ظهور نسخة جديدة للمكتبة أو للتبعية. زيادة عدد طلبات HTTP بين الخادم والعميل: وذلك بعد زيادة عدد الملفات المستدعاة في ملف index.html. ظهور CommonJS جرت نقاشات عديدة في عام 2009 حول إمكانية جلب لغة جافاسكربت إلى الواجهات الخلفية (استخدامها من جانب الخادم) وفعلًا كان ذلك على يد مهندسٍ شاب يعمل لدى شركة موزيلا ويُدعى كيفن دانجور (Kevin Dangoor). قدمت CommonJS طريقة لتعريف الوحدات لحل مشكلة المجال في جافاسكربت من خلال التأكد من تنفيذ كلّ وحدة في فضاء الأسماء (namespace) الخاص بها وذلك بإجبار الوحدات على تصدير تلك المتغيّرات صراحةً (الذين نريد عرضهم واستخدامهم في المجال العام) وأيضًا تعريف تلك الوحدات المطلوبة للعمل بالشكل الصحيح مع بعضها بعضًا. بالإضافة إلى ذلك قدمت CommonJS واجهة برمجية مخصصة للجافاسكربت هذه المميزات فتحت أبصار العالم لإمكانيات هذه اللغة العظيمة، وجذبت اهتمام كبير من المطورين والذي انعكس في سرعة تطورها وتأقلمها مع جميع التغيّرات والمشاكل الّتي واجهتها. إن CommonJS ليست مكتبة جافاسكربت وإنما هي معايير تنظيمية لكتابة الشيفرة البرمجية (على سبيل المثال الطريقة الّتي خصصتها لاستيراد الوحدات استيرادً منظمًا) وهذه المعايير شبيه بالّتي تطرحها منظمة ECMA (European Computer Manufacturers Association). ولتحقيق التنظيم في طريقة استدعاء الوحدات تقدم لنا CommonJS الدوال والأغراض المساعدة لذلك وهي: دالة require(): والّتي تسمح لنا باستيراد وحدات معينة في المجال المحلي الّذي نكون فيه. كائن الوحدة module.exports: والذي يسمح لنا بتصدير دالة ما من المجال الحالي إلى الوحدة. ولنأخذ مثلًا بسيطًا عن كيفية استخدام CommonJS: الملف moduleA.js: module.exports = function( value ){ return value*2; } الملف moduleB.js: var multiplyBy2 = require('./moduleA'); var result = multiplyBy2( 4 ); لاحظ أننا لم نستخدم الاسم الكامل للملف moduleA.js وإنما حذفنا اللاحقة، كما أن /. تشير إلى أن الوحدة moduleA موجودة في نفس المجلد الموجود فيه moduleB. وبفضل مشروع CommonJS ظهر أكبر مشروع معتمدًا عليه وهو Node.js وهي بيئة تشغيل لغة جافاسكربت مفتوحة المصدر وتعمل على جميع أنظمة التشغيل، والّتي تستطيع تشغيل شيفرة جافاسكربت خارج المتصفحات. بالإضافة إلى ذلك تسمح Node.js للمطوري الواجهات الخلفية باستخدام جافاسكربت لكتابة برمجيات تعمل من جهة الخادم وذلك لتوليد صفحات الوِب توليدًا ديناميكيًا قبل إرسالها إلى المتصفح، وكما تستطيع أيضًا التعامل مع الملفات وقواعد البيانات، ومختلف أنظمة الشبكات وخدمات أنظمة التشغيل. الوحدة غير المتزامنة AMD علِمنا إن الهدف الرئيسي الّذي بنيت عليه CommonJS هو استخدامها في الواجهات الخلفية (من طرف المخدم) ولذلك مشكلة استدعاء الوحدات استدعاءً متزامنًا لم تكُ مشكلة في ذلك الحين، بل ولم تكُ لتظهر لولا إصرار مجتمع المطورين على جلب CommonJS إلى الواجهات الأمامية ولنُلخص مشكلة CommonJS هي عندما نستدعي الوحدة معينة في ملف ما ولتكن مثلًا add كما في السطر التالي: var add=require('add'); سيتوقف النظام حتى تصبح الوحدة add جاهزة؛ أي أن هذا السطر البرمجي سيجمد المتصفح أثناء تحميل هذا الملف. ماذا لو كان هنالك أكثر من وحدة مطلوبة كيف ستكون الأمور عندها؟ لذلك إنها ليست أفضل طريقة لتعريف الوحدات من جانب المتصفح. من أجل نقلِ صياغة تعريف وحدة ما من صياغة يفهمها الخادم إلى صياغة يفهمها المتصفح قدمت لنا CommonJS العديد من التنسيقات لتعريف الوحدات وكانت واحدة من أشهرها هي تعريف الوحدات بالطريقة غير المتزامنة (Asynchronous Module Definition) والّتي تُعرف إختصارًا AMD وتكون طريقة تعريفها كما في المثال التالي: define([‘add’, ‘reduce’], function(add, reduce){ return function(){...}; }); إن الدالة define تأخذ قائمة بالتبعيّات الموجودة والتي مرّرناها لها كقائمة وستُعيد النتيجة إلى الدالة المجهولة (Anonymous function) كوسطاء (الدالة المجهولة هي الدالة الّتي ليس لديها اسم ولقد فصلنا في مقالٍ سابق كيفية استخدمها وذلك في سلسلة تعلم جافاسكربت). وسيكون ترتيب التبعيات بنفس الترتيب الموجود في القائمة ومن ثم ستُعيد الدالة المجهولة النتيجة والتي سنُصدرها ونستخدمها في نهاية المطاف. هذه الطريقة تُكافئ الطريقة السابقة لاستدعاء الوحدات (التبعيات) لأنها تعطي نفس النتائج الوظيفية، إلا أن هذه الطريقة تستخدم التحميل غير المتزامن للوحدات. إن CommonJS و AMD حلّت آخر مشكلتين متبقيتين مع نمط الوحدات وهما على الشكل التالي: عدم وجود ثبات في التبعية بين الشيفرة البرمجية. التضارب في المتغيرات العامة. نحن فقط سنهتم بالتبعيات الموجودة من أجل كلّ وحدة (أو ملف) وبالتأكيد في هذه الحالة لا يوجد هناك أي تضارب في المتغيرات العامة. مُحمل الوحدات RequireJS في الحقيقة إن طريقة استخدام AMD مع CommonJS كانت مفيدة جدًا، ولكن كيف يمكننا استخدامها في المتصفح وهنا جاء محمل الوحدات RequireJS إلى الساحة والّذي سيساعدنا لتحميل الوحدات تحميلًا غير متزامن AMD. والذي يعتبر من أوائل التطبيقات الفعلية لمكتبة CommonJS مع AMD. على الرغم من إسمها، إلا أن هدفها ليس دعم بناء جملة 'require' في CommonJS. إن RequireJS تُتيح لنا كتابة وحدات من نمط AMD. ملاحظة: قبل أن تطبق المثال التالي، يجب عليك تنزيل ملف require.js من موقعه الرسمي. لاحظ أن الاستدعاء الوحيد الموجود في ملف index.html هو: <script data-main=”main” src=”require.js”> </script> هذا الوسم سيُحمِّلُ محليًا مكتبة require.js إلى الصفحة، ومن بعدها السمة data-main في الوسم <script> ستخبر المكتبة من أي ملف ستبدأ. بعد أن تستدعي require.js ملف main.js سيقودنا هذا الملف إلى التبعيات المتعلقة به، وهكذا إلى أن نحمل جميع التبعيات (الملفات) المطلوبة. ملاحظة: استخدمنا main فقط بدون الإشارة إلى اللاحقة والتي هي js وذلك لأن هذه المكتبة تفترض بأن كلّ القيم الّتي سنُسندها لهذه الخاصية ستكون ملفات جافاسكربت. وسيكون تحميل التبعيات للمثال السابق كما في الصورة التالية: نلاحظ أن المتصفح يحمّل الملف index.html والملف بدوره يحمّل المكتبة require.js والّذي سيتكفل ببقية الملفات الأخرى. وبهذا نكون حللنا جميع المشاكل الّتي واجهتنا حتى هذه اللحظة، ولكن وكما هي العادة في عالم البرمجة في كلّ محاولة لإصلاح مشكلةٍ ما تظهر مشكلةٌ أخرى، ولكن عادة ما تكون أخف من سابقتها في التأثير. ومن المشاكل الّتي ظهرت مع هذا الحل هي: صياغة AMD طويلة ومضجرة: إذ أن كلّ شيء يجب تغليفة بالدالة define ولذا يوجد مسافة بادئة (يُقصد تعريف الدالة define) للشيفرة البرمجية وهذه المشكلة يمكن ألا تظهر مع الملفات الصغيرة ولكن ما إن يكبر حجم الملف وتزداد تفاصيله ستصبح مشكلة كبيرة. قوائم الاعتماديات الموجودة في المصفوفة: إن قائمة الاعتماديات الموجودة في المصفوفة يجب أن تتشابه تمامًا مع القائمة المررة كوسيط للدالة وإذا كان لدينا العديد من التبعيات ستزداد الأمور تعقيدًا. في النسخة الحالية من HTTP للمتصفحات تحميل العديد من الملفات الصغيرة سيخفف من الأداء (وخصيصًا بدون استخدام أي تقنيات مساعدة مثل: ذاكرة التخزين المؤقت Cache). مجمع الوحدات أو مجمع الحزم (Module Bundler) انطلاقًا من الأسباب السابقة أراد بعض الأشخاص بناء التعليمات من خلال CommonJS لكن هذه الأخيرة مخصصة للعمل على الخوادم وليس المتصفح وهي تدعم التحميل المتزامن أيضًا. بقيت هذه الإشكالية عصية على الحل حتى جاء مجمع الوحدات Browserify لينقذ الموقف ويقدم لنا حلولً مناسبة. وهو يعدّ أول مجمع وحدات وجد آنذاك، وكان باستطاعته تحويل الوحدات المكتوبة بصياغة CommonJS والتي لا يستطيع المتصفح أن يفهمها بطبيعة الحال (وذلك لأنها بُنيت بالأساس للتعامل مع الخادم) إلى صياغة يفهمها المتصفح. يمكننا التعامل مع مجمع الحزم Browserify من خلال سطر الأوامر إذ يمكنك إعطاؤه أمرًا ما وتمرير بعض الخيارات الإضافية المتاحة لكل أمر من الأوامر الموجودة. وهو يعتمد في بنيته على مدير الحزم npm وبيئة Node.js. يمكن لمُجمع الوحدات Browserify تجميع شجرة التبعيات للشيفرة البرمجية الخاصة بك وتحزيمها في ملف واحد. وأيضًا يحل مشكلة عدم إمكانية الوصول إلى الملفات من قبل المتصفح إذ إنه يبحث عن جميع تعليمات require (والتي لا يمكن للمتصفح أن يستدعي الملف المطلوب لأنه لا يملك الصلاحيات المناسبة لذلك) فيستبدلها بمحتوى الملف المراد تضمينه (وذلك انطلاقًا من اعتماده على Node.js والتي تستطيع الوصول إلى الملفات) وهكذا يصبح الملف جاهزًا للتنفيذ في المتصفح ولا يواجه أي مشكلة. حلول كثيرة فأي منها سنستخدم؟ إذا لدينا الكثير من الخيارات المتاحة فأي واحدة منهم سنستخدم في مشروعنا القادم؟ إذ إننا حتى هذه اللحظة ناقشنا العديد من الخيارات المتاحة لكتابة الوحدات مثل: نمط الوحدات (Module Pattern) وطريقة CommonJS مع AMD وطريقة RequireJS فأي منهم سنعتمده لمشروعنا القادم؟ الجواب: ولا واحدة منها. كما نعلم بأن لغة جافاسكربت لم تكُ تدعم نظام الوحدات في أصل اللغة، ولهذا نلاحظ وجود العديد من الخيارات المتاحة لتعويض هذا النقص. ولكن هذا الأمر لم يستمر طويلًا إذ بعد تحديث المواصفات القياسية للغة جافاسكربت ES6 أصبح وأخيرًا نظام الوحدات جزءًا أساسيًا منها وهذا يكون جواب سؤالنا الرئيسي أي الخيارات سنستخدم؟ إنها طريقة ES6 (تحدثنا في سلسلة مقالاتٍ سابقة عن المميزات الجديدة لهذا الإصدار من لغة جافاسكربت ES6). تُستخدم التعليمة import و export لاستيراد وتصدير الوحدات في التحديث الجديد ES6. وإليك مثالًا عمليًا يوضح لك كيفية استخدامها: الملف main.js: import sum from "./sum"; var values = [ 1, 2, 4, 5, 6, 7, 8, 9 ]; var answer = sum(values); document.getElementById("answer").innerHTML = answer; الملف sum.js: import add from './add'; import reduce from './reduce'; export default function sum(arr){ return reduce(arr, add); } الملف add.js: export default function add(a,b){ return a + b; } الملف reduce.js: export default function reduce(arr, iteratee) { let index = 0, length = arr.length, memo = arr[index]; index += 1; for(; index < length; index += 1){ memo = iteratee(memo, arr[index]); } return memo; } في الحقيقة دعم جافاسكربت لنظام الوحدات بهذا الشكل المختصر قلبَ مجريات الُلعبة، بل إن نظام الوحدات هذا سيحكم عالم جافاسكربت في نهاية المطاف. إنها باختصار مستقبل لغة جافاسكربت. ولكن! (أعلم بأنك سئمت من هذه الكلمة ولكن يجب علينا إكمال بقية جوانب هذه الطريقة لتوضيح جميع تفاصيل المشهد لديك) هذا التحديث من اللغة لم تدعمه جميع المتصفحات المستخدمة في هذا اليوم، أو لنكن أكثر دقة ما تزال بعض المتصفحات لا تدعم هذه التحديث وخصوصًا المتصفحات القديمة وفي الحقيقة نسبة المستخدمين لهذه المتصفحات كبيرة وتؤخذ بعين الإعتبار. إذا ما الّذي يجب علينا فعله الآن؟ وكيف سنحوّل الشيفرة البرمجية من الإصدار ES6 إلى الإصدار ES5؟ هنا يأتي دور أهم أداة سنتعرف عليها اليوم ألا وهي مجمع الوحدات Webpack. ما هي Webpack؟ هي عبارة عن مجمع واحدات (Module Bundler) أو أداة بناء (Build Tool) مثل أداة Browserify وهي تحول شجرة تبعية الملفات وتُجمعها في ملف واحد. ليس ذلك فحسب وإنما تحوي على الكثير من المميزات الأخرى نذكر منها: تقسيم الشيفرة البرمجية: عندما يكون لدينا تطبيقات متعددة تتشارك نفس الوحدات يمكننا من خلال هذه الأداة تجميع الشيفرة البرمجية في ملفين أو أكثر. فمثلًا إذا كان لدينا التطبيقين التاليين app1 و app2 ويشترك كلاهما في العديد من الوحدات إذا استخدمنا Browserify سيكون لدينا app1.js و app2.js وكل ملف منهم مجمع فيه الشيفرات البرمجية الخاصة بكل تطبيق، بينما مع أداة Webpack يمكننا إنشاء ملف app1.js وملف app2.js وبالإضافة إلى الملف المشترك shared-lib.js. نعم ستضطر إلى تحميل ملفين في صفحة Html ولكن مع إمكانية استخدام تقنيات مساعدة مثل: التخزين في الذاكرة المؤقتة للمتصفح (Cache) واستخدام شبكة توصيل المحتوى الموزعة CDN (Content Delivery Network) كلّ هذه التقنيات ستقلل من وقت التحميل الإبتدائي للصفحات. المُحملات (Loaders): مع استخدام المُحمل المخصص يمكنك تحميل أي ملف إلى التطبيق إذ يمكنك استخدام الدالة reuiqre ليس فقط لتحميل ملفات جافاسكربت فقط (مثلما كانت أداة Browserify) وإنما ملفات التنسيقات وملفات SaSS وملفات Less بالإضافة إلى إمكانية تحميل الصور والخطوط والملفات والكثير غيرها. الملحقات (Plugins): تقدم Webpack ميزة الملحقات مجموعة واسعة من المهام مثل تحسين الحزمة وإدارة الملحقات (مثل الصور) بالإضافة إلى ذلك يمكننا حتى التلاعب بالملفات قبل تحميلها وتحزيمها في الملف الهدف (على سبيل المثال إمكانية ضغط الصور قبل رفعها على المخدم سنتطرق لهذه الميزّة لاحقًا في هذا الدليل). نظام الأوضاع (Mode): توفر لك هذه الأداة ثلاث أنواع من الأوضاع وضع التطوير ووضع الإنتاج أو بدون وضع. باختصار يستخدم كلّ وضع من الأوضاع من أجل سيناريو معين: وضع التطوير: يستخدم عند العمل في مرحلة التطوير لمشروع الوِب وتكون الشيفرة البرمجية مقروءة ومفهومة. وضع الإنتاج: يستخدم عند العمل في مرحلة عرض مشروع الوِب على الإنترنت وتكون الشيفرة البرمجية مختصرة وغير مقروءة. بدون وضع: يكون الشيفرة الّتي استخدمت في مرحلة التطوير هي ذاتها الّتي ستعرض على الإنترنت بدون أي تعديل. تسهل عملية تحويل الشيفرات البرمجية إلى إصدار أقدم (Transpiling): إمكانية تحويل شيفرات جافاسكربت البرمجية الحديثة مثل ES6 والّتي لا تدعمها بعض المتصفحات إلى شيفرات جافاسكربت البرمجية القديمة مثل ES5 من خلال Babel على سبيل المثال، وبذلك نكون ضربنا عصفورين بحجر واحد أولهما أننا كتبنا التطبيق بالإصدار الحديث من اللغة، وثانيهما أننا استطعنا تشغيل التطبيق على كافة المتصفحات. أليس هذا رائعًا؟ لابد بأنك متحمسٌ جدًا للتعرف على هذه الأداة والبدء في استخدامها على الفور في مشاريعك القادمة إذًا هيا بنا نبدأ لنتعرف عليها أكثر ونتعلم كيفية استخدامها. مفاهيم أساسية قبل الشروع في العمل مع هذه الأداة لا بدّ لنا من التعرف على بعض المفاهيم الرئيسية والتي سنستخدمها بكثرة في الأمثلة ملف الإعداد webpack.config.js :هو عبارة عن ملف يحدد كيفية تعامل الأداة Webpack مع بعض الخصائص للمحملات أو الملحقات وبعض خصائص الأداة نفسها. وعند إنشائنا لمشروع جديد لن نجده في مجلد المشروع وذلك بسبب ميزة التعديلات الصفرية (zero configuration) الجديدة الّتي جاءت مع الإصدار الرابع أو الأحدث من هذه الأداة والتي تمكننا من استخدام الأداة بدون الحاجة لأي تعديل في ملف الإعداد. بل يمكننا عدم إنشاؤه من الأساس. يمكن تخصيص هذا الملف تخصيصًا بسيطًا أو متقدمًا وذلك بحسب المشروع الّذي تعكفُ على تطويره، وهنالك بعض الخصائص الأساسية المشتركة في كلّ المشاريع، والّتي يجب التنويه إليها: الخاصية Entry: تحدد هذه الخاصية ملف الأولي من الشروع الّذي سنبنيه (نجمعه) في أول التنفيذ. الخاصية Output: تحدد مجلد المشروع الّذي سنستخدمه في مرحلة الإنتاج (أو النشر) يكون فيه الشيفرة البرمجية الّتي نريد استخدامها لنشر المشروع على الإنترنت. تحتوي هذه الخاصية على بعض الخيارات نذكر منها: filename: نحدد فيها أسم الملف الّذي نريد تجميع الحزم فيه. path: نحدد فيها مسار الملف الّذي نريد تجميع الحزم فيه. الخاصية Loaders: تحدد المحملات الّتي نريد أن نستخدمها مع Webpack. كلّ مُحمل يحتوي على بعض الخيارات نذكر منها: test: تحدد نوع الملفات الّتي سيُحملها هذا المُحمل (يمكننا استخدام التعابير النمطية في تحديد الملفات). exclude: الملفات الّتي نريد استبعادها (والتي من الممكن أن تحقق الخاصية الأولى). use: ما هو المُحمل الّذي سنستخدمه لإجراء التغييرات على الملفات المقبولة في test ولم تُستبعد في الخاصية exclude. الخاصية Plugins: تحدد هذه الخاصية الملحقات الّتي نريد استخدامها وكما تحدد بعض الخيارات لهذه الملحقات. الخاصية Mode: تحدد هذه الخاصية الوضع الّذي نريد العمل عليه أي طريقة نشر المشروع إلى مجلد الخرج (output). كانت هذه أبرز المفاهيم الأساسية الّتي سنتعامل معها في الأمثلة القادمة. إعداد بيئة التطوير بما أن مجمعات الحزم (الوحدات) تعتمد على Node.js اعتمادً أساسيًا للوصول إلى نظام الملفات من أجل تجميع الاعتماديات بشكلها النهائي لذا لابد لنا من تثبيت Node.js في البداية وإليك الخطوات الكاملة لتثبيته على نظام التشغيل ويندوز (يمكنك الاطلاع على مقال سابق تحدثنا فيه عن كيفية تثبيت Node.js على نظام لينكس): ندخل إلى الموقع الرسمي الخاص ببيئة Node.js ونحمل النسخة الموافقة لنظام التشغيل الخاص بك (يفضل تحميل الإصدارات ذات الدعم الطويل والتي تُدعى LTS). بمجرد إنتهاء التنزيل نفتح الملف المُنزّل. سيسألك معالج التثبيت عن موقع التثبيت والمكونات الّتي تريد تضمينها في عملية التثبيت يمكنك ترك تلك الخيارات بوضعها الافتراضي. انقر فوق تثبيت وانتظر حتى ينتهي معالج التثبيت. تهانينا أصبحت بيئة Node.js جاهزة للعمل. ملاحظة: يمكنك التأكد من تثبيت البيئة تثبيتًا صحيحًا من خلال تنفيذ الأمر التالي على سطر الأوامر (Command line) node –v يجب أن يظهر لك نسخة Node.js المثبتة وفي حالتنا ستظهر 12.16.1. كما يمكنك التأكد من تثبيت مدير الحزم Node Package Manager والّذي يُعرف اختصارًا npm من خلال الأمر npm –v يجب أن تظهر لك نسخة npm المثبتة وفي حالتنا ستظهر 6.13.4. نحن جاهزون الآن لإنشاء مشروع جديد وتثبيت Webpack! إنشاء مشروع جديد وتثبيت Webpack في البداية ننشئ مجلدًا جديدًا للمشروع وندخل إليه عبر التعليمات التالية: $ mkdir project; cd project ثم ننشئ مشروعًا جديدًا عبر التعليمة التالية: $ npm init -y ثم نثبت أداة Webpack عبر التعليمة التالية: $ npm install -D webpack webpack-dev-server يجب أن يظهر لك نتيجة مماثلة للصورة التالية: الآن لننشئ بنية الملفات الهرمية التالية: webpack-demo |- package.json + |- index.html + |- /src + |- index.js ملاحظة: جرى عرض الملفات في هذه المقالة بأسلوب عرض التغييرات في git فالأسطر الّتي بجانبها إشارة موجبة + يجب عليك إضافتها والّتي بجانبها إشارة سالبة - يجب عليك حذفها. الآن نفتح ملف index.js الموجود في مجلد src ونجري عليه التعديلات التالية: unction component() { const element = document.createElement('div'); // Lodash, currently included via a script, is required for this line to work element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element; } document.body.appendChild(component()); ونعدل الملف index.html الموجود في مجلد webpack-demo ونجري عليه التعديلات التالية: <!doctype html> <html> <head> <title>Getting Started</title> <script src="https://unpkg.com/lodash@4.16.6"></script> </head> <body> <script src="./src/index.js"></script> </body> </html> كما يجب علينا أن نعدل ملف package.json لتفعيل الوضع الخاص كي نمنع النشر العرضي للشيفرة البرمجية الخاصة بنا ليصبح على الشكل التالي: { "name": "webpack-demo", "version": "1.0.0", "description": "", + "private": true, - "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "webpack": "^4.20.2", "webpack-cli": "^3.1.2" }, "dependencies": {} } لمزيد من المعلومات حول التفاصيل الداخلية لملف package.json ننصحك بأخذ جولة في التوثيق الرسمي الخاص به. في المثال السابق هنالك تبعيات ضمنية إذ أن الملف index.js يعتمد على loadash (وهي مكتبة تساعد المبرمجين على كتابة شيفرة برمجية أكثر إيجازًا وتزيد من قابلية الصيانة) في عمله وبناءً عليه يجب أن يكون loadash مُضمن قبل أن تعمل الشيفرة البرمجية للملف index.js. ولكن إن الملف index.js لم يُصرح بوضوح عن حاجته لهذه المكتبة وإنما افترض أنها موجودة ضمن المتحولات العامة. في الحقيقة إن إدارة المشروع بهذه الطريقة تعدّ مشكلة وذلك للأسباب التالية: ليس من الواضح أن الشيفرة البرمجية للملف index.js تعتمد على مكتبة خارجية. إذا كانت التبعية مفقودة، أو ضُمنت في الترتيب الخطأ، فلن يعمل التطبيق بالطريقة الصحيحة. إذا ضُمنت تبعيةً ما ولكن لم تُستخدم، سيضطر المتصفح إلى تنزيلها مع أنها غير ضرورية. لنستخدم Webpack لإدارة هذه المشروع بدلًا من الطريقة الحالية. إنشاء حزمة باستخدام Webpack سنعدل بنية المشروع قليلًا لفصل الشيفرة البرمجية الّتي سنعمل عليها عن الشيفرة البرمجية الّتي سننشرها. وتجدر الإشارة إلى أن الشيفرة البرمجية الّتي سننشرها هي الناتج المصغّر والمحسّن لعملية البناء الناتجة عن الشيفرة الّتي كتبناها والتي ستُحمّل في نهاية المطاف في المتصفح. إذًا سنضع الشيفرة البرمجية الّتي سنعمل عليها في المجلد src أما الّتي سننشرها ستكون في مجلد dist أي ستكون بهذا الشكل: webpack-demo |- package.json + |- /dist + |- index.html - |- index.html |- /src |- index.js لتحزيم مكتبة loadash (والّتي هي تبعية في ملف index.html) باستخدام الملف index.js سنحتاج أولًا إلى تثبيت هذه المكتبة محليًا باستخدام الأمر التالي: npm install --save lodash عند تثبيت حزمة (مكتبة) معينة والّتي سنحتاجها في عملية التحزيم النهائية قبل النشر النهائي يجب علينا إضافة install --save أما إذا أردت تثبيت حزمة (مكتبة) معينة لمرحلة التطوير فقط يجب عليك إضافة install --save-dev. لمزيد من المعلومات ننصحك بالإطلاع على التوثيق الرسمي لمدير الحزم NPM. الآن لنضيف تعليمة استيراد الحزمة في الشيفرة البرمجية للملف index.js الموجود في المجلد src كما في الشكل التالي: + import _ from 'lodash'; + function component() { const element = document.createElement('div'); - // Lodash, currently included via a script, is required for this line to work element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element; } document.body.appendChild(component()); بما أننا قمنا باستيراد مكتبة loadash في الملف السابق لنعدل الملف index.html بما يتوافق مع ذلك ليكون كما في الشكل التالي: <!doctype html> <html> <head> <title>Getting Started</title> - <script src="https://unpkg.com/lodash@4.16.6"></script> </head> <body> - <script src="./src/index.js"></script> + <script src="main.js"></script> </body> </html> ملاحظة: يتطلب ملف index.js صراحة وجود المكتبة (أو أي تبعية إذا أردنا تعميم الفكرة) loadash ويربطه كمتحول _ (أي لا يوجد تضارب في المجال). من خلال تحديد التبعيات الّتي تحتاجها الوحدة، يمكن لمُجمع الوحدات (المقصود Webpack) استخدام هذه المعلومات لإنشاء مخطط بياني للاعتماديات (dependency graph). ثم يستخدم الرسم البياني لإنشاء حزمة محسنة والّتي ستُنفذ الاستدعاءات بالترتيب الصحيح. لننفذ التعليمة التالية npx webpack والتي ستأخذ الشيفرة البرمجية في الملف index.js وهو القيمة المسندة للخاصية entry وتنشر الخرج في ملف main.js والذي سيكون القيمة في المسندة للخاصية output. إن تعليمة npx والتي تأتي مع نسخة 8.2 من Node.js أو أحدث، و 5.2.0 من مدير الحزم NPM أو أحدث. إذ تعمل على أداة Webpack الثنائية الموجودة في (./node_modules/.bin/webpack) الّتي ثبتناها في البداية. ويكون ناتج التنفيذ كما يلي: npx webpack ... Built at: 13/06/2018 11:52:07 Asset Size Chunks Chunk Names main.js 70.4 KiB 0 [emitted] main ... WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/ ملاحظة: من الممكن أن يختلف الناتج الّذي سيظهر لك بعض الشيء ولكن إذا نجحت عملية البناء فلا تقلق من رسالة التحذير فإن الأمور على ما يرام. افتح الملف index.html يجب أن يظهر لك Hello webpack فإذا ظهرت لديك تهانينا هذا يدلّ على أنك أنجزت جميع الخطوات بنجاح. إذا ظهرت لديك رسالة خطأ في صياغة ملف جافاسكربت المصغّرة (minified) وذلك عند فتحك لملف index.html فعيّن وضع التطوير ومن ثم شغل الأمر npx webpack من جديد. هذا الخطأ يتعلق بتشغيل حزمة الوٍب npx على أحدث نسخة من Node.js (الإصدار 12.5 أو الأحدث) بدلًا من الإصدار ذو الدعم الطويل LTS. الوحدات في المواصفات القياسية لنسخة جافاسكربت ES6 دُعمت تعليمتي import وexport إذ أن معظم المتصفحات تدعمها في الوقت الحالي (ولكن يوجد بعض المتصفحات لا تدعمها) وWebpack ليست استثناءً بل إنها تدعمها دعمًا متميزًا. تدعم Webpack هذه الخاصية من خلال تحويل (transpiles) الشيفرة البرمجية المقابلة للتعليمتين import وexport إلى نسخة أقدم من ES6 مثل ES5 وبذلك تؤمن فهم المتصفح ما تعنيه هذه التعليمتين باللغة الّتي يفهمها. إضافةً إلى ذلك يدعم Webpack العديد من صيغ الوحدات الأخرى لمزيد من المعلومات يمكنك زيارة التوثيق الرسمي. ملاحظة: إن Webpack لن يحوّل أي تعليمة برمجية عدا تعليمتي import وexport ولذلك في حال كنت تستخدم مميزات أخرى من المواصفات القياسية ES6 فعندها يجب عليك استخدام محولات المخصصة لذلك مثل Babel أو Bublé. استخدام ملف الإعداد إن جميع الإصدارات الّتي جاءت بعد الإصدار الرابع من Webpack تدعم ميزة التعديلات الصفرية الّتي تحدثنا عنها سابقًا في هذا الدليل، ولذا إذا أردنا أن نخصص بعض الإعدادات في المشروع لا بد لنا من إنشاء ملف الإعداد إنشاءً يدويًا. إذًا سنضيف ملف الإعداد على بنية الملفات وستصبح البنية الهرمية للمشروع على الشكل التالي: webpack-demo |- package.json + |- webpack.config.js |- /dist |- index.html |- /src |- index.js وسنُضيف إليه بعض التعليمات المهمة والتي سنستخدمها كثير في المشروع وبذلك ستتحسن إنتاجيتنا أكثر من ذي قبل. وتكون الإضافة كما يلي: const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist'), }, }; أما الآن لنجرب تنفيذ التعليمة التالية: npx webpack --config webpack.config.js ... Asset Size Chunks Chunk Names main.js 70.4 KiB 0 [emitted] main ... WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/ ملاحظة: في حالة وجود أكثر من ملف للإعداد تلتقط التعليمة Webpack ذلك إلتقاطًا إفتراضيًا. ونستخدم خيار --config وبعده اسم الملف لتوضيح فكرة أنه بإمكانك تمرير أسم أي ملف تريده تمريرًا يدويًا، وهذا سيكون مفيدًا جدًا لملفات الإعداد الأكثر تعقيدًا والتي سنحتاج لتقسيمها إلى ملفات متعددة. يتيح ملف التكوين مرونة أكبر بكثير من استخدام سطر الأوامر CLI (Command Line Interface) البسيط. إذ يمكننا تحديد وتثبيت قواعد معينة للمُحمل (Loader) والملحقات (Plugin) وتخصيص الخيارات بالإضافة للعديد من التحسينات الأخرى. لمزيد من المعلومات يمكنك الإطلاع على التوثيق الرسمي لملف الإعداد. إنشاء إختصار لتعليمة البناء يمكننا استخدام مميزات Webpack لجعل الأمور أسهل من خلال وضع بعض اللمسات الجمالية مثل اختصار بعض الخطوات، وذلك من خلال كتابة الأوامر في ملف package.json وتحديدًا في scripts. وبذلك نختصر على أنفسنا عناء كتابة بعض التعليمات الطويلة والمُملة. إذًا لنعدل ملف package.json ليصبح على الشكل التالي: { "name": "webpack-demo", "version": "1.0.0", "description": "", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "build": "webpack" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "webpack": "^4.20.2", "webpack-cli": "^3.1.2" }, "dependencies": { "lodash": "^4.17.5" } } يمكننا الآن استخدام الأمر npm run build بدلًا من الأمر npx الّذي استخدمنا سابقًا. لاحظ بأنه يمكننا دائمًا الإشارة إلى الحزم المثبتة محليًا في مدير الحزم npm في السمة scripts في الملف package.json بنفس الطريقة الّتي استخدمناها مع التعليمة npx. هذا الطريقة هي متعارف عليها في معظم المشاريع القائمة على مدير الحزم npm لأنه يسمح لجميع المساهمين لاستخدام نفس التعليمات المشتركة (وحتى مع بعض الخيارات مثل --config). ملاحظة: يمكنك تمرير الخيارات الخاصة لتعليمة ما من خلال إضافة شرطتين -- بين الأمر npm run build والخيارات الّتي نريد تخصيصها مثل npm run build -- --colors. npm run build ... Asset Size Chunks Chunk Names main.js 70.4 KiB 0 [emitted] main ... WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/. أما الآن وبعد أن تعلمنا الأساسيات عن كيفية استخدام Webpack لننتقل إلى الاستخدامات الأهم لهذه الأداة مثل إدارة الصور والخطوط ..إلخ. إذا نفذت جميع التعليمات السابقة تنفيذًا صحيحًا يجب أن يكون البنية الهرمية للمشروع على الشكل التالي: webpack-demo |- package.json |- webpack.config.js |- /dist |- main.js |- index.html |- /src |- index.js |- /node_modules ملاحظة: إذا كنت تستخدم الإصدار الخامس من مدير الحزم npm من الممكن أن ترى ملفًا إضافيًا اسمه package-lock.json. استخدام Webpack لإدارة الملحقات بعد أن تعلمنا أساسيات Webpack وإنشأنا مشروعًا صغيرًا يعرض "Hello Webpack"، سنحاول الآن أن نركز أكثر على الأمور المهمة والتي تخدمنا بها هذه الأداة مثل إدارة ملفات التنسيق والصور وسنرى بالضبط كيف تتعامل هذه الأداة مع كلٍّ منهم. يستخدم مطورو الواجهات الأمامية أدوات بناء مثل: Grunt و Glup لمعالجة هذه الملحقات ونقلها من مجلد src إلى مجلد dist أو حتى لإنشاء مجلد جديد لهذه الملحقات، تستخدم Webpack نفس الفكرة للتعامل مع الوحدات، بالإضافة إلى أن Webpack تجمع كلّ التبعيات ديناميكيًا وتنشئ ما يعرف بمخطط التبعيات وهذا أمر رائع لأن كلّ وحدة (Module) توضح صراحة ما هي تبعياتها وبذلك نتجنب تجميع الوحدات غير المستخدمة في المشروع. واحدة من أروع مميزات Webpack هي إعطاؤك إمكانية تضمين أي نوع آخر من الملفات، إلى جانب جافاسكربت، ولهذه الفكرة تحديدًا أنشئ المحمل (Loader). أي يمكن تطبيق نفس المزايا المذكورة أعلاه (التبعيات المستخدمة من قبل الوحدات) على كلّ شيء مستخدم في إنشاء المواقع أو تطبيقات الوِب أيضًا. إدارة ملفات التنسيق CSS في البداية سنعدل قليلًا في بنية الملفات وبعض الملفات قبل أن ندير ملفات التنسيق. سنعدل الملف dist/index.html ليصبح كما يلي: <!doctype html> <html> <head> - <title>Getting Started</title> + <title>Asset Management</title> </head> <body> - <script src="main.js"></script> + <script src="bundle.js"></script> </body> </html> وكما سنعدل أيضًا ملف الإعداد webpack.config.js ليصبح: const path = require('path'); module.exports = { entry: './src/index.js', output: { - filename: 'main.js', + filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, }; وبذلك يُصبح كلّ شيء جاهز لنبدأ. أولًا لنثبت محمل ملفات التنسيق css-loader الّذي سيساعدنا في معالجة تعليمة الاستيراد import الّتي سنستخدمها أيضًا من أجل استيراد ملفات التنسيق ومحمل التنسيق style-loader الّذي سيساعدنا في أخذ ملف التنسيق ووضعه في ملف (أو ملفات) تنسيق منفصلة. إذًا لنُنفذ الأمر التالي: npm install --save-dev style-loader css-loader ولنُعدل ملف الإعداد webpack.config.js ليحوي المعلومات اللازمة لحزم المُحمل (Loader) الّتي ثبتناها للتو وسيصبح الملف على الشكل التالي: const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + 'style-loader', + 'css-loader', + ], + }, + ], + }, }; ملاحظة: تستخدم Webpack التعابير النمطية (Regular Expression) لتحديد الملفات الّتي يجب البحث عنها وتقديمها إلى مُحمل (Loader) محدد. في الحالة السابقة نلاحظ أنه ستُقدم جميع ملفات التنسيق (ذات اللاحقة css) إلى المُحمل style-loader والمُحمل css-loader. وهذا بدوره سيمكنك من استيراد ملف التنسيق الّذي سيكون مثل هذا import './style.css' إلى الملف الّذي يعتمد على ملف التنسيق هذا. عند تشغيل مجمع الحزم Webpack سيُضاف ملف تنسيق مخصص في وسم <style> وذلك في داخل الوسم <head>. لنجرب ذلك من خلال إضافة ملف تنسيق جديد style.css إلى مشروعنا واستيراده في الملف index.js: لننشئ أولًا ملف التنسيق style.css في مشروعنا لتصبح البنية الهرمية للمشروع على الشكل التالي: webpack-demo |- package.json |- webpack.config.js |- /dist |- bundle.js |- index.html |- /src + |- style.css |- index.js |- /node_modules ومن ثم لنُضف بعض الخصائص إلى ملف style.css ليصبح على الشكل التالي: .hello { color: red; } ولنستدعي ملف التنسيق style.css في ملف index.js ليصبح على الشكل التالي: import _ from 'lodash'; + import './style.css'; function component() { const element = document.createElement('div'); // Lodash, now imported by this script element.innerHTML = _.join(['Hello', 'webpack'], ' '); + element.classList.add('hello'); return element; } document.body.appendChild(component()); ومن ثم نُنفذ أمر البناء التالي: npm run build ... Asset Size Chunks Chunk Names bundle.js 76.4 KiB 0 [emitted] main Entrypoint main = bundle.js لنفتح الآن ملف index.html ولنرى ما هي التغييرات الّتي جرت عليه. لاحظ أن كلمة "Hello Webpack" أصبحت الآن باللون الأحمر. لمعرفة ما الّذي فعلته Webpack افحص الصفحة من خلال أدوات المطوّر (المُقدمة من متصفح جوجل كروم على سبيل المثال)، ولكن لا تعرض مصدر الصفحة لأنها لن تقدم لك النتيجة الّتي نود الإشارة إليها. إذ أن الوسم <style> سيُنشئ ديناميكيًا من قِبل جافاسكربت. لذلك افحصها حصرًا من خلال أدوات المطوّر وافحص تحديدًا الوسم <head> يجب أن يحتوي على الوسم <style> والذي استوردناه في ملف index.js. ملاحظة: سابقًا كان علينا تصغير (Minimize) ملفات التنسيق تصغيرًا يدويًا قدر الإمكان وذلك بحذف المساحات الفارغة بين الخصائص الموجودة في الملف من أجل زيادة سرعة تحميل الصفحة، ولكن مع الإصدار الرابع من مجمع الحزم 4 Webpack أو الأحدث منه أصبح تصغير ملفات التنسيق خطوة افتراضية في الأداة، وبذلك أضافت لنا هذه الأداة بُعدًا آخر لتحسين الشيفرة البرمجية وسبب وجيّه لزيادة محبتنا لها. إدارة ملفات SASS تتيح لنا Webpack إمكانية التعامل مع ملفات SASS وتحويلها إلى ملفات تنسيق عادية. ولنأخذ مثالًا عمليًا نطبق فيه كيفية تحويل ملفات SASS إلى ملفات تنسيق عادية. سنركز في هذا المثال على دعم الملفات SCSS مثل: (your-styles.scss) و الملفات SCSS modules مثل: (your-component.module.scss). تجنبًا لتعقيد الأمور أكثر من اللازم سنبدأ بمشروع جديد ننفذ فيه هذه الفكرة. سنفترض أنك أنشأت مشروعًا جديدًا وثبتّ أداة Webpack، لننتقل الآن لتثبيت الإضافات والمُحملات اللازمة لهذا المشروع. سنبدأ أولًا بتثبيت الحزم التالية: npm install --save-dev node-sass sass-loader style-loader css-loader mini-css-extract-plugin ستكون مهمة كلّ حزمة من الحزم على الشكل التالي: node-sass: ستوفر هذه الحزمة ربط Node.js مع LibSass وهذا الأخير هو مترجم SASS. sass-loader: هو مُحمّل ملفات SASS إلى مشروعنا. css-loader: تستخدم هذه الحزمة لتفسير التعليمة @import و @url() بما تشير إليه في ملفات التنسيق. style-loader: تستخدم هذه الحزمة لإسناد الخصائص الموجودة في ملفات التنسيق إلى الوسوم الفعلية في شجرة DOM الافتراضية. mini-css-extract-plugin: هذه الحزمة تستخرج الخصائص الموجودة في ملفات التنسيق إلى ملفات منفصلة. إذ أنها تنشئ لكل ملف جافاسكربت ملف تنسيق الخاص به وهو لدعم ميّزة التحميل عند الطلب (On-Demand-Loading) لملفات التنسيق و خرائط الشيفرة البرمجية المحوّلة Source Maps (لمزيد من المعلومات عنها يمكنك الإطلاع على المقال التالي). سنحتاج إلى إضافة مُحملين، أحدهما للتنسيقات العامة والأخرى للتنسيقات المركبة. واللّذان يشار إليهما بملفات (SCSS modules). إذ أن هذه الأخيرة تعمل جيدًا مع المكتبات أو أطر العمل المُعتمدة على المكونات (component-based) مثل: React. سنضيف هذه الحزمة الملحقة إلى ملف الإعداد webpack.config.js على الشكل التالي: + const MiniCssExtractPlugin = require('mini-css-extract-plugin') module.exports = { plugins: [ + new MiniCssExtractPlugin({ + filename: isDevelopment ? '[name].css' : '[name].[hash].css', + chunkFilename: isDevelopment ? '[id].css' : '[id].[hash].css' + }) ] } نلاحظ أننا أضفنا خاصية أسماء الملفات المجزأة من أجل زيادة فعالية وسهولة خرق ذاكرة التخزين المؤقّت (Cache Bustring وهي تحِلُّ مشكلة التخزين المؤقت في المتصفح باستخدام إصدار معرف فريد للملف يميزه وذلك من أجل أخباره في حال وجود نسخة جديدة من الملف الذي حفظه فعلًا في هذه الذاكرة، وذلك من أجل أن يحملها تلقائيًا إلى ذاكرة التخزين المؤقت بدلًا من نسخة الملف القديمة الموجودة فيه)، والآن سنضيف الخواص المناسبة لملف الإعداد webpack.config.js من أجل عملية التحويل المناسبة للملفات: module.exports = { module: { rules: [ + { + test: /\.module\.s(a|c)ss$/, + loader: [ + isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader, + { + loader: 'css-loader', + options: { + modules: true, + sourceMap: isDevelopment + } + }, + { + loader: 'sass-loader', + options: { + sourceMap: isDevelopment + } + } + ] + }, + { + test: /\.s(a|c)ss$/, + exclude: /\.module.(s(a|c)ss)$/, + loader: [ + isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader, + 'css-loader', + { + loader: 'sass-loader', + options: { + sourceMap: isDevelopment + } + } + ] + } ] }, resolve: { - extensions: ['.js', '.jsx'] + extensions: ['.js', '.jsx', '.scss'] } } نلاحظ أن القاعدة الأولى المطبقة في الشيفرة السابقة ستُطبق على الملفات ذات الامتدادات .module.scss أو .module.sass إذ في البداية ستُحوّلُ ملفات SASS إلى CSS من خلال sass-loader ومن ثم ستُمرّر إلى الحزمة css-loader لمعالجة التعليمات @import() و url() ..إلخ. ومن ثمّ ستُسندُ الحزمة style-loader الخصائص المناسبة في DOM أو ستسند من خلال الحزمة Mini CSS Extract Plugin وذلك لإخراج ملفات التنسيق أثناء وضع النشر. القاعدة الثانية مشابهة جدًا للقاعدة الأولى باستثناء أننا لا نحوّل أسماء الأصناف. الآن أصبح ملف الإعداد جاهز نحتاج الآن لإنشاء ملف تنسيقات SASS للتأكد من أن كل شيء يعمل مثلما خطط له. أنشئ مجلد src ثم أنشئ بداخله ملفًا جديدًا باسم app.module.scss وأضف الشيفرة البرمجية التالية: .red { color: red; } أي عنصر سيأخذ الصنف red سيكون لونه أحمر. افتح الملف app.js واستدعي الملف السابق على الشكل التالي: import styles from './app.module' نلاحظ أن اسم الملف لا يحتوي على اللاحقة .scss وذلك لأننا سبق وأخبرنا Webpack بأن يأخذ بعين الاعتبار هذه اللاحقة وذلك في ملف الإعداد. ثم لنُضيف الآن الدالة التالية في نفس الملف app.js ليصبح على الشكل التالي: function App() { return <h2 className={styles.red}>This is our React application!</h2> } أليست سهلة جدًا؟ بغض النظر عن كيفية تحويل الحزمة css-loader اسم الصنف الّذي بنيناه (red) والّذي سيصبح مثل: _1S0lDPmyPNEJpMz0dtrm3F أو شيء من هذا القبيل، ولكنها ساعدتنا في مهمتنا مساعدةً كبيرة. لنُضيف الآن بعض التنسيقات العمومية. لننشئ ملف جديد وليكن global.scss في المجلد src ولِنفتحه ونُضيف بداخله الشيفرة البرمجية التالية: body { background-color: yellow; } هذا الملف سيجعل لون خلفية الصفحة الرئيسية لتطبيق الوِب خاصتنا أصفر. ولكن يجب أن نفتح الملف index.js ونستدعي ملف التنسيق السابق في بداية الملف. مثلما هو موضح في الشيفرة التالية: import './global' واخيرًا سنحصل على الخرج التالي: نلاحظ أن استخدام وحدات SCSS يتطلب منا جهدًا لا بأس به، ولكن بالموازنة مع كمية الفائدة الّتي تقدمها وحدات SCSS من سهولة في الصيانة لتطبيق الوِب في المستقبل فأعتقد أن الأمر يستحق هذا الجهد. بالإضافة إلى ذلك توفر أداة Webpack حزم أُخرى مخصصة لأي نكهة من نكهات ملفات التنسيق مثل الحزمة: postcss لتوفير دعم Postcss أو الحزمة Less لدعم ملفات التنسيق من نوع Less أيضًا. إدارة الصور تتيح Webpack لنا إمكانية إدارة الصور مثل: الخلفيات والأيقونات وذلك من خلال مُحمل الملفات. في البداية لنثبت أولًا مُحمل الملفات من خلال الأمر التالي: npm install --save-dev file-loader ومن ثم سنضيف إلى ملف الإعداد webpack.config.js المعلومات اللازمة لعمل هذا المُحمل كما في الشكل التالي: const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader' ], }, + { + test: /\.(png|svg|jpg|gif)$/, + use: [ + 'file-loader', + ], + }, ], }, }; عند استيراد لصورة معينة ولتكن import MyImage from './my-image.png' ستضاف هذه الصورة إلى مجلد الخرج (output) الّذي حددناه في ملف الإعداد وسيحمل المتغير MyImage عنوان الرابط التشعبي الخاص بالصورة (URL) بعد معالجتها. عندما استخدمنا محمل ملفات التنسيق css-loader جرى نفس السيناريو السابق. أي أنه سيكون الخاصية التالية في ملفات التنسيق url('./my-image.png') والمُحمل سيلاحظ أن الملف هذا موجود محليًا وبذلك سيُحول './my-image.png' إلى المسار النهائي المُسند للخاصية (output) في ملف الإعداد webpack.config.js ومُحمل ملفات html (html-loader) سيتعامل مع <img src="./my-image.png" /> بنفس الطريقة. لنُضف الآن الصور اللازمة في مشروعنا. وهنا يمكنك استخدام أي صورة تريدها. لننسخ الصورة الّتي سنعمل عليها ولتكن icon.png إلى مشروعنا. لتصبح البنية الهرمية للمشروع على الشكل التالي: webpack-demo |- package.json |- webpack.config.js |- /dist |- bundle.js |- index.html |- /src + |- icon.png |- style.css |- index.js |- /node_modules ومن ثم لنستورد هذه الصورة في ملف src/index.js، ولنُضيفها إلى وسم <div> المتواجدة فيه، ولتصبح الشيفرة البرمجية للملف src/index.js على الشكل التالي: import _ from 'lodash'; import './style.css'; + import Icon from './icon.png'; function component() { const element = document.createElement('div'); // Lodash, now imported by this script element.innerHTML = _.join(['Hello', 'webpack'], ' '); element.classList.add('hello'); + // Add the image to our existing div. + const myIcon = new Image(); + myIcon.src = Icon; + + element.appendChild(myIcon); return element; } document.body.appendChild(component()); ومن ثم سنعدل ملف التنسيق من أجل تضمين الصور الّتي نعمل عليها ليصبح بذلك ملف التنسيق src/style.css على الشكل التالي: .hello { color: red; + background: url('./icon.png'); } ولننفذ الآن أمر البناء التالي: npm run build ... Asset Size Chunks Chunk Names da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] bundle.js 76.7 KiB 0 [emitted] main Entrypoint main = bundle.js ... إذا نفذت جميع الخطوات السابقة تنفيذًا صحيحًا يجب أن ترى الأيقونة (الصورة) مكررة في الخلفية، بالإضافة إلى وسم <img> بجوار النص "Hello webpack". وإذا فحصت الصورة ستجد أن اسمها الفعلي تغيّر إلى شيء شبيه بهذا الاسم 5c999da72346a995e7e2718865d019c8.png هذا يعني أن Webpack عثرت على الملف في مجلد src وعالجته. الخطوة المنطقية التالية الّتي سننفذها هي تصغير حجم الصور الّتي سنستخدمها في المشروع وتحسينها وذلك من خلال الحزم المساعدة المتوفرة مع الأداة Webpack مثل الحزمة Imagemin. ضغط الصور باستخدام Imagemin إن طريقة ضغط الصور الّتي سنستخدمها في المشروع هي باستخدام حزمة Imagemin إذ تعدّ هذه الحزمة خيارًا ممتازًا وذلك لأنها تدعم مجموعة متنوعة من أنواع الصور وسهلة التكامل مع الشيفرة البرمجية لأدوات البناء أو مجمع الحزم (الوحدات). سنعمل على مشروع جديد تجنبًا للمشاكل التي من الممكن أن تظهر لنا في حال أكملنا العمل على المشروع السابق. سنفرض أنك أنشأت مشروعًا جديدًا وثبّت الأداة Webpack تثبيتًا صحيحًا. في البداية لنثبت هذه الحزم عبر التعليمة التالية: npm install imagemin-webpack-plugin copy-webpack-plugin --save-dev ملاحظة: أن الحزمة copy-webpack-plugin ستساعدنا على نسخ الصور من مجلد images/ إلى مجلد dist/ وهو مجلد النشر وهو اختصار لكلمة distribution. لننشئ ملف الإعداد webpack.config.js ولنعدله ليتناسب مع الحزم الجديدة ليصبح على الشكل التالي: const ImageminPlugin = require('imagemin-webpack-plugin').default; const CopyWebpackPlugin = require('copy-webpack-plugin'); const path = require('path'); module.exports = { entry: './index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, plugins: [ new CopyWebpackPlugin([{ from: 'img/**/**', to: path.resolve(__dirname, 'dist') }]), new ImageminPlugin() ] } تعدّ هذه الطريقة من أسهل الطرق لإعداد لهذه الحزمة. ولنضغط الصور الّتي في المجلد images/ وننسخها إلى المجلد dist/ من خلال تنفيذ الأمر التالي: webpack --config webpack.config.js --mode development نلاحظ من التعليمة السابقة أن وضع التنفيذ الحالي هو وضع التطوير، ولكن ما الّذي سيحدث إذا نفذنا التعليمة في وضع النشر؟ لنرى ما الّذي سيحدث. webpack --config webpack.config.js --mode production ستُظهر لنا في هذه المرة أداة Webpack تحذيرًا يخبرك بأن الصور ذات النوعية PNG الخاصة بك لا تزال تتجاوز الحد الأقصى للحجم الموصى به، على الرغم من بعض الضغط. ولذلك سنحتاج إلى ضبط اليدوي لعملية الضغط لهذا النوع من الصور لتصبح أفضل مما قبل. لنعدل قيمة الضغط للصور ذات النوعية PNG لتصبح 50% وسيكون ملف الإعداد على الشكل التالي: const ImageminPlugin = require('imagemin-webpack-plugin').default; const CopyWebpackPlugin = require('copy-webpack-plugin'); const path = require('path'); module.exports = { entry: './index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, plugins: [ new CopyWebpackPlugin([{ from: 'img/**/**', to: path.resolve(__dirname, 'dist') }]), new ImageminPlugin({ pngquant: ({quality: [0.5, 0.5]}), }) ] } نلاحظ أننا مررنا للغرض Pngquant مجالًا لقيمة جودة الصور من 0.5 إلى 0.5 أي من الحدّ الأدنى إلى الحدّ الأعلى لجودة الصورة. إذ أن الحدّ الأعلى الأفتراضي 1 والحدّ الأدنى الافتراضي 0. ولكن ماذا لو أردنا أن نضبط الجودة (نسبة الضغط) المستخدمة لبقية الأنواع من الصور بنفس الطريقة السابقة؟ في الحقيقة يوجد بعض الملحقات الإضافية المساعدة لهذا الغرض تحديدًا والّتي سنستعرضها في هذا الجدول: نوع الصور ضغط مع خسارة بعض معلومات الصورة ضغط بدون خسارة بعض معلومات الصورة JPEG imagemin-mozjpeg imagemin-jpegtran PNG imagemin-pngquant imagemin-optipng GIF imagemin-giflossy imagemin-gifsicle SVG Imagemin-svgo WebP imagemin-webp table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } نلاحظ أن لدينا نوعين من طرق ضغط الصور وهما كالتالي: ضغط مع خسارة بعض معلومات الصورة (Lossy): يؤدي استخدام هذا النوع إلى تصغير حجم الصورة تصغيرًا ملحوظًا، ولكن مع فقدان بعض معلومات الصورة. ضغط بدون خسارة بعض معلومات الصورة (Lossless): يؤدي استخدام هذا النوع إلى تصغير حجم الصورة تصغيرًا أقل من الطريقة السابقة، ولكن بدون فقدان بعض معلومات الصورة. إن طريقة الضغط الإفتراضية للحزمة imagemin للصور ذات النوعية JPEG هي الطريقة imagemin-jpegtran، سنستعرض كيفية ضغط الصور باستخدام الحزمة الأخرى وهي imagemin-mozjpeg. في البداية يجب علينا تثبيت هذه الحزمة من خلال الأمر التالي: npm install imagemin-mozjpeg ولنُعدل ملف الإعداد webpack.config.js لضبط طريقة ضغط الصور وفق ما نريده. ليصبح الملف على الشكل التالي: const imageminMozjpeg = require('imagemin-mozjpeg'); const ImageminPlugin = require('imagemin-webpack-plugin').default; const CopyWebpackPlugin = require('copy-webpack-plugin'); const path = require('path'); module.exports = { entry: './index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, plugins: [ new CopyWebpackPlugin([{ from: 'img/**/**', to: path.resolve(__dirname, 'dist') }]), new ImageminPlugin({ pngquant: ({quality: [0.5, 0.5]}), plugins: [imageminMozjpeg({quality: 50})] }) ] } نلاحظ أن نسبة الضغط في هذه الحزمة من 100 إذ مررنا القيمة 50 وبذلك نخبره بأننا نريد ضغط الصور من النوع JPEG بنسبة 50%. ولنُنفذ الآن التعليمة التالية لنرى النتيجة: webpack --config webpack.config.js --mode production تهانينا في حال نفذّت جميع الخطوات تنفيذًا صحيحًا يجب أن تكون الصور مضغوطة وفقَ المطلوب. إن الأداة Webpack تحذرنا من الصور ذات الحجم الكبير، ولكنها لا تستطيع إخبارنا إن كانت الصور مضغوطة أم لا، ولهذا السبب سنستخدم الأداة Lighthouse للتحقق من التغييرات المُنفّذة. تسمح لنا الأداة Lighthouse من التحقق من ترميز الصور بكفاءة وإن كانت الصور الموجودة في صفحتك مضغوطة على نحوٍ أمثلي أم لا (لمزيد من المعلومات حول هذه الأدة ننصحك بالاطلاع على هذا المقال المفصّل). وستكون النتيجة مشابهة للصورة التالية: بنفس الطريقة يمكنك استخدام بقية الحزم لتخصيص قيمة الضغط المطلوب للأنواع الأخرى من الصور المستخدمة في مشروعك. إدارة الخطوط يمكننا إدارة الخطوط أيضًا مع Webpack من خلال مُحمل الملفات الّذي ثبتناه في إدارة الصور (سنعمل على نفس المشروع الّذي بنيناه في فقرة إدارة الصور)، والذي سيأخذ أي ملف تضعه له في ملف الإعداد ويضعه في المسار النهائي المُسند للخاصية (output) في ملف الإعداد webpack.config.js. أي أن مُحمل الملفات قادر على التعامل الخطوط أيضًا. لنعدل الآن ملف الإعداد webpack.config.js ليصبح على الشكل التالي: const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader' ], }, { test: /\.(png|svg|jpg|gif)$/, use: [ 'file-loader', ], }, + { + test: /\.(woff|woff2|eot|ttf|otf)$/, + use: [ + 'file-loader', + ], + }, ], }, }; أضف خطًا معينًا إلى مجلد المشروع لتصبح البنية الهرمية للمشروع على الشكل التالي: webpack-demo |- package.json |- webpack.config.js |- /dist |- bundle.js |- index.html |- /src + |- my-font.woff + |- my-font.woff2 |- icon.png |- style.css |- index.js |- /node_modules من خلال التعديلات الّتي أجريناها على ملف الإعداد لمُحمل الملفات يمكننا الآن جعل التعليمة الّتي تصرح بها عن المسارات للخطوط @font-face إلى الشكل التالي url(...). سيعاد توجيه هذه المسارات إلى المسار النهائي المُسند للخاصية (output) في ملف الإعداد webpack.config.js تمامًا كما تعامل مع الصور. إذا سيصبح ملف التنسيق src/style.css على الشكل التالي: + @font-face { + font-family: 'MyFont'; + src: url('./my-font.woff2') format('woff2'), + url('./my-font.woff') format('woff'); + font-weight: 600; + font-style: normal; + } .hello { color: red; + font-family: 'MyFont'; background: url('./icon.png'); } لنرى كيف سيتعامل Webpack مع الخطوط ولننفذ أمر البناء على الشكل التالي: npm run build ... Asset Size Chunks Chunk Names 5439466351d432b73fdb518c6ae9654a.woff2 19.5 KiB [emitted] 387c65cc923ad19790469cfb5b7cb583.woff 23.4 KiB [emitted] da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] bundle.js 77 KiB 0 [emitted] main Entrypoint main = bundle.js ... افتح ملف index.html وانظر إلى النص "Hello webpack" كيف تغير شكل الخط ليصبح مطابق لشكل الخط الجديد. أما الآن لننتقل إلى واحدٍ من أبرز استخدامات مجمع الحزم Webpack وهو تحويل الشيفرات البرمجية الخاصة بالإصدارات الحديثة من المواصفات القياسية للغة جافاسكربت مثل ES6 إلى ES5. تحويل الشيفرة البرمجية باستخدام Babel بعد أن تعرفنا كيف ندير جميع التبعيات الموجودة في شيفرات جافاسكربت البرمجية من خلال Webpack. لا بُدّ لنا من جعل هذه الشيفرة البرمجية تعمل على جميع المتصفحات وذلك لكي نضمن أنه مهما يكن المتصفح الّذي سيستخدمه العميل (أو المستخدم) ستظهر النتيجة المطلوبة تمامًا مثل ما نريده. عملية التحويل (Transpiling): هي عملية تغيير الشيفرة البرمجية من إصدار معين إلى إصدار أقدم وذلك لضمان عمل هذه الشيفرة البرمجية على المتصفحات كلها. مقتطف من المخطط التفصيلي لدعم المتصفحات للمميزات الإصدار ES5 والإصدار ES6 من لغة جافاسكربت. سننشئ مشروعًا بسيطًا لشرح طريقة استخدام هذا المُحول: mkdir webpack-demo2 cd webpack-demo2 npm init -y npm install webpack webpack-cli --save-dev ملاحظة: لن نتطرق للتفاصيل نظرًا لأنها شُرحت في بداية هذا الدليل. ستكون البنية الهرمية للمشروع على الشكل التالي: webpack-demo2 |- package.json + |- index.html + |- /src + |- index.js في البداية سنحتاج لتثبيت ثلاث حزم للتعامل مع المحول Babel وستكون على الشكل التالي: npm install babel-core babel-loader babel-preset-env --save-dev الحزمة babel-core: تحتوي على الشيفرة البرمجية للنواة الأساسية للمُحول Babel. الحزمة babel-preset-env: تحتوي على الشيفرة البرمجية الّتي ستمكن النواة الأساسية للمحول Babel من تحويل الشيفرة البرمجية للجافاسكربت ذات الإصدار 6ES إلى الإصدار ES5. الحزمة babel-loader: أو (مُحمل المحول) وهي الّتي ستستخدمها Webpack في تحميل المحول والتعامل معه في عملية التحزيم (Bundling). أما الآن سننشئ ملف babelrc. والذي سيطلب من المحول Babel أن يستخدم الحزمة babel-preset-env أثناء عملية التحويل وسيكون الملف babelrc. على الشكل التالي: +{ "presets": ["env"] } ومن ثم سننشئ ملف الإعداد webpack.config.js ونطلب من Webpack الإستعانة بالمحمل Babel أثناء تحزيمه. وسيكون ملف الإعداد webpack.config.js على الشكل التالي: + const path = require('path'); + module.exports = { + entry: { main: './src/index.js' }, + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'main.js' + }, + module: { + rules: [ + { + test: /\.js$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader' + } + } + ] + } + }; سنضع الآن في ملف src/index.js شيفرة برمجية من الإصدار ES6، وليصبح على الشكل التالي: + const fn = () => "Arrow functions're Working!"; + alert(fn()); ومن ثم ننفذ الأمر التالي: npm run dev ومن ثم لنفتح ملف dist/main.js نلاحظ أن الدالة السهمية (Arrow function) تُحوّلُ إلى دالة عادية وذلك وفق الطريقة المتبعة في الإصدار ES5 من لغة جافاسكربت. وسيكون محتوى الملف dist/main.js على الشكل التالي: 'use strict'; var fn = function fn() { return "Arrow functions're Working!"; }; alert(fn()); وبذلك استطعنا استخدام مميزات الإصدار الحديث من لغة جافاسكربت ES6 وتحويله إلى إصدار أقدم ES5 لتفهمه المتصفحات القديمة. هل من المخاطرة تعلم Webpack؟ بعد أن تعرفنا سريعًا على Webpack يمكن لسائل أن يسأل ماذا لو أنني تعلمت العمل على Webpack وبعدها ظهرت أداة جديدة أفضل منها أو تغطي مجال أوسع في العمل؟ أليس ذلك هدرًا لوقتي ولجهدي؟ صراحة، الشيء الوحيد الّذي استطيع تأكيده لك هو أن عجلة التحديث في مجال الواجهات الأمامية سريع الدوران، وما إن تظهر مشكلة ما حتى يتسارع المطورون لحلها فمن الممكن أن تظهر أداة أقوى منها (وهذا لا اتوقعه أن يحدث قريبًا وخصيصًا مع الدعم الكبير الّتي تشهده هذه الأداة من الشركات العملاقة مثل فيسبوك) هذا وارد الحدوث، ولكن هذا الأمر لا يُلغي فكرة أهمية تعلمك العمل مع هذه الأداة إذ أن معظم الأدوات الّتي تظهر لحل مشكلة معينة تكون متشابهة في البنية وطريقة العمل مع بعض الإختلافات. أي إن تعلمك العمل مع هذه الأداة سيجهزك للعمل مع الأدوات الأخرى المستقبلية. ومن يعلم ربما تكون أنت صاحب فكرة الأداة الجديدة الّتي ستتفوق على Webpack! والسؤال الأخر الّذي من الممكن يخطر في أذهاننا أيضًا هل تستحق هذه الأداة الوقت المبذول لتعلمها؟ أو بتعبير أخر هل النتائج الّتي سأجنيها من استخدام هذه الأداة ستغطي على الوقت المبذول لتعلمها؟ في الحقيقة لا أبالغ أن قُلت أنه من الواجب عليك تعلمها فورًا وبدون تردد وخصيصًا إن كُنت تتخذُ من مهنة تطوير الواجهات الأمامية (أو مطور برمجيات عمومًا) مصدرًا أساسيًا للدخل في حياتك! لأنها ستعزز كثيرًا من إنتاجيتك وسرعتك وجودة العمل المُسلّم وهذا ما ستشعر به من أول شهر من استخدامك لها. في الحقيقة إن مجيئ Webpack بكل هذه المميزات وقابلية التخصيص والإمكانيات أطاح بجميع المنافسين لديها مثل Browserify، ليس ذلك فحسب بل تخطّت إمكانياتها حدود الفكرة التي أُنشأت من أجلها لتهدد أدواتٍ مساعدةٍ أخرى كأدوات البناء مثل Gulp (والتي تحدثنا عنها في مقالٍ سابق) إذ أنه يمكننا من خلال NPM Script أن نعوّض عمل Gulp ولكن هذا سيكون على حساب الصعوبة إذ أن العمل مع Webpack ليس بسهولة العمل مع Gulp. ننصحك بالانتقال بعد الانتهاء من هذا المقال إلى مقال، أيهما أفضل كأداة مساعدة Webpack أم Browserify مع Gulp؟ الذي يشرح الفروقات بين كل هذه الأدوات وحالات استخدامها وغيرها من التفاصيل المفيدة. بالإضافة إلى ذلك وفرت لنا Webpack إمكانية التكامل مع أدوات مساعدة أُخرى مثل أداة السقالة Yeoman (والتي تحدثنا عنها في مقالٍ سابق) وبذلك نحصل على فوائد كِلتا الأداتين ونختصر وقتنا اختصارًا ملحوظًا. وبذلك يمكننا القول بأن المرونة الموجودة لدى Webpack وملحقاتها الرائعة والدعم المتميز من مجتمعها ومستخدميها جعلها من أقوى الخيارات الموجودة في الساحة حاليًا. الخاتمة بدأنا هذا الدليل ونحن لا نعرف شيئًا عن Webpack، ثم حفرنا عميقًا في تاريخها لنفهم تمامًا ما هي الأسباب الّتي أدت لظهور أداةٍ قوية كهذه الأداة، ثم بدأنا بتجهز المتطلبات اللازمة لتشغيلها، وفصلّنا في جميع المفاهيم الأساسية لها، وتعلمنا كيفية استخدامها في إدارة ملفات التنسيق والصور والخطوط ، وكيفية استخدامها لضغط الصور قبل رفعها وتعلمنا طريقة استخدامها لتحويل الشيفرة البرمجية من إصدار حديث إلى إصدار أقدم منه. وأخيرًا ناقشنا أهمية تعلمها وفوائده. وختامًا إن هذا الدليل لم يغطي كافة المميزات والجوانب الموجودة في أداة Webpack وإنما فقط أردنا من هذا الدليل أن يلفت نظرك لأهمية هذه الأداة وقدراتها المتميزة في مساعدتك في العمل على المشاريع وخصوصًا الكبيرة منها. بل وجعلها يدك اليمنى في أي مشروع جديد وبالتأكيد إن كلّ هذه المعلومات لن تُشبع فضول المطوّر المحترف ولذلك يمكنك دومًا الاطلاع على التوثيق الرسمي للأداة لمزيد من المعلومات. المصادر التوثيق الرسمي لأداة Webpack. التوثيق الرسمي لمدير الحزم npm. المقال Using Imagemin with webpack لصاحبته Katie Hempenius. المقال How to configure SCSS modules for Webpack لصاحبه Jon Preece. المقال Brief history of JavaScript Modules لصاحبه SungTheCoder.1 نقطة