Laiskasti ladattavat moduulit ja ominaisuusliput
Ladatkaa valinnaiset ominaisuusmoduulit tarpeen mukaan LazyModuleLoaderilla käynnistysajan lyhentämiseksi.
Laiskasti ladattavat moduulit ja ominaisuusliput on ilmainen NestJS-yritysbackendien API:t-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu NestJS-yritysbackendien API:t-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. NestJS-yritysbackendien API:t-kurssilla on yhteensä 4 oppituntia.
Miksi innokas lataus hidastaa käynnistystä
Oletusarvoisesti NestJS luo jokaisen imports-kaaviossa olevan moduulin käynnistyksen yhteydessä. Yritystason API:ssa, jossa on kymmeniä valinnaisia ominaisuuksia — PDF-viejä, maksupalvelu tai tekoälyyn perustuva pisteytysmoottori — tämä tarkoittaa kaikkien palveluntarjoajien luonnin ja yhteyksien lämmityksen kustannusten maksamista ennen kuin sovellus edes vastaanottaa ensimmäistä pyyntöä.
- Raskaat SDK:t (Stripe, AWS, gRPC-asiakkaat) suorittavat konstruktorinsa innokkaasti.
- Moduulit, joita tietty käyttöönotto ei koskaan käytä, ladataan silti.
- Kylmäkäynnistyksen viive kasvaa lineaarisesti moduulikaavion koon mukana.
Ratkaisu on ladata valitut ominaisuusmoduulit laiskasti vasta ensimmäisen käyttökerran yhteydessä.
LazyModuleLoader
Nest sisältää valmiin LazyModuleLoader-luokan (paketista @nestjs/core). Se injektoidaan kuten mikä tahansa provider, minkä jälkeen kutsutaan load()-metodia factory-funktiolla, joka palauttaa moduulin. Nest rekisteröi moduulin providerit tarvittaessa ja tallentaa muodostuneen viitteen myöhempiä kutsuja varten.
Keskeiset ominaisuudet:
- Lazily ladattavia moduuleja ei määritetä missään
imports-taulukossa. - Ne eivät rekisteröi controllereita, resolvereita tai enhancereita — ainoastaan providereita.
- Ensimmäinen
load()-kutsu luo instanssin; myöhemmät kutsut palauttavat välimuistissa olevanModuleRef-viitteen.
import { Injectable } from '@nestjs/common';
import { LazyModuleLoader } from '@nestjs/core';
@Injectable()
export class ReportsService {
constructor(private readonly lazyModuleLoader: LazyModuleLoader) {}
async generate(): Promise<void> {
const { PdfModule } = await import('./pdf/pdf.module');
const moduleRef = await this.lazyModuleLoader.load(() => PdfModule);
// moduleRef now exposes PdfModule's providers
}
}Providerin ratkaiseminen lazily ladatusta moduulista
load()-metodin palauttama objekti on ModuleRef. Sen get()-metodilla voitte noutaa konkreettisen providerin juuri ladatusta moduulista. Koska lazily ladatut moduulit ovat eristettyjä, provider tulee pyytää vasta moduulin lataamisen jälkeen.
Request-scoped- tai transient-providereita varten käyttäkää moduleRef.resolve()-metodia get()-metodin sijaan.
async generate(): Promise<Buffer> {
const { PdfModule } = await import('./pdf/pdf.module');
const moduleRef = await this.lazyModuleLoader.load(() => PdfModule);
const pdfService = moduleRef.get(PdfService);
return pdfService.render({ title: 'Invoice' });
}Dynaaminen import() säästää tavut
Varsinainen käynnistysajan hyöty syntyy, kun LazyModuleLoader.load() yhdistetään dynaamiseen import()-kutsuun. Tiedoston alussa oleva staattinen import tuo moduulin — ja sen raskaat transitiiviset riippuvuudet — bootstrap-bundleen. Dynaaminen import() siirtää tiedoston evaluoinnin siihen asti, kunnes kutsu suoritetaan.
- Staattinen
import { PdfModule }tiedoston alussa = ladataan käynnistyksen yhteydessä. - Metodin sisällä oleva
await import('./pdf/pdf.module')= ladataan ensimmäisellä käyttökerralla.
Tuokaa siis lazily ladattavan moduulin tiedosto aina dynaamisesti, ei koskaan staattisesti.
Lazily ladattavan feature-moduulin määrittely
Lazily ladattava moduuli on tavallinen @Module — sen decoratorissa ei ole mitään erityistä. Lazily latautuvaksi sen tekee ainoastaan tapa, jolla sitä käytetään (eli LazyModuleLoader-luokan kautta imports-taulukon sijaan).
Pidä sen providerit itsenäisinä, jotta moduulin lataaminen ei tuo mukanaan koko sovellusta.
import { Module } from '@nestjs/common';
import { PdfService } from './pdf.service';
@Module({
providers: [PdfService],
exports: [PdfService],
})
export class PdfModule {}Välimuisti tekee toistuvista latauksista edullisia
Nest ylläpitää sisäisesti rekisteriä jo ladatuista lazily ladatuista moduuleista factory-funktion tuloksen perusteella. Siksi load()-metodin toistuva kutsuminen saman moduuliluokan kanssa on ensimmäisen latauksen jälkeen käytännössä ilmaista — instansseja ei luoda kahdesti eikä yhteyksiä muodosteta päällekkäin.
Voitte siis kutsua load()-metodia turvallisesti suoraan kuormitetussa handlerissa ilman omaa suojausta; framework huolehtii päällekkäisten latausten yhdistämisestä. Kertaluonteinen kustannus syntyy ensimmäisestä pyynnöstä, joka tarvitsee ominaisuutta.
Feature toggle: ohjaa lataamista
Feature toggle -kytkimet ja lazy loading sopivat luontevasti yhteen. Moduulien rekisteröimisen ehdollisesti käännösvaiheessa sijaan tarkistatte lipun ajonaikana ja kutsutte load()-metodia vain, kun lippu on käytössä. Käytöstä poistettu ominaisuus ei tällöin maksa mitään — edes sen konstruktoria ei suoriteta.
- Lippu voi tulla ympäristömuuttujasta, config-palvelusta tai etäisestä lippupalvelusta (LaunchDarkly, Unleash).
- Jos kytkin on pois käytöstä, keskeyttäkää suoritus ennen importia.
@Injectable()
export class ExportService {
constructor(
private readonly lazyModuleLoader: LazyModuleLoader,
private readonly flags: FeatureFlagService,
) {}
async export(payload: ExportDto) {
if (!this.flags.isEnabled('pdf-export')) {
throw new ForbiddenException('Feature disabled');
}
const { PdfModule } = await import('./pdf/pdf.module');
const ref = await this.lazyModuleLoader.load(() => PdfModule);
return ref.get(PdfService).render(payload);
}
}Pienin mahdollinen lippupalvelu (itsenäinen)
Feature flag -tarkistus on vain deterministinen haku. Tässä on frameworkista riippumaton versio, jonka toimintaa voitte tarkastella ja testata erikseen — sama logiikka, jonka Nestin FeatureFlagService voisi kääriä ympärilleen. Se lukee lippukarttaa ja käyttää oletusarvoa, jos avainta ei löydy.
class FeatureFlags {
constructor(private readonly flags: Record<string, boolean>) {}
isEnabled(key: string, fallback = false): boolean {
return this.flags[key] ?? fallback;
}
}
const flags = new FeatureFlags({ 'pdf-export': true, 'ai-scoring': false });
console.log(flags.isEnabled('pdf-export')); // true
console.log(flags.isEnabled('ai-scoring')); // false
console.log(flags.isEnabled('unknown', true)); // true (fallback)Controllerit ja enhancerit ohitetaan
Keskeinen rajoitus on seuraava: kun moduuli ladataan lazily, Nest rekisteröi siitä ainoastaan providerit. Se ohittaa tarkoituksella seuraavat:
controllers— uusia HTTP-reittejä ei synny.- Moduulissa määritetyt globaalit guardit, interceptorit, pipet ja filterit.
- GraphQL-resolverit.
Lazily ladattava moduuli ei siis voi lisätä endpointteja. Julkaiskaa ominaisuus eager-tilassa ladatun moduulin controllerista, joka delegoi kutsun lazily ladatulle providerille.
@Controller('reports')
export class ReportsController {
constructor(private readonly reports: ReportsService) {}
@Post('pdf')
async pdf(@Body() dto: ExportDto) {
// controller is eager; PdfModule is loaded lazily inside the service
return this.reports.generate(dto);
}
}Warm-up vai lazy loading: valitkaa ominaisuuskohtaisesti
Lazy loading vaihtaa ensimmäisen pyynnön kertaluonteisen viivepiikin nopeampaan ja kevyempään käynnistykseen. Se on oikea ratkaisu harvoin käytetyille, raskaille ominaisuuksille. Kuormituspolulla oleville ominaisuuksille eager loading (tai eksplisiittinen warm-up kohdassa onApplicationBootstrap) estää ensimmäisen käyttäjän hidastumisen.
Ohje päätöksentekoon:
- Lazy: raskas SDK, käytössä alle X prosentissa pyynnöistä, käyttöönoton mukaan valinnainen.
- Eager: ydintoimialue, jokainen pyyntö, viiveherkkä.
- Lazy + warm-up: raskas ominaisuus, jota tarvitaan ennustettavasti pian käynnistyksen jälkeen.
@Injectable()
export class Warmer implements OnApplicationBootstrap {
constructor(private readonly lazyModuleLoader: LazyModuleLoader) {}
async onApplicationBootstrap() {
if (process.env.PRELOAD_PDF === 'true') {
const { PdfModule } = await import('./pdf/pdf.module');
await this.lazyModuleLoader.load(() => PdfModule); // pay cost now, off the request path
}
}
}Hyödyn mittaaminen
Mitatkaa tilanne ennen ja jälkeen muutoksen. Mitatkaa bootstrapin kesto ja ensimmäinen lazy load()-kutsu varmistaaksenne, että kompromissi on työkuormallanne todellinen.
- Käynnistysajan pitäisi lyhentyä viivästettyjen moduulien konstruktorien ja yhteyksien muodostamisen yhteenlasketun kustannuksen verran.
- Lazily ladattavan ominaisuuden ensimmäinen kutsu sisältää tämän kustannuksen kerran.
- Seuratkaa käyttöönoton jälkeisen ensimmäisen pyynnön P99-arvoa — siinä viivästetty kustannus näkyy.
Jos lazily ladattavaa ominaisuutta käytetään lähes jokaisessa pyynnössä, mittaustulokset osoittavat, että se kannattaa vaihtaa takaisin eager-lataukseen.
const t0 = performance.now();
const { PdfModule } = await import('./pdf/pdf.module');
const ref = await this.lazyModuleLoader.load(() => PdfModule);
this.logger.log(`Lazy PdfModule ready in ${Math.round(performance.now() - t0)}ms`);Pikatarkistus
Lataatte PdfModule-moduulin lazily LazyModuleLoader-luokan avulla. PdfModule määrittää controllerin, jossa on @Post('pdf')-reitti. Lataamisen jälkeen reitti palauttaa 404-virheen. Mikä on oikea selitys ja korjaus?
Yhteenveto
Opitte pienentämään NestJS:n käynnistyskustannuksia tarvittaessa ladattavilla moduuleilla:
LazyModuleLoader.load(() => SomeModule)luo moduulin providerit ensimmäisellä käyttökerralla ja tallentaa tuloksen välimuistiin.- Yhdistäkää se dynaamiseen
import()-kutsuun, jotta moduulin tiedostoa (ja raskaita riippuvuuksia) ei evaluoida bootstrapin aikana. - Ratkaiskaa providerit
moduleRef.get()-metodilla (tai scoped-providereilleresolve()-metodilla). - Feature toggle ohjaa lataamista: käytöstä poistettu ominaisuus ei maksa mitään, ei edes konstruktorin suoritusta.
- Lazily ladattavat moduulit eivät rekisteröi controllereita, resolvereita tai enhancereita — delegoikaa kutsu eager-tilassa ladatusta controllerista.
- Valitkaa lazy raskaille, harvoin käytetyille ja valinnaisille ominaisuuksille; käyttäkää eager-latausta (tai lazy + warm-up -ratkaisua) kuormituspolun koodille. Mitatkaa käynnistys- ja ensimmäisen kutsun viive varmistaaksenne ratkaisun toimivuuden.
Opi TypeScript tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 20
- Oppitunnit
- 76
Usein kysytyt kysymykset
Onko oppitunti ”Laiskasti ladattavat moduulit ja ominaisuusliput” ilmainen?
Kyllä – oppitunnin ”Laiskasti ladattavat moduulit ja ominaisuusliput” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko NestJS-yritysbackendien API:t-kurssin, päivitä CoddyKit PROhon. NestJS-yritysbackendien API:t-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Laiskasti ladattavat moduulit ja ominaisuusliput”?
Ladatkaa valinnaiset ominaisuusmoduulit tarpeen mukaan LazyModuleLoaderilla käynnistysajan lyhentämiseksi. Harjoittelet NestJS-yritysbackendien API:t-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni NestJS-yritysbackendien API:t-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin NestJS-yritysbackendien API:t-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.
Kuinka kauan ”Laiskasti ladattavat moduulit ja ominaisuusliput”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä NestJS-yritysbackendien API:t-oppitunnilla?
Kyllä. Jokainen NestJS-yritysbackendien API:t-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Portit ja adapterit toimialueen eristämiseen
- Palveluntarjoajien dynaaminen rekisteröinti DiscoveryServicella
- Laiskasti ladattavat moduulit ja ominaisuusliput
- Laajennuspisteet Module Reference APIlla