تجربتنا في إضافة تشغيل الحافة إلى Next.js SDK
يدعم Logto's Next.js SDK الآن تشغيل الحافة. في هذه المقالة، سنشارك مغامرتنا ونتحدث عن العقبات التي واجهناها، وكيف تغلبنا عليها، والأشياء الرائعة التي تعلمناها على طول الطريق.
المقدمة
أصبح تشغيل الحافة كلمة رنانة في عالم التكنولوجيا، حيث يساهم في تشغيل الوظائف الديناميكية وقليلة الانتظار في المنصات من AWS Lambda@Edge وCloudflare Workers إلى Vercel Edge. في دلالة على أهميته، قامت Vercel مؤخرًا بتغيير "experimental-edge" إلى "edge"، مما يشير إلى الدعم الرسمي في إطار العمل الشهير Next.js. مع زيادة شعبية Next.js SDK الخاص بنا بشكل ملحوظ، فكرنا في Logto، "لماذا لا نضيف دعم تشغيل الحافة؟". لذا، شرعنا في العمل ودخلنا في التحدي. في هذه المقالة، سنشارك مغامرتنا، ونلقي نظرة على العقبات التي واجهناها، وكيف تغلبنا عليها، والأشياء الرائعة التي تعلمناها على طول الطريق.
نقل الوحدات والاعتماديات لدعم تشغيل الحافة
العمل مع تشغيل الحافة يواجه بعض التحديات الفريدة، خاصة لأنه لا يدعم جميع الوحدات والاعتماديات المستخدمة بشكل شائع في Node.js. لقد واجهنا هذه المشكلة مع وحدات crypto، lodash، وiron-session، مما استلزم بعض الحلول الابتكارية.
Crypto
في بيئة Node.js، يعتبر و حدة crypto وسيلة لتغليف وظائف التشفير في OpenSSL. لسوء الحظ، لا يدعمه تشغيل الحافة. لكن لا تقلق - تأتي معظم التشغيلات الحافة لدعم Web Crypto API. على الرغم من بعض الاختلافات البسيطة، إلا أنها تتعتبر بديلاً جيدًا لوحدة crypto. على سبيل المثال، لتوليد بايتات عشوائية:
والتجزئة:
Lodash
تعتبر Lodash مفضلة لدى العديد من المطورين لوظائفها العامة، ولكن تشغيل الحافة ليس معجبًا بها. ما هو الحل الذي اتبعناه؟ لقد استبدلنا وظائف Lodash بطرق JavaScript الأصلية، مع الحفاظ على كفاءة ووضوح الشيفرة. على الرغم من أن استبدال معظم وظائف Lodash لم يكن مهمة شاقة، إلا أنه تطلب بعض الدقة. دعونا نلقي نظرة على كيف أعدنا خلق وظيفة "once" بطريقتنا الخاصة:
Iron Session
إن الإصدار الأحدث من وحدة iron-session مناسبة لتشغيل الحافة، لذلك كل ما كان علينا فعله هو تحديث الإصدار لدينا. بكل بساطة!
التنقل في التعقيدات "الاستجابة" في تشغيل الحافة
تحدي آخر واجهناه عند تعديل SDK الخاص بنا لتشغيل الحافة كان التعامل مع الفروقات في كائن "الاستجابة". إليك كيف تغلبنا على هذه الفروقات:
إنشاء استجابة يدويًا
على عكس Node.js، الطلبات في تشغيل الحافة لا تأتي مع استجابة مشتركة. يعني ذلك أننا يجب أن نقوم بإنشائها عن طريق استدعاء new Response()
، وهنا مثال على كيفية إعادة البيانات:
التخلي عن "withIronSessionApiRoute"
في تشغيل الحافة، Response.body
يعتبر قراءة فقط. يعني ذلك أننا لم نتمكن من تهيئة استجابة قبل إعداد البيانات. نتيجة لذلك، كان علينا وضع الموثوق به "withIronSessionApiRoute" (جنبًا إلى جنب مع وسائط أخرى).
لفهم ما استبدلنا، لنقم أولاً بفكفكة ما يقوم به withIronSessionApiRoute
بالفعل:
- يأخذ نظرة على الكوكي، يقوم بإنشاء كائن جلسة، ويربطه بـ
res
. - يضيف تلقائيًا رأس "set-cookie" إلى
res
إذا كان هناك تغيير في الجلسة.
إذًا، كيف قمنا بمحاكاة هذه الوظيفة في بيئتنا الجديدة لتشغيل الحافة؟
- القراءة: استغللنا وظيفة
getIronSession
الموجودة. عن طريق إعطائهاresponse
فارغة ووهمية، تستعيد الجلسة عند الحاجة. استبدل هذا طريقة "get" منreq.session
. - الكتابة: أعددنا
response
بالبيانات مسبقًا، ثم استخدمناgetIronSession
على هذه النسخة منresponse
للحصول على كائن الجلسة. بمجرد أن أصبح هذا الكائن في أيدينا، تمكنا من تعديل الجلسة حسب الحاجة.
التوجيه
التوجيه في تشغيل الحافة يحتاج منا لإضافة يدويًا رأس Location
إلى استجاباتنا.
حزمة واحدة، تشغيلان
في رحلتنا، قررنا الالتزام بحزمة واحدة لدعم تشغيل الحافة و Node.js على حد سواء.
لماذا؟
فكرنا في إنشاء حزمة منفصلة لتشغيل الحافة، لكن أدركنا سريعًا أنه لم يكن ضروريًا. معظم الشيفرة الخاصة بنا كانت مشتركة بين التشغيلين، مع الحاجة فقط لبعض الخطوط لتعديلات بسيطة. بالإضافة إلى ذلك، استخدام SDK بقي نفسه عبر كلا التشغيلين، لذلك كان الحفاظ على حزمة موحدة أكثر منطقية.
ماذا فعلنا؟
بدلاً من تكرار الجهود، قررنا توسيع الحزمة الحالية. أضفنا مجلد "edge" بجوار مجلد "src" القديم داخل الجذر في الحزمة. ثم قمنا بتحديث ملف package.json، مضيفين مسارًا جديدًا إلى "التصديرات". بهذه الطريقة، يمكن لكل من تشغيل الحافة و Node.js العيش بتناغم داخل نفس الحزمة، مع أقل عناء ممكن.
الختام
يمكنك الاطلاع على الكود المصدري الكامل لجزء الحافة من Next.js SDK الخاص بنا هنا.
من خلال مشاركة رحلتنا في تبني تشغيل الحافة، نأمل في إلهام وإرشاد الآخرين الذين يستكشفون مسارات مشابهة. ترقبوا المزيد من التحديثات مع Next.js SDK الخاص بنا.