اذهب إلى المحتوى

سامح أشرف

الأعضاء
  • المساهمات

    2934
  • تاريخ الانضمام

  • تاريخ آخر زيارة

  • عدد الأيام التي تصدر بها

    56

كل منشورات العضو سامح أشرف

  1. سأحاول شرح كيفية البحث داخل أي نص بإستخدام Python وعليك أن تقوم بتحويل الكود إلى اللغة التي تستعملها بنفسك. في البداية نحتاج إلى عمل دالة تأخذ النص المراد البحث فيه (النص الكامل)، وكلمة نريد البحث عنها في النص وليكن اسمها keyword: def search(text, keyword): # باقي الكود سيكون هنا الآن نحتاج إلى أن نقوم بالبحث عن الكلمة في النص، وتوجد عدة طرق للقيام بهذا الأمر، أسهل طريقة للقيام بهذا الأمر هو إستخدام المعامل in : def search(text, keyword): if keyword in text: return "keyword was found" else: return "can't find the keyword" ويمكننا أن نستخدمها بهذه الطريقة: >>> search("some text here!!", "text") 'keyword was found' >>> search("some text here!!", "hello") "can't find the keyword" >>>
  2. إن كنت تقصد Office 365، فإن شركة مايكروسوفت (الشركة المالكة لـ Office 365) لا توفر تخفيضات في الوقت الحالي، وتبدأ أسعار الحزم من 5$ شهريًا (بدون الضرائب)، وبفضل دائمًا أن تشتري البرامج من الشركة الأم بدلًا من محاولة الحصول على الخدمات من خلال مواقع أخرى حيث قد يعرضك هذا الأمر لخطر الوقوع كضحية لعملية إحتيال. إن كان لديك بريد إلكتروني جامعي فيمكنك الحصول على الحزمة Office 365 A1 التي توفر العديد من برامج Office 365 مثل Microsoft Word و Microsoft Excel و Microsoft PowerPoint وغيرها من الخدمات بشكل مجاني بالكامل، إن كنت طالب وليس لديك بريد إلكتروني فيمكنك التواصل مع مركز الخدمات التقينة في جامعتك/كليتك للحصول عليه، أيضًا سوف تحصل على تخفيض كبير إن أردت الحصول على حزمة مختلفة عن Office 365 A1. يمكنك أن تقرأ كل المعلومات المتوفرة عن خطط الأسعار المتاحة للطلبة من هذه الصفحة. إن لم تكن طالب أو لم تتمكن من الحصول على بريد إلكتروني جامعي فيمكنك ان تقوم بتجربة أي حزمة من حزم Office 365 بشكل مجاني لمدة شهر واحد فقط.
  3. يمكنك حل هذه المشكلة من خلال إنشاء كائن Response (عبر الدالة make_response) وتحديد الترويسة Content-Type لتكون من نوع الصورة مثل image/jpeg ، وإن أردت أن يتم تحميل الصورة وحفظها بدلًا من عرضها على الشاشة فيجب أن تقوم بتحديد التوريسة Content-Disposition لتحمل القيمة attachment، على النحو التالي: @app.route('/images/<image_id>.jpg') def load_image(image_id): image_binary = read_image(image_id) # يتم هنا جلب الصور في شكل bson.Binary response = make_response(image_binary) response.headers.set('Content-Type', 'image/jpeg') # لتحميل الصورة وحفظها بدلًا من عرضها response.headers.set('Content-Disposition', 'attachment', filename='%s.jpg' % image_id) return response يمكنك أيضًا أن تستعمل الدالة send_file لإرسال كائن من نوع io.BytesIO: from flask import Flask, send_file @app.route("/images/<image_id>.jpg") def load_image(image_id): image_binary = read_image(image_id) # يتم هنا جلب الصور في شكل bson.Binary return send_file( io.BytesIO(image_binary), mimetype='image/jpeg', as_attachment=True, attachment_filename='%s.jpg' % image_id ) تستطيع أيضًا حفظ الصورة في ملف مؤقت على الخادم وإرسال هذا الملف بشكل عادي، والتحقق من وجود الملف أولًا لكي لا يتم إعادة حفظ نفس الصورة في كل مرة يتم طلبها.
  4. يتم عمل مثل هذه الفيديوهات عبر برامج مثل Adobe Illustrator لرسم الصور والكائنات وتلوينها وبرنامج Adobe After Effects لتحريك هذه الرسومات حسب الحاجة وإضافة بعض التأثيرات والإنتقالات .. إلخ، يمكنك التأكد من هذا الأمر من خلال زيارة صفحة about الخاصة بالقناة على اليوتيوب. بالتأكيد يمكن إستخدام برامج أخرى للقيام بهذا الأمر ولكن في الغالب يتم إستخدام برامج Adobe للقيام بعمل فيديوهات Motion Graphics. تستطيع الإطلاع على هذه الإجابات هنا للحصول على عدد من المصادر لتعلم الـ Motion Graphics: أيضًا تحتوي أكاديمية حسوب على عدد كبير من المقالات في برنامج Adobe Illustrator ومقالات في التصميم الجرافيكي بشكل عام.
  5. فلاسك عبارة عن إطار عمل للويب بلغة بايثون، ويمكنك أن تقوم بقراءة ملفات JSON بشكل عادي كما تقوم بها بلغة بايثون، هنا مثال لكيفية قراءة ملف JSON : with open('db.json', 'r', encoding='utf-8') as f: content = f.read() json_data = json.loads(content) print(json_data) كما يمكن إستخدام هذه الطريقة في تطبيق مبني بإستخدام فلاسك Flask كالتالي: from flask import Flask, jsonify import json app = Flask(__name__) @app.route('/', methods=['POST', 'GET']) def index(): with open('db.json', 'r', encoding='utf-8') as f: content = f.read() json_data = json.loads(content) # قراءة ملف json return jsonify(json_data) # إرسال كود json if __name__ == '__main__': app.run(debug=True) لحفظ كود JSON إلى ملف يمكنك أن تقوم بنفس الشيء، على النحو التالي: json_data = {'posts': [{'id': 1, 'title': 'json-server'}, {'id': 2, 'title': 'post 2'}]} content = json.dumps(json_data) # تحويل الكائن إلى كود JSON على شكل نص with open('db.json', 'w', encoding='utf-8') as f: f.write(content)
  6. يمكنك أن تقوم بتوليد secret key بأكثر من طريقة في Python: بإستخدام مكتبة os (لبايثون 3): >>> import os >>> os.urandom(12).hex() 'f3cfe9ed8fae309f02079dbf' بإستخدام مكتبة uuid (لبايثون 2 و 3): >>> import uuid >>> uuid.uuid4().hex '93ec461e09494cc782777a2d72849347' بإستخدام مكتبة secrets (لبايثون 3.6 أو أعلى): >>> import secrets >>> secrets.token_urlsafe(16) 'ZUhfGOVy7hC8Zvljx73jkQ' >>> secrets.token_hex(16) 'be193b8219c908baa36c17a64b58d39d' ويمكنك أن تضيف المفتاح بإستخدام أحد الطرق التالية: app.secret_key = 'the random string' app.config['SECRET_KEY'] = 'the random string' أو تضيف المفتاح إلى ملف الإعدادات، بالشكل التالي: SECRET_KEY = 'the random string'
  7. بشكل إفتراضي جلسات فلاسك Flask Session يتم إنهائها بمجرد إغلاق المتصفح، إلا في حالة واحدة وهو جعل الجسلة دائمة permanent session وتحديد وقت معين لإنتائها كالتالي: from datetime import timedelta from flask import session, app @app.before_request def make_session_permanent(): session.permanent = True app.permanent_session_lifetime = timedelta(minutes=15) بهذا الشكل سوف تستمر الجلسة حتى وإن قام المستخدم بإعادة تشغيل المتصفح الخاص به، وسوف تنتهي الجلسة بعد مرور 15 دقيقة من وقت تسجيل الدخول. ملاحظة: إن لم يتم تحديد مدة حياة الجلسة permanent_session_lifetime فسوف تستمر لشهر كامل، بالتحديد لـ 31 يوم.
  8. يمكنك القيام بهذا الأمر من خلال تعليمة include في قوالب Jinja على النحو التالي: الملف index.html <!DOCTYPE html> <html lang="en"> <body> <h1>Index Content</h1> {% include 'footer.html' %} </body> </html> محتوى الملف footer.html: <h1>{{ name }}</h1> طريقة عرض الملف index.html: def index(): return render_template('index.html', name="sameh") # لاحظ تم تمرير المعامل name لأن الملف footer.html يحتاجه بهذا الشكل سوف يتم جلب محتوى الملف footer.html إلى داخل الملف index.html، أي تم إستدعائه، وستكون النتيجة في النهاية كالتالي: <!DOCTYPE html> <html lang="en"> <body> <h1>Content</h1> <h1>sameh</h1> </body> </html> ملاحظة: كل المتغيرات والبيانات الممررة إلى الملف index.html سوف يتم تمريرها إلى الملف footer.html أيضًا، لذلك عليك تمرير كل المتغيرات التي يحتاجها الملف footer.html إلى الملف index.html عند إستخدام الدالة render_template
  9. يمكن القيام بهذا الأمر من خلال تغير مسار المجلد static الإفتراضي حتي يمكنك الوصول إلى محتويات المجلد المباشرة من خلال كتابة اسم الملف بعد النطاق domain مباشرة، ويتم هذا الأمر من خلال الخاصية static_url_path، حيث يتم إستخدام نص فارغ للتعبير عن المسار الرئيسي للمجلد: from flask import Flask app = Flask(__name__, static_folder='static', static_url_path='') يمكنك أيضًا أن تقوةم بعمل مسارات مخصصة لهذه الملفات، ثم إرسال محتوى هذه الملفات من خلال الدالة send_from_directory : from flask import Flask, request, send_from_directory app = Flask(__name__, static_folder='static') @app.route('/robots.txt') @app.route('/sitemap.xml') def static_from_root(): return send_from_directory(app.static_folder, request.path[1:]) بهذا الشكل يمكنك أن تصل إلى الملفات من خلال العناوين: https://www.example.com/robots.txt https://www.example.com/sitemap.xml
  10. توفر قوالب Jinja إمكانية عرض أي نصوص من خلال إستخدام من خلال ما يسمى بـ Escaping وذلك عبر إستخدام العنصر {% raw %} و {% endraw %} على النحو التالي: {% raw %} <ul> {% for item in seq %} <li>{{ item }}</li> {% endfor %} </ul> {% endraw %} بهذا الشكل سوف يتم عرض النص بنفس طريقة كتابته، ولن يتم ترجمة الكود من قِبل Jinja ملاحظة: لا يمكن أن يحتوي النص نفسه على الوسم {% endraw %} وذلك لأنه سيتم إعتباره نهاية الوسم {% raw %} بالتأكيد، لذلك يمكنك أن تقوم بإستخدام HTML Entities: &lbrace; { &percnt; % &rbrace; }
  11. لقد تم نشر المشروع في معرض أعمالك بدون مشكلة، ولكن يبدو أن المشروع نفسه يحتوي على خطأ أثناء رفعه، لذلك لا تظهر كل الصور بشكل سليم. عليك التحقق من المشروع قبل رفعه جديد، ثم إعادة رفعه إلى إستضافة أو إلى GitHub مرة أخرى.
  12. يمكن القيام بهذا الأمر من خلال إستخدام الصنف BaseConverter (المتوفر في werkzeug.routing) للقيام بإنشاء محول converter باسم regex على سبيل المثال، على النحو التالي: from werkzeug.routing import BaseConverter class RegexConverter(BaseConverter): def __init__(self, url_map, *items): super(RegexConverter, self).__init__(url_map) self.regex = items[0] app.url_map.converters['regex'] = RegexConverter ويمكنك أن تستخدمه بالشكل التالي: from flask import Flask, render_template from werkzeug.routing import BaseConverter app = Flask(__name__) class RegexConverter(BaseConverter): def __init__(self, url_map, *items): super(RegexConverter, self).__init__(url_map) self.regex = items[0] app.url_map.converters['regex'] = RegexConverter @app.route('/<regex("[a-zA-Z0-9]{2,5}"):uid>/', methods=['POST', 'GET']) def index(uid): return uid if __name__ == '__main__': app.run(debug=True) ستلاحظ أن كل المسارات التالية تعمل لأنها تحقق الشروط: http://127.0.0.1:5000/hi/ http://127.0.0.1:5000/12/ http://127.0.0.1:5000/123/ http://127.0.0.1:5000/hi123/ ... بينما المسارات التالية لن تعمل على الإطلاق: http://127.0.0.1:5000/ http://127.0.0.1:5000/a/ http://127.0.0.1:5000/%D9/ http://127.0.0.1:5000/hello-world/ http://127.0.0.1:5000/helloworld/ ... يمكنك أن تقرأ أكثر حول التعابير النمطية في هذه المقالة:
  13. يمكنك أن تستخدم أي خدمة إستضافة لرفع ملفات المشروع النهائية (في الغالب تكون في المجلد dist أو public)، وسوف تحصل على رابط لمشاركة المشروع مع الآخرين، أيضًَا يمكنك أن تستخدم GitHub لنشر الكود الخاص بالمشاريع وبالتالي يمكن للآخرين قراءة الكود الخاص بك ومعرفة مستواك في حل المشاكل وكتابة الأكواد والبرمجة بشكل عام، وحينها يمكنك أن تستخدم حسابك على GitHub كمعرض أعمال. تستطيع أيضًا أن تستخدم أحد مواقع العمل الحر مثل مستقل كمعرض أعمال، حيث يوفر لك الموقع إمكانية إضافة أعمالك في شكل صور ونص يشرح المشروع وإضافة رابط أيضًا لتصفح المشروع بشكل حي.
  14. يمكنك القيام بهذا الأمر بطريقتين، الأولى عبر إستعمال JavaScript للحصول على البيانات من عنصر input وإرسالها في طلب إلى فلاسك Flask ليتم إستخدام هذه البيانات في عمل أي مهمة ثم إرجاع نتيحة معينة إلى صفحة الويب، أما الطريقة الثانية وهي الأسهل، حيث يتم إستخدام نموذج form لإرسال البيانات بطريقة POST إلى فلاسك Flask ثم يقوم بتنفيذ بعض المهام بإستخدام هذا النص ويرجع البيانات، كالتالي: في البداية تحتاج إلى تجهيز مسار route في فلاسك يستقبل هذه البيانات ويرجع قيمة معينة: @app.route('/process', methods=['POST']) def upper_text(): text = request.form['text'] processed_text = text.upper() return processed_text ومسار route آخر لعرض النموذج form: @app.route('/') def form(): return render_template('form.html') وسيحتوي الملف templates/form.html على نموذج واحد كالتالي: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Upper Text</title> </head> <body> <form method="POST" action="/process"> <input name="text"> <input type="submit"> </form> </body> </html> بهذا الشكل سوف يتم الحصول على البيانات من النموذج form ثم سيتم تحويلها إلى أحرف كبيرة (يمكنك القيام بأي شيء في الدالة upper_text) ثم يتم إرجاع البيانات إلى المتصفح مرة أخرى. يمكنك أيضًا أن تستعمل قالب ليعرض البيانات المرجعة بدلًا من عرضها في شكل نصي فقط.
  15. يستخدم فلاسك Flask مكتبة logging لعرض الرسائل في الـ console ويمكنك أن تعدل على هذا الأمر وتجعله يعرض رسائل الخطأ فقط من خلال إضافة الكود التالي: import logging log = logging.getLogger('werkzeug') log.setLevel(logging.ERROR) بهذا الشكل لن يتم عرض أي رسائل إلا رسائل الخطأ فقط. هنا مثال لكيفية إستخدام هذا الكود في تطبيق فلاسك: from flask import Flask, request, render_template import logging app = Flask(__name__) # Stop logger log = logging.getLogger('werkzeug') log.setLevel(logging.ERROR) @app.route('/', methods=['POST', 'GET']) def index(): return render_template('home.html') if __name__ == '__main__': app.run(debug=True)
  16. ليس من الضروري أن تقوم بعمل مشروع بمفردك، ولكن قيامك بعمل مشروع كامل بإستخدام ما تعلمته سوف يفيدك للغاية لأنك ستعرف الأجزاء التي تعلمها جيدًا والأجزاء التي قد تحتاج أن تراجعها، وبالتأكيد تستطيع أن تضيف هذا المشروع (حتى وإن كان مشروع صغير أو بسيط) إلى معرض أعمالك فيما بعد، وسيكون طريقة جيدة لتعرف لاحقًا مدى التقدم الذي تحرزة مع مرور الوقت. أما إن لم ترغب في عمل مشروع جديد من الصفر وترى أنك تعلمت كل محتوى المسار فلا توجد مشكلة أيضًا ويمكنك الإنتقال إلى المسار التالي. بعد إنهاء المسارات وإتمام كل المشاريع، ستحتاج إلى خوض إمتحان يحدده لك المدرب، وسيكون مشروع مرتبط بما تعملته، ويجب إنهائه في فترة من أسبوع إلى أسبوعين، لذلك يمكنك أن تقوم بعمل مشروع وحدك قبل خوض الإمتحان للتأكد من أن أتممت كل المسارات بشكل سليم قبل خوض الإمتحان، ويمكنك أيضًا أن تبدأ في الامتحان مباشرة إن كنت متأكدًا من معلوماتك. من ضمن الأشياء التي تحدد مستواك بالنسبة للشركات هو معرض أعمال، فكلما كانت أعمالك مميزة كلما زادت فرصتك في الحصول على وظيفة في أحد الشركات، وستحصل على معلومات مفيدة من متخصصين في كيفية تجهيز سيرتك الشخصية وملفك الشخصي على مواقع العمل الحر من متخصصين بعد الإنتهاء من الامتحان. يمكنك معرفة المزيد عن الامتحان من مركز المساعدة من هنا
  17. ما تحاول القيام به هو إرجاع رد برقم 204 ، حيث يعبر رقم الحالة 204 عن عدم وجود محتوى No Content، وللقيام بإرجاع رد برقم 204 يمكنك إستخدام الكود التالي: @app.route('/', methods=['POST', 'GET']) def index(): return ('', 204) أيضًا يمكنك أن تستعمل قيمة الخاصية NO_CONTENT كالتالي: import http @app.route('/', methods=['POST', 'GET']) def index(): return ('', http.HTTPStatus.NO_CONTENT) إن كنت تستعمل Python 2 فستحتاج إلى إستعمال الخاصية NO_CONTENT من المكتبة httplib: return ('', httplib.NO_CONTENT) لمزيد من المعلومات عن رموز الإجابة في HTTP: ويمكنك الإطلاع أيضًا على هذه الإجابة لمزيد من رموز الإجابة مع شرحها:
  18. فلاسك Flask يقوم بتخزين مسار المجلد static في الخاصية static_url_path الموجودة في الكائن app.config ويمكن تغيرها إلى أي قيمة أخرى: from flask import Flask, render_template app = Flask(__name__) app.config.static_url_path = "/assets" @app.route('/', methods=['POST', 'GET']) def index(): return render_template("home.html") if __name__ == '__main__': app.run(debug=True) لكن لاحظ أنك إن قمت بتغير المسار إلى مسار آخر يستخدمه فلاسك بالفعل فلن يعمل، فعلى سبيل المثال لا يمكنك أن تقوم بإستخدام المجلد templates بدلًا من statics لأن فلاسك Flask سوف يقوم بإستخدام المجلد للقوالب وليس للملفات الثابتة static. ملاحظة: يمكنك إستخدام الخاصية static_url_path من داخل app مباشرة بدون الوصول إلى config: app = Flask(__name__) app.static_url_path = "/assets"
  19. الـ user agent عبارة عن ترويسة header يتم إرسالها مع كل طلب، لذلك يمكنك الحصول عليه من خلال القاموس headers المتوفر في الكائن request: from flask import request, render_template app = Flask(__name__) @app.route('/', methods=['POST', 'GET']) def index(): print(request.headers.get('User-Agent')) return render_template("home.html") if __name__ == '__main__': app.run(debug=True) وإن كنت تستعمل الإصدار 2.0 أو أقل من Werkzeug فيمكنك أن تستخدم user_agent الموجود في الكائن request والذي يوفر لك مجموعة من الخصائص مثل الحصول على نظام التشغيل أو نوع المتصفح .. إلخ: @app.route('/', methods=['POST', 'GET']) def index(): print(request.user_agent.string) # Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.57 print(request.user_agent.platform) # windows print(request.user_agent.browser) # chrome print(request.user_agent.version) # 96.0.4664.110 print(request.user_agent.language) # None return render_template("home.html")
  20. هل يمكنك التأكد من أن الصورة موجودة بجانب ملف html، لأن هذا الخطأ يعني أنه لم يتم العثور على الصورة، أما بسبب أنها موجودة في مجلد مختلف أو أنها تحمل اسم مختلف
  21. يمكنك أن تستعمل ميزة blueprint التي يوفرها فلاسك Flask بشكل إفتراضي، حيث تقوم بإضافة كل المسارات إلى blueprint وتضيق نص مسبق إلى هذا المخطط blueprint، على النحو التالي: bp = Blueprint('api', __name__, template_folder='templates') @bp.route("/") def index(): return "Home page" @bp.route("/about") def about(): return "abour us page" بعد ذلك عليك أن تضيف هذا المخطط إلى التطبيق من خلال الكود التالي: app = Flask(__name__) app.register_blueprint(bp, url_prefix='/api/v1')
  22. هل يمكنكِ إعادة تسيمة الصورة لأي نص بسيط مثل img.jpg وإضافتها في الكود بالاسم الجديد، وكذلك يجب التأكد من حفظ الملفات وتحديث الصفحة في المتصفح. أيضًا قد يظهر خطأ في الـ console ويمكن عرض هذا الخطأ من خلال الضغط على F12 والذهاب إلى تبويب Console كما في الصورة:
  23. يوجد خطأ في كتابة مسار الصورة، حيث أن الصورة موجودة بجانب ملف html في المجلد "my photo" ولكن المسار المستخدم خاطيء، هنا المسار الصحيح: <img src="./IMG_0832 2.JPG" alt=""/> كما أرجو التأكد من اسم الصورة الصحيح، هل يبدأ الاسم بمسافة أم لا؟
  24. يمكنك القيام بهذا الأمر من خلال إستخدام التابع BackgroundScheduler الموجود في الحزمة APScheduler والتي تسمح لك بتنفيذ دالة معينة كل فترة من الزمن مثل ما يقوم به corn بالضبط. أولًا عليك تثبيت الحزمة من خلال الأمر التالي: pip install APScheduler ثم يمكنك أن تقوم بإستخدامها على النحو التالي: import time import atexit from flask import Flask, request, render_template from apscheduler.schedulers.background import BackgroundScheduler app = Flask(__name__) scheduler = BackgroundScheduler() def date_time(): print("Working at: ", time.strftime("%A, %d. %B %Y %I:%M:%S %p")) @app.route('/', methods=['POST', 'GET']) def index(): scheduler.add_job(func=date_time, trigger="interval", seconds=3600) scheduler.start() return render_template("home.html") if __name__ == '__main__': app.run(debug=True) كما يمكنك أن تقوم بإيقاف كل العمليات التي تعمل في الخلفية من خلال إستخدام التابع register: atexit.register(lambda: scheduler.shutdown()) ويمكنك أن تضيف الكود السابق في مسار مختلف ليتم إيقاف العمليات عند زيارته: @app.route('/shutdown') def shutdown(): atexit.register(lambda: scheduler.shutdown()) return "closed"
  25. كلًا من NPM و PNPM يقوم بإدارة وتحميل الحزم الخاصة بـ Node.js ولكن بطرق مختلفة، فبداية من الإصدار 3 في NPM أصبح يتم تحميل الحزم وتخزينها في مجلد node_modules على شكل flattened dependency tree أي أن كل حزمة يكون لها مجلد خاص بها منفصل عن باقي الحزم بالكامل، وبالتالي يمكن لأكثر من مكتبة أن تستعمل نفس الحزمة بدون الحاجة لتحميل الحزمة مرتين (مرة لكل مكتبة) في المشروع الواحد، وبالتالي هذا الأمر يوفر في المساحة المستخدمه لتخزين الحزم والمكتبات في المشروع، ولكن بالنسبة لمشروع آخر فيجب أن يتم تحميل الحزم مرة أخرى وتخزينها في مجلد node_modules جديد خاص بالمشروع الثاني، وهذا الأمر يسبب في بطء عملية تحميل وتثبيت الحزم وخصوصًا إن كنت تعمل على مشاريع متعددة. على الجانب الآخر يستعمل PNPM طريقة مختلفة لتثبيت الحزم، حيث يتم تثبيت الحزم والمكتبات في مكان عام (على القرص C على سبيل المثال) ثم يتم عمل إختصار (hard linking and symbolic linking) لمجلد الحزمة في مجلد node_modules الخاص بالمشروع، وبالتالي لا يتم تحميل وتثبيت الحزمة إلا مرة واحدة ثم يتم إستعمالها في كل المشاريع المختلفة بدون مشكلة. هنا مثال لكيف سيبدو مجلد node_modules في حالة تم إستعمال PNPM، حيث ستجد أن المجلد الخاص بكل حزمة يشير إلى مجلد بنفس الاسم ولكن في مكان مختلف (داخل مجلد التثبيت العام والذي يشار إليه في الشكل التالي بـ <store>): node_modules └── .pnpm ├── bar@1.0.0 │ └── node_modules │ └── bar -> <store>/bar │ ├── index.js │ └── package.json └── foo@1.0.0 └── node_modules └── foo -> <store>/foo ├── index.js └── package.json يمكنك تثبيت PNPM من خلال الأمر التالي: npm install -g pnpm ويمكنك أن تستخدمه لتثبيت الحزم أو حذفها أو تحديثها من خلال الأوامر: pnpm add <pkg> pnpm remove <pkg> pnpm up <pkg>
×
×
  • أضف...