پروژه ای که سه ماه پیش در بخش فرانت شروع کردم به توسعه ش ، شامل دو اپلیکیشن انگولار بود که با یک کتابخانه مشترک بنام UI-Kit کار میکردند. در واقع در بخش ui-design هر دو اپلیکیشن از استانداردهای یکسانی برای نمایش استفاده شده بود. بنابر این کتابخانه مشترکی بنام uikit نیاز بود که یکبار طرح های همکاران دیزاینر پیاده سازی بشه.
برای همچین پروژه هایی میشه از angular workspace استفاده کرد. قطعا ممکنه کتابخانه های مشترک دیگه ای هم در توسعه نرم افزار باشه که لازمه جدا از فضای اپلیکیشن توسعه پیدا کنند.
طی این مقاله، تجربه خودم رو در سه بخش به اشتراک میگذارم که عبارتند از:
۱- ساخت workspace به همراه اپلیکیشن ها و کتابخانه مشترک
۲- استفاده از کتابخانه مشترک در هر اپلیکیشن
۳- اضافه کردن اپلیکشن از قبل ساخته شده به workspace
۴- اضافه کردن کامپوننت جدید به کتابخانه مشترک
قبل از اینکه جلوتر بریم، بگم که این مقاله رو بر اساس تجربیات خودم نوشتم. ممکنه بنا به هر دلیلی مثل تفاوت نسخه ها شما با مشکلات دیگری روبرو بشید که من روبرو نشدم. امیدوارم این مقاله برای شما راهگشا باشه.
اول یک فضای workspace میسازیم به اسم angular-ws
بعد وارد پوشه angular-ws میشیم
اگر یک نگاهی به فایل های ساخته شده بندازیم، میبینیم که فعلا خبری از پوشه projects یا src نیست:
محتوای فایل package.json ساخته شده رو ببینیم:
و محتوای فایل angular.json که اینجا هم بخش projects خالیه:
در حالیکه داخل پوشه angular-ws هستیم، اپلیکیشن جدیدی میسازیم بنام myapp1 :
اگر یه نگاهی به فولدر angular-ws بندازیم می بینیم که پوشه projects داخلش ایجاد شده و داخل پوشه projects هم پوشه مربوط به اپ تازه ساخته شده مون به اسم myapp1 هست
اگر نگاهی به فایل angular.json بندازیم، می بینیم که پروژه ای بنام myapp1 ساخته شده که projectType از نوع application داره و همه تنظیمات مربوط به اپلیکیشن انگولار براش بر نظر گرفته شده.
به همین ترتیب اپلیکیشن myapp2 میسازیم:
و بعدش کتابخانه uikit رو میسازیم که قراره بین دو اپلیکیشن مشترک باشه:
داخل پوشه projects ، سه پوشه از اپلیکیشن ها و کتابخانه ی ساخته شده داریم
همین طور داخل فایل angular.json سه پروژه تعریف کردیم. اپلیکیشن ها از جنس application و کتابخانه uikit از جنس library هستند.
برای اجرا کردن هر کدوم از اپلیکیشن ها میتونیم از دستورهای زیر استفاده کنیم:
که در واقع متناظر با دستورهای زیر هستند:
در قدم اول، از کتابخانه مشترک یک نسخه میسازیم:
به محتوای پوشه angular-ws که نگاه بندازیم، می بینیم که یک پوشه dist ساخته شده و داخلش یه پوشه uikit هست و نسخه build شده از کتابخانه uikit داخلش قرار داره.
در قدم دوم میخوایم این کتابخانه ساخته شده رو به اپلیکیشن myapp1 اضافه کنیم. داخل فایل app.module.ts در myapp1 ( فرقی نمیکنه کدوم اپلیکیشن ) کتابخانه uikit رو import میکنیم:
در قدم سوم میخوایم از کامپوننت کتابخانه uikit در اپلیکیشن myapp1 استفاده کنیم. پس اول یک نگاهی به فایل uikit.component.ts داخل پوشه uikit میندازیم ببینیم اسم کامپوننت (بخش selector) چیه:
اسم selector رو پیدا میکنیم که هست lib-uikit .
در قدم چهارم از این کامپوننت uikit داخل اپلیکیشن myapp1 استفاده میکنیم. یعنی داخل app.component.html در پروژه myapp1 ، کامپوننت رو اضافه میکنیم:
اول اپلیکیشن رو run میکنیم ببینیم محتوای کامپوننت uikit.component.ts رو در صفحه myapp1 می بینیم یا خیر:
و با باز شدن صفحه (پیشفرض localhost با پورت ۴۲۰۰ ) روی آدرس http://localhost:4200 همه چیز به نظر درست میاد:
پایین سمت چپ نوشته uikit works! رو میبینیم که محتوای کامپوننت uikit هست.
حالا وقتشه یک build از اپلیکیشن myapp1 بگیریم و خروجی رو بررسی کنیم.
در قدم پنجم، از اپلیکیشن myapp1 بیلد میگیریم:
داخل پوشه dist در angular-ws یک پوشه ساخته میشه به اسم myapp1 که همه bundle ها و فایل های اپلیکیشن داخلش قرار گرفته. وقتشه که اپلیکیشن رو host کنیم (قدم ششم).
قدم ششم دستور نصب http-server و اختیاریه. اگر دوست دارید مثل من از پکیج http-server استفاده کنید. اگر نه هر پکیجی که دوست دارید رو استفاده کنید. برای نصب http-server دستور زیر رو اجرا میکنیم:
حالا با اجرای دستور زیر ( به صورت پیشفرض در localhost پورت 8080 ) داخل پوشه angular-ws، اپلیکیشن ما هاست میشه:
وقتی آدرس http://localhost:8080 رو روی مرورگر باز کنیم باز هم می بینیم که همه چیز داره درست کار میکنه
بنابر این اصل کار جمع شده!
قدم هفتم معرفی کردن dist/uikit به تنظیم paths در tsconfig.json هست و برای نسخه های قدیمی تر ضروریه. در نسخه ۱۶ انگولار این مشکل حل شده ولی در نسخه ۱۵ به قبل به صورت پیش فرض حل نشده:
اگر تایپ اسکریپت به هر دلیلی یاری نکرد و حاصر نشد uikit رو به رسمیت بشناسه، این قدم رو بردارید و حتما اکی میشه. این قدم اضافه کردن مسیر نسخه نهایی uikit به فایل tsconfig.app.json درون پوشه myapp1 هست:
اول یه نگاهی به محتوای فعلی این فایل بندازیم. یک آپشن داره به اسم compilerOptions که شامل تنظیم outDir و types هست:
میخواهیم یک تنظیم دیگه به compilerOptions اضافه کنیم به اسم paths:
و typescript با اضافه کردن این تنظیم uikit رو میشناسه.
به این نکته دقت کنید که از این به بعد هر کامپوننت یا سرویسی که میسازید، باید نام اپلیکیشن یا سرویس مربوطه را هم مشخص کنید:
و کامپوننت یا سرویس جدید در همان اپلیکیشن ساخته میشود:
فرض کنید یک اپلیکیشن داریم به اسم myapp3 و میخواهیم به workspace منتقلش کنیم یا اپلیکیشن myapp3 رو تبدیلش کنیم به workspace که اپلیکیشن داخلشه.
قدم اول: ساخت workspace
اگر workspace قبل تر وجود داشته، داخلش یک اپلیکیشن خالی myapp3 میسازیم . اگر هم میخوایم تازه یک workspace برای همین اپلیکیشن مون بسازیم که مراحل ساخت workspace و یک اپلیکیشن جدید داخل workspace بنام myapp3 رو بر اساس بخش های قبلی مقاله انجام میدیم.
در قدم دوم همه محتوای src اپلیکیشن موجود رو داخل اپلیکیشن جدید (داخل workspace ) کپی میکنیم. مثلا اگر در روت workspace باشیم:
قدم سوم: برای اینکه import های داخل فایل های پروژه به مشکل نخورند، داخل فایل tsconfig.app.json داخل اپلیکیشن myapp3 باید تغییراتی اعمال کنیم و به تنظیمات compilerOptions ، مقدار baseUrl رو اضافه کنیم:
قدم چهارم: اضافه کردن dependency ها به پروژه
همه dependency های اپلیکیشن قدیمی رو به workspace اضافه کنید و npm install بزنید تا نصب بشن. نگران اینکه کدوم اپلیکیشن به کدوم dependency نیاز داره نباشید. اگر اپلیکیشنی به یک dependency نیاز نداشته باشه، موقع build اپلیکیشن اصلا سراغ اون dependency نمیره.
در قدم پنجم چنانچه به دلیل تفاوت نسخه های انگولار یا typescript یا پکیج های دیگر بین اپلیکیشن موجود و اپلیکیشن جدید بخش هایی از برنامه به خطا بخورد، تغییراتی لازم است که انجام شود. مشکلاتی که من به شخصه باهاشون روبرو بودم از جنس پشتیبانی نکردن از syntax های قدیمی بود و همه syntax ها رو به روز کردم. تا همین قدم برای من کار جمع شد و تونستم اپلیکیشن رو به workspace منتقل کنم.
در این قسمت میخوایم یک کامپوننت جدید به کتابخانه uikit اضافه کنیم، طوری که بتونیم در اپلیکیشن ها ازش استفاده کنیم.
در قدم اول یک کامپوننت به اسم button میسازم که قراره دکمه طراحی شده در uikit رو ارائه بده:
اسم selector این کامپوننت lib-button تعریف شده.
در قدم دوم میرم سراغ یک فایل به اسم public-api.ts که در پوشه lib داخل کتابخانه uikit موجوده. در انتهای این فایل، کامپوننت button رو export میکنم:
در قدم سوم میرم سراغ فایل ماژول uikit به اسم uikit.modue.ts و کامپوننت رو داخلش تعریف میکنم و در بخش exports هم اضافه میکنم که خارج از ماژول هم بشه از این کامپوننت استفاده کرد:
کامپوننت جدیدمون آماده است. در ادامه میتونم یک بیلد از کتابخانه بگیرم و هر جای اپلکیشن myapp1 که لازمم بشه، به صورت زیر ازش استفاده کنم:
در این مقاله با workspace ها آشنا شدیم و دیدیم چطور میشه اپلیکیشن های مختلف از یک کتابخانه مشترک استفاده کنند. همینطور دیدیم که چطور میشه یک اپلیکیشن رو وارد فضای workspace کرد یا به یک workspace تبدیلش کرد. در آخر هم یک کامپوننت دیگه به کتابخانه مشترک اضافه کردیم طوری که در اپلیکیشن ها قابل استفاده باشه :)