خدمات بارگذاری تنبل در انگولار. چی؟! بله ما میتوانیم.

ما به بارگذاری تنبل ماژول ها یا کامپوننت ها در Angular عادت کرده ایم. اما خدمات بارگذاری تنبل چطور؟ صبر کن چی؟ بله ما میتوانیم. در این مقاله یاد می گیریم که چگونه یک سرویس را در Angular و آن گوچا لود کنیم.
Lazy Loading چیست؟
بارگذاری تنبل یک تکنیک بهینه سازی کد است که به آن تقسیم کد نیز می گویند. برای بارگذاری کد تنها زمانی استفاده می شود که به منظور کاهش اندازه اولیه بسته نرم افزاری و همچنین زمان بارگذاری برنامه مورد نیاز باشد. برای اینکه کد را تنبل بارگذاری کنیم، از دستور واردات پویا استفاده می کنیم.
به عنوان مثال، ما می توانیم یک ماژول مانند این را با تنبلی بارگذاری کنیم:
import("./my-component").then((file) => {
// do something with the component
});
با انجام این کار، به باندلر میگوییم که یک باندل جداگانه برای ماژول ایجاد کند و تنها زمانی که کد اجرا شد، آن را بارگذاری کند.
چگونه یک سرویس را در Angular بارگذاری کنیم؟
بله، ما از دستور واردات پویا استفاده خواهیم کرد. اما، نه تنها این! از آنجا که خدمات در Angular از دکوراتور تزریقی، به این معنی است که آنها قابل تزریق هستند و ممکن است به خدمات دیگری نیز وابسته باشند. بنابراین، ما نمیتوانیم سرویس را با تنبلی بارگیری کنیم و مستقیماً به عنوان یک کلاس معمولی از آن استفاده کنیم.
کاری که ما باید انجام دهیم این است که از دستور واردات پویا برای بارگذاری تنبل سرویس و سپس استفاده از آن استفاده کنیم انژکتور برای بدست آوردن نمونه خدمات. برای مثال، میتوانیم سرویسی مانند این را با تنبلی بارگذاری کنیم:
import("./my-service").then((file) => {
const service = this.injector.get(file.MyService);
// do something with the service
});
این عالی است، اما برای ما خوب نیست DX (تجربه توسعه دهنده). برای دریافت نمونه سرویس باید از انژکتور استفاده کنیم. بنابراین، ما می توانیم یک را ایجاد کنیم عملکرد کمکی که باعث بارگیری سرویس و بازگشت نمونه سرویس می شود. در اینجا یک تابع کمکی وجود دارد که می تواند در این مورد کمک کند.
export function lazyLoadService<T>(loader: () => Promise<T>): Promise<T> {
const injector = inject(Injector);
return loader().then((serviceClass) => {
const service = injector.get(serviceClass);
return service;
});
}
بیایید یک را برگردانیم قابل مشاهده به جای الف وعده، همانطور که بیشتر است راحت برای استفاده در Angular و زنجیر کردن راحت تر.
export function lazyService<T>(loader: () => Promise<Type<T>>): Observable<T> {
const injector = inject(Injector);
return defer(() => {
return loader().then((service) => injector.get(service));
});
}
این به تعویق انداختن اپراتور یک Observable ایجاد می کند که تابع لودر را فقط زمانی اجرا می کند که Observable باشد مشترک شد به. بنابراین، می توانیم از آن به صورت زیر استفاده کنیم:
lazyService(() => import("./my-service")).subscribe((service) => {
// do something with the service
});
یا بهتر از آن، می توانیم سرویس قابل مشاهده را لوله کنیم:
lazyService(() => import("./my-service")).pipe(
concatMap((service) => {
// do something with the service
})
);
بیایید نمونه ای از نحوه استفاده از آن را در یک کامپوننت ببینیم:
const DataServiceImport = () =>
import('./data.service').then((m) => m.DataService);
@Component({
template: `
<ul>
<li *ngFor="let todo of todos$ | async">
{{ todo.title }}
</li>
</ul>
`,
standalone: true,
imports: [NgFor, AsyncPipe],
})
export class AppComponent {
private dataService$ = lazyService(DataServiceImport);
todos$ = this.dataService$.pipe(concatMap((s) => s.getTodos()));
}
و حالا بیایید نگاهی به تب شبکه بیندازیم!
بله، این سرویس در بسته خود خواهد بود 🎉!
اما اگر بخواهیم از سرویس در کامپوننت دیگری استفاده کنیم، باید این کار را انجام دهیم تنبل دوباره آن را بارگذاری کنید. در غیر این صورت به صورت بسته بندی می شود بسته اصلی (اگر در کامپوننت بارگذاری نشده استفاده شود)، یا بسته مشترک (اگر در یکی دیگر از اجزای بارگذاری شده تنبل استفاده شود)، و تقسیم کد را بشکنید.
توجه: بسته جاوا اسکریپت فقط یک بار دانلود می شود، مهم نیست که چند بار آن را بارگیری کنیم، زیرا پس از اولین بارگیری، وب پک (باندلر) فقط از بسته دانلود شده مجددا استفاده می کند.
روش های مختلف برای بارگذاری تنبل یک سرویس
به این توییت توسط یونس، جایی که او روش های مختلف برای بارگذاری تنبل یک سرویس در Angular را توضیح می دهد:
فایده بارگذاری تنبل یک سرویس چیست؟
فرض کنید سرویسی داریم که فقط در یک جزء استفاده می شود. و ما می خواهیم کامپوننت را با تنبلی بارگذاری کنیم. بنابراین، ما می توانیم سرویس را نیز با تنبلی بارگذاری کنیم. و سرویس تنها زمانی که کامپوننت بارگیری می شود یا از سرویس استفاده می شود، لود می شود.
یکی دیگر از موارد استفاده زمانی است که ما برنامه های بسیار پویا داریم، یعنی کامپوننت ها را به صورت پویا و شاید بر اساس کانفیگ ها بارگذاری می کنیم و این کامپوننت ها ممکن است از سرویس های مختلف یا همان سرویس ها استفاده کنند. اما چون نمیدانیم از کدام سرویسها استفاده میشود، نمیتوانیم آنها را در بسته اصلی قرار دهیم وگرنه بزرگ میشود! بنابراین، میتوانیم سرویسها را با تنبلی بارگیری کنیم و فقط در صورت نیاز آنها را بارگیری کنیم.
نتیجه
من می خواهم یک فریاد بزنم @یونس برای تحقیقات عالی او در مورد خدمات بارگذاری تنبل در Angular. او کسی است که من را برای نوشتن این مقاله تشویق کرد. بنابراین، ادامه دهید و او را دنبال کنید توییتر.
پس از عرضه Ivy، کار با همه چیز در Angular آسان تر شده است. خدمات بارگیری تنبل نیز از این قاعده مستثنی نیست!
ادامه دهید و آن را امتحان کنید تا اندازه بسته اصلی را کاهش دهید. و نظر خود را در نظرات زیر به من بگویید.
با این ویژگی در اینجا بازی کنید: https://stackblitz.com/edit/angular-jb85mb?file=src/main.ts 🎮
با تشکر برای خواندن!
من در مورد Angular توییت میکنم (آخرین اخبار، ویدیوها، پادکستها، بهروزرسانیها، RFCها، درخواستهای کششی و موارد دیگر). اگر در مورد آن علاقه دارید، من را دنبال کنید @Enea_Jahollari. اگر این مقاله را دوست داشتید و می خواهید موارد بیشتری از این قبیل ببینید، من را در dev.to دنبال کنید!