ما هو Tinkoff Business
تقدم Tinkoff Business حلولًا للشركات الصغيرة والمتوسطة: مشروع راتب ، وخدمات نقدية وتسوية ، ومصمم مستندات وحوالي 20 منتجًا آخر.
كل هذا يتم تنفيذه في التطبيقات. تم تطوير هذه التطبيقات بواسطة فرق منفصلة ولها دورات إصدار خاصة بها. وتعمل كل هذه التطبيقات بترخيص واحد ، وتحتوي على جزء مشترك من منطق الأعمال في مكتبة منفصلة ، وتستخدم مكونات واجهة المستخدم الشائعة.
دعنا نعود قبل عامين
بدا تطبيق Tinkoff Business النموذجي شيئًا كالتالي:
في الأعلى - رأس مع التنقل عبر التطبيق ، وعلى اليمين - شريط جانبي به تنقل المنتج.
في ذلك الوقت ، لم تكن فكرة الواجهة المصغرة شائعة جدًا بعد ، لكننا كنا نتحرك بالفعل في هذا الاتجاه: كان الشريط الجانبي تطبيقًا زاويًا منفصلًا. حمّل التطبيق الرئيسي الشريط الجانبي في إطار iframe ، مما سمح بإطلاق التطبيق بشكل مستقل.
كان لهذا النهج عيوبه: عند التبديل بين المنتجات ، كان عليك الانتظار حتى يتم تحميل صفحة كاملة مع تطبيقين Angular. ونظرًا لأن معظم التطبيقات تستخدم نفس طلبات واجهة برمجة التطبيقات الخلفية ، كان على المستخدمين انتظار إعادة تنفيذها.
فكرة مدير الإطار
لقد عشنا مع مثل هذه البنية حتى ظهرت مهمة عالمية لجميع التطبيقات - إعادة التصميم. ثم ظهرت الفكرة: لماذا لا تقوم بنوع من عكس التحكم وبدلاً من تحميل التطبيقات الشريط الجانبي داخل نفسها ، يقوم الشريط الجانبي بتحميل التطبيقات نفسها؟
هذا جعل من الممكن الحفاظ على مزايا العمارة الحالية والتخلص من المشاكل المذكورة أعلاه (وجلب مشاكل جديدة ، هاها).
النموذج الأولي
في البداية ، أنشأنا نموذجًا أوليًا مع الحد الأدنى من الوظائف المطلوبة لتحميل التطبيقات الأخرى. تم إنشاء مجال منفصل على مقعد الاختبار. تغيرت المسارات في nginx لإحصاءات التطبيق: سابقًا ، تم تحميل احصائيات التطبيقات المقابلة على طول المسارات / sme ، / account ، / الراتب ، إلخ. الآن تم إرسال إحصائيات إدارة الإطارات على طول جميع المسارات ، وتمت إضافة postfix / static إلى المسارات الثابتة للتطبيقات نفسها .
لتوضيح الأمر ، دعنا نلقي نظرة على مثال: تحتاج إلى تحميل تطبيق موجود على مسار / بعض التطبيقات مع بعض المسارات . إذا تركنا التفاصيل جانباً ، فلنرى ما هي العملية التي تحدث عند تحميل / some-app / some-route / :
- يرسل Nginx إحصائيات مدير الإطارات على طول هذا المسار.
- يتم تحميل مدير الإطارات. بناءً على المسار ، يتفهم تحميل بعض التطبيقات .
- يتم إنشاء إطار iframe باستخدام src = '/ some-app / static /' حيث يتم تحميل التطبيق الرئيسي.
في الوقت نفسه ، كانت هناك حاجة لتحسينات كبيرة في التطبيقات نفسها. لذلك ، قمنا بتشكيل رئيس فرع التطبيق وأضفنا التغييرات اللازمة هناك ، وبعد ذلك قمنا برفع نسخ فردية من التطبيقات نفسها مع التغييرات التي تم إجراؤها.
المشاكل الأولى
لذلك قمنا بنقل 4 تطبيقات إلى Frame Manager وتأكدنا من أن الحل يعمل. كان يتعين ترجمة جميع التطبيقات الأخرى. وهنا واجهتنا مشكلة: اتضح أن الحفاظ على الإصدار العادي والإصدار للعمل مع مدير الإطارات أمر مكلف للغاية.
كان علينا تحديث الإصدارات الجديدة من التطبيقات باستمرار لكل تغيير في الإصدار الرئيسي من الإصدارات القديمة ، وحل النزاعات الناشئة ، وتعطل الوظائف الحالية غالبًا ، وتضاعفت تكلفة اختبار الانحدار تقريبًا - كل هذا استغرق وقتًا طويلاً. كان من الواضح أن هناك حاجة إلى حل جديد.
تحسينات
إذا كان بإمكان إصدار واحد من التطبيق العمل مع كل من الشريط الجانبي ومدير الإطارات ، فإن ذلك سيوفر لنا الكثير من المشاكل. دعونا نرى ما يمكن عمله.
بادئ ذي بدء ، تحتاج إلى تحديد ما إذا كان التطبيق يعمل في إدارة الإطارات بطريقة ما. هذا بسيط للغاية: تحتاج إلى مقارنة مراجع window.top و window.self. إذا لم يكونوا متساوين ، فنحن في إطار ، أي في إدارة الإطارات! ولكن ، إذا كانت هناك تطبيقات تفتح في إطار iframe افتراضيًا ، فأنت بحاجة إلى إضافة منطق إضافي. لذلك ، كان لدينا تطبيق عنصر واجهة مستخدم تم فتحه في البداية في إطار وبدأ في افتراض أنه موجود دائمًا في Frame Manager ، وهذا هو سبب تعطله في الوضع القديم.
الآن دعنا نلقي نظرة فاحصة على التغييرات المطلوبة في التطبيقات وكيف يمكنك دعم العمل في وضعين:
- url. iframe, . , - , — . url’ Frame Manager, . .
- . Frame Manager’ . : . . , , , post messages custom events. Frame Manager.
- . , Frame Manager. , Angular .
- . , , TCS, config.js . Frame Manager .
- base href. nginx, base href ( /static/). : , base href , . , , , , base href, .
- تفويض. للحصول على إذن في جميع التطبيقات ، يتم استخدام برنامج نصي منفصل ، مضمن في index.html. في الإصدار الجديد ، تم تضمين هذا البرنامج النصي في إدارة الإطارات ، وستؤدي إعادة استخدامه في التطبيقات إلى حدوث أخطاء. يمكنك تغيير منطق البرنامج النصي بحيث يتم تجاهله إذا تم تحميل التطبيق داخل Frame Manager.
هذه كلها حلول عملية ، لكنها ليست مرنة بما يكفي. تمت إضافة فروع جديدة بمنطق يحتاج أيضًا إلى الصيانة في أماكن مختلفة. بشكل عام ، كل شيء يبدو وكأنه هيكل معقد وغير مستقر نوعًا ما.
إعادة اختراع إطار iframe
ثم جاءت فكرة اختراق عملية تحميل تطبيق index.html قليلاً. بدلاً من تحميل التطبيق في إطار iframe يحدد سمة src ، يمكنك تقديم طلب xhr لـ index.html ، والحصول على الصفحة في شكل نصي ، ومعالجتها ، وتحميلها في إطار iframe. سيعطي هذا تحكمًا كاملاً في التطبيق المحمّل: سيسمح لك بتعريف href الأساسي وإزالة البرامج النصية غير الضرورية وأنماط التصحيح ومتغيرات التجاوز وغير ذلك الكثير!
نعم ، لا يشجع المطورون تصحيح mokey ويعتبر ممارسة سيئة ، ولكن إذا استخدمه فريق Angular في مكتبة zone.js ، فكيف نكون أسوأ؟ قد تكون هناك شكوك حول الأداء: يبدو أن تحليل html عملية مكلفة. ولكن ، كقاعدة عامة ، لا تتجاوز صفحة البداية لتطبيق Angular 50 سطرًا ، وفي جميع المتصفحات (حتى IE 10!) هناك واجهة برمجة تطبيقات ملائمةDOMParser ، الذي يسمح لك بالحصول على DOM من سلسلة.
دعنا نلقي نظرة على ما يفعله مدير الإطارات أثناء تحميل التطبيق (تم تحميل مدير الإطارات نفسه بالفعل):
- استنادًا إلى المسار ، يتم تحميل index.html للتطبيق.
- يوزع الصفحة ، ويحولها إلى DOM ، ويزيل البرامج النصية غير الضرورية في الذاكرة ، ويستبدل المتغيرات الأساسية href ، والمتغيرات العامة بالتكوينات والأنماط.
- ينشئ عنصر iframe يكتب المستند الناتج (محوّلًا إلى سلسلة) باستخدام document.write ().
- يضع التطبيق طريقًا يجب أن يكون سلكيًا إليه. كما أنه يغذي النماذج الضرورية لمنطق الأعمال للعمل من خلال خدمة تبادل البيانات.
وبالتالي ، من بين التغييرات الستة الضرورية المذكورة أعلاه في المنطق ، يلزم تنفيذ التغيير الأول فقط (مزامنة عنوان url) داخل التطبيق ، ويتولى مدير الإطارات الباقي!
ما حصل
تم تغيير مظهر التطبيق تمامًا ، عمليًا دون إجراء أي تغييرات على كود التطبيق نفسه.
قبل. الشريط الجانبي محاط بدائرة باللون الأحمر. مضمن في إطار iframe
بعد. يتم تمييز "مدير الإطارات" باللون الأحمر. تم تحميل التطبيق في إطار iframe
حصلت على القدرة على تجاوز أو إضافة المتغيرات والأنماط العالمية.
على سبيل المثال ، هذا هو شكل تكوين النمط للتطبيق
export const business = {
'sidebar.b-main__sidebar': {
display: 'none'
},
'.b-main': {
'margin-left': '260',
position: 'relative',
display: 'block',
width: '1104px',
'min-height': '100vh',
margin: '0 auto'
}
};
وهكذا - تكوين التطبيق نفسه
{
id: 'products',
name: ' ',
icon: 'products',
frameSupported: true,
applications: [
{
id: 'products',
path: '/products',
apiPrefix: '/products',
hasMenuConfig: true,
dynamicCompanyChange: true,
}
]
}
في الوقت نفسه ، تكون التكوينات في مستودع ، منفصلة عن Frame Manager ، مما يسمح لك بتغيير بعض معلمات عمل التطبيق دون تحريرها.
لقد أنشأنا أيضًا انتقالات سلسة بين التطبيقات ، وأذننا في إدارة الإطارات. لقد حققنا أنه نظرًا لمشاركة البيانات بين إدارة الإطارات والتطبيقات ، لا يتم إجراء الطلبات غير الضرورية.
لا يخلو من المشاكل: بعض المكونات الإضافية لـ chrome (CryptoPro ، redux devtools) توقفت عن العمل في التطبيق الذي تم تنزيله ، بسبب فقد رابط النافذة أثناء التفاعل. كانت التحسينات الإضافية مطلوبة.
نتيجة لذلك ، في نهاية عام 2019 ، نجحنا في نقل جميع التطبيقات إلى مدير الإطارات ، وغرق الشريط الجانبي في النسيان. ولكن استمر العمل في برنامج Frame Manager ، وظهر سؤال جديد: هل من الممكن تحسين وتحسين عمل الواجهة الأمامية في Tinkoff Business بطريقة ما؟ اتضح أنه يمكنك! لكن المزيد عن ذلك في المقالة التالية.