Dinamiškame šiuolaikinio interneto kūrimo pasaulyje sklandžios ir jautrios vartotojo patirties užtikrinimas yra itin svarbus, ypač pasaulinei auditorijai. Vartotojai skirtinguose regionuose, su skirtingu interneto greičiu ir įrenginių galimybėmis, tikisi, kad programos bus įkeliamos greitai ir sklandžiai tvarkys klaidas. React, pirmaujanti JavaScript biblioteka vartotojo sąsajoms kurti, pristatė Suspense – galingą funkciją, skirtą supaprastinti asinchronines operacijas ir pagerinti įkėlimo būsenų bei klaidų valdymą mūsų komponentuose.
Šiame išsamiame vadove gilinsimės į React Suspense, tyrinėsime jo pagrindines koncepcijas, praktinius pritaikymus ir tai, kaip jis suteikia kūrėjams galimybę kurti atsparesnes ir našesnes globalias programas. Aptarsime asinchroninį komponentų įkėlimą, pažangius klaidų tvarkymo mechanizmus ir geriausias praktikas integruojant Suspense į jūsų projektus, užtikrinant aukščiausios kokybės patirtį vartotojams visame pasaulyje.
Evoliucijos supratimas: Kodėl Suspense?
Prieš atsirandant Suspense, asinchroninių duomenų gavimo ir komponentų įkėlimo valdymas dažnai reikalavo sudėtingų šablonų:
Rankinis būsenos valdymas: Kūrėjai dažnai naudojo vietinę komponento būseną (pvz., useState su loginėmis reikšmėmis kaip isLoading ar hasError), kad sektų asinchroninių operacijų statusą. Tai vedė prie pasikartojančio šabloninio kodo įvairiuose komponentuose.
Sąlyginis atvaizdavimas: Skirtingų vartotojo sąsajos būsenų (įkėlimo indikatorių, klaidų pranešimų ar tikrojo turinio) rodymas reikalavo sudėtingos sąlyginio atvaizdavimo logikos JSX viduje.
Aukštesnės eilės komponentai (HOC) ir atvaizdavimo savybės (Render Props): Šie šablonai dažnai buvo naudojami duomenų gavimo ir įkėlimo logikai abstrahuoti, tačiau jie galėjo sukelti savybių perdavimo („prop drilling“) problemą ir sudėtingesnį komponentų medį.
Fragmentuota vartotojo patirtis: Kadangi komponentai įsikeldavo nepriklausomai, vartotojai galėjo susidurti su nesuderinta patirtimi, kai dalys vartotojo sąsajos atsirasdavo anksčiau už kitas, sukurdamos „nestilizuoto turinio blyksnį“ (FOUC) arba nenuoseklius įkėlimo indikatorius.
React Suspense buvo pristatytas siekiant išspręsti šias problemas, suteikiant deklaratyvų būdą tvarkyti asinchronines operacijas ir su jomis susijusias vartotojo sąsajos būsenas. Jis leidžia komponentams „sustabdyti“ atvaizdavimą, kol jų duomenys bus paruošti, o React gali valdyti įkėlimo būseną ir rodyti atsarginę vartotojo sąsają. Tai ženkliai supaprastina kūrimo procesą ir pagerina vartotojo patirtį, užtikrindama vientisesnį įkėlimo srautą.
Pagrindinės React Suspense koncepcijos
Iš esmės, React Suspense sukasi aplink dvi pagrindines koncepcijas:
1. Suspense komponentas
Suspense komponentas yra asinchroninių operacijų dirigentas. Jis apgaubia komponentus, kurie gali laukti duomenų ar kodo įkėlimo. Kai antrinis komponentas „sustabdomas“, artimiausia virš jo esanti Suspense riba atvaizduos savo fallback savybę. Ši fallback savybė gali būti bet koks React elementas, dažniausiai įkėlimo indikatorius, karkaso ekranas („skeleton screen“) ar klaidos pranešimas.
import React, {
Suspense
} from 'react';
const MyDataComponent = React.lazy(() => import('./MyDataComponent'));
function App() {
return (
Welcome!
Loading data...
}>
);
}
export default App;
Šiame pavyzdyje, jei MyDataComponent sustabdomas (pvz., gaunant duomenis), Suspense komponentas rodys „Loading data...“, kol MyDataComponent bus pasirengęs atvaizduoti savo turinį.
2. Kodo padalijimas su React.lazy
Vienas iš dažniausių ir galingiausių Suspense panaudojimo atvejų yra kodo padalijimas. React.lazy leidžia atvaizduoti dinamiškai importuotą komponentą kaip įprastą komponentą. Kai tingiai įkeliamas komponentas atvaizduojamas pirmą kartą, jis sustabdomas, kol modulis, kuriame yra komponentas, bus įkeltas ir paruoštas.
React.lazy priima funkciją, kuri turi iškviesti dinaminį import(). Ši funkcija turi grąžinti pažadą (Promise), kuris išsipildo į objektą su default eksportu, turinčiu React komponentą.
// MyDataComponent.js
import React from 'react';
function MyDataComponent() {
// Assume data fetching happens here, which might be asynchronous
// and cause suspension if not handled properly.
return
Here is your data!
;
}
export default MyDataComponent;
// App.js
import React, { Suspense } from 'react';
// Lazily import the component
const LazyLoadedComponent = React.lazy(() => import('./MyDataComponent'));
function App() {
return (
Asynchronous Loading Example
Loading component...
}>
);
}
export default App;
Kai App atvaizduojamas, LazyLoadedComponent inicijuos dinaminį importą. Kol komponentas gaunamas, Suspense komponentas rodys savo atsarginę vartotojo sąsają. Kai komponentas bus įkeltas, Suspense jį automatiškai atvaizduos.
3. Klaidų ribos (Error Boundaries)
Nors React.lazy tvarko įkėlimo būsenas, jis savaime netvarko klaidų, kurios gali atsirasti dinaminio importo proceso metu arba pačiame tingiai įkeltame komponente. Čia į pagalbą ateina klaidų ribos (Error Boundaries).
Klaidų ribos yra React komponentai, kurie pagauna JavaScript klaidas bet kurioje savo antrinių komponentų medžio vietoje, registruoja tas klaidas ir rodo atsarginę vartotojo sąsają vietoj komponento, kuris sugedo. Jos įgyvendinamos apibrėžiant static getDerivedStateFromError() arba componentDidCatch() gyvavimo ciklo metodus.
// ErrorBoundary.js
import React, { Component } from 'react';
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
console.error("Uncaught error:", error, errorInfo);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return
Įdėjus Suspense komponentą į ErrorBoundary vidų, sukuriama patikima sistema. Jei dinaminis importas nepavyksta arba pats komponentas sukelia klaidą atvaizdavimo metu, ErrorBoundary ją pagaus ir parodys savo atsarginę vartotojo sąsają, neleisdama visai programai sugesti. Tai yra gyvybiškai svarbu norint išlaikyti stabilią patirtį vartotojams visame pasaulyje.
Suspense duomenų gavimui
Iš pradžių Suspense buvo pristatytas su akcentu į kodo padalijimą. Tačiau jo galimybės išsiplėtė ir apima duomenų gavimą, leidžiančios taikyti vieningesnį požiūrį į asinchronines operacijas. Kad Suspense veiktų su duomenų gavimu, jūsų naudojama duomenų gavimo biblioteka turi integruotis su React atvaizdavimo primityvais. Bibliotekos kaip Relay ir Apollo Client buvo ankstyvosios šios technologijos naudotojos ir teikia integruotą Suspense palaikymą.
Pagrindinė idėja yra ta, kad duomenų gavimo funkcija, ją iškvietus, gali neturėti duomenų iš karto. Užuot grąžinusi duomenis tiesiogiai, ji gali „išmesti“ (throw) pažadą (Promise). Kai React susiduria su šiuo išmestu pažadu, jis žino, kad reikia sustabdyti komponentą ir parodyti artimiausios Suspense ribos pateiktą atsarginę vartotojo sąsają. Kai pažadas išsipildo, React iš naujo atvaizduoja komponentą su gautais duomenimis.
Pavyzdys su hipotetiniu duomenų gavimo kabliu (Hook)
Įsivaizduokime individualų kablį, useFetch, kuris integruojasi su Suspense. Šis kablys paprastai valdytų vidinę būseną ir, jei duomenų nėra, išmestų pažadą, kuris išsipildo, kai duomenys gaunami.
// hypothetical-fetch.js
// This is a simplified representation. Real libraries manage this complexity.
let cache = {};
function createResource(fetchFn) {
return {
read() {
if (cache[fetchFn]) {
const { data, promise } = cache[fetchFn];
if (promise) {
throw promise; // Suspend if promise is still pending
}
return data;
}
const promise = fetchFn().then(data => {
cache[fetchFn] = { data };
});
cache[fetchFn] = { promise };
throw promise; // Throw promise on initial call
}
};
}
export default createResource;
// MyApi.js
const fetchUserData = async () => {
console.log("Fetching user data...");
// Simulate network delay
await new Promise(resolve => setTimeout(resolve, 2000));
return { id: 1, name: "Alice" };
};
export { fetchUserData };
// UserProfile.js
import React, { useContext, createContext } from 'react';
import createResource from './hypothetical-fetch';
import { fetchUserData } from './MyApi';
// Create a resource for fetching user data
const userResource = createResource(() => fetchUserData());
function UserProfile() {
const userData = userResource.read(); // This might throw a promise
return (
User Profile
Name: {userData.name}
);
}
export default UserProfile;
// App.js
import React, { Suspense } from 'react';
import UserProfile from './UserProfile';
import ErrorBoundary from './ErrorBoundary';
function App() {
return (
Global User Dashboard
Loading user profile...
}>
);
}
export default App;
Šiame pavyzdyje, kai UserProfile atvaizduojamas, jis iškviečia userResource.read(). Jei duomenys nėra talpykloje (cache) ir duomenų gavimas tebevyksta, userResource.read() išmes pažadą. Suspense komponentas pagaus šį pažadą, parodys atsarginį pranešimą „Loading user profile...“ ir iš naujo atvaizduos UserProfile, kai duomenys bus gauti ir išsaugoti talpykloje.
Pagrindiniai privalumai globalioms programoms:
Vieningos įkėlimo būsenos: Valdykite tiek kodo dalių, tiek duomenų gavimo įkėlimo būsenas vienu, deklaratyviu šablonu.
Geresnis suvokiamas našumas: Vartotojai mato nuoseklią atsarginę vartotojo sąsają, kol vykdomos kelios asinchroninės operacijos, o ne fragmentuotus įkėlimo indikatorius.
Supaprastintas kodas: Sumažina šabloninio kodo kiekį, reikalingą rankiniam įkėlimo ir klaidų būsenų valdymui.
Įdėtosios Suspense ribos
Suspense ribos gali būti įdėtos viena į kitą. Jei komponentas, esantis įdėtoje Suspense riboje, sustabdomas, jis suaktyvins artimiausią Suspense ribą. Tai leidžia smulkmeniškai valdyti įkėlimo būsenas.
import React, { Suspense } from 'react';
import UserProfile from './UserProfile'; // Assumes UserProfile is lazy or uses data fetching that suspends
import ProductList from './ProductList'; // Assumes ProductList is lazy or uses data fetching that suspends
function Dashboard() {
return (
Dashboard
Loading User Details...
}>
Loading Products...
}>
);
}
function App() {
return (
Complex Application Structure
Loading Main App...
}>
);
}
export default App;
Pagal šį scenarijų:
Jei UserProfile sustabdomas, jį tiesiogiai apgaubianti Suspense riba parodys „Loading User Details...“.
Jei ProductList sustabdomas, jo atitinkama Suspense riba parodys „Loading Products...“.
Jei pats Dashboard (arba jame esantis neapgaubtas komponentas) sustabdomas, išorinė Suspense riba parodys „Loading Main App...“.
Ši įdėjimo galimybė yra itin svarbi sudėtingoms programoms su daugybe nepriklausomų asinchroninių priklausomybių, leidžianti kūrėjams apibrėžti tinkamas atsargines vartotojo sąsajas skirtinguose komponentų medžio lygmenyse. Šis hierarchinis požiūris užtikrina, kad tik atitinkamos vartotojo sąsajos dalys rodomos kaip įkeliamos, o kitos dalys lieka matomos ir interaktyvios, taip pagerinant bendrą vartotojo patirtį, ypač vartotojams su lėtesniu interneto ryšiu.
Klaidų tvarkymas su Suspense ir klaidų ribomis
Nors Suspense puikiai valdo įkėlimo būsenas, jis savaime netvarko klaidų, kurias išmeta sustabdyti komponentai. Klaidas turi pagauti klaidų ribos (Error Boundaries). Norint sukurti patikimą sprendimą, būtina derinti Suspense su klaidų ribomis.
Dažniausi klaidų scenarijai ir sprendimai:
Dinaminio importo gedimas: Tinklo problemos, neteisingi keliai ar serverio klaidos gali sukelti dinaminio importo nesėkmę. Klaidų riba pagaus šią nesėkmę.
Duomenų gavimo klaidos: API klaidos, tinklo laiko limitų viršijimas ar netinkamai suformuoti atsakymai duomenis gaunančiame komponente gali sukelti klaidas. Jas taip pat pagauna klaidų ribos.
Komponento atvaizdavimo klaidos: Bet kokia nepagaunama JavaScript klaida komponente, kuris atvaizduojamas po sustabdymo, bus pagauta klaidų ribos.
Geriausia praktika: Visada apgaubkite savo Suspense komponentus su ErrorBoundary. Tai užtikrina, kad bet kokia neapdorota klaida suspensijos medyje sukels sklandų atsarginės vartotojo sąsajos rodymą, o ne visos programos gedimą.
// App.js
import React, { Suspense } from 'react';
import ErrorBoundary from './ErrorBoundary';
import SomeComponent from './SomeComponent'; // This might lazy load or fetch data
function App() {
return (
Secure Global Application
Initializing...
}>
);
}
export default App;
Strategiškai išdėstydami Error Boundaries, galite izoliuoti galimus gedimus ir pateikti informatyvius pranešimus vartotojams, leisdami jiems atsigauti ar bandyti dar kartą, o tai yra gyvybiškai svarbu norint išlaikyti pasitikėjimą ir patogumą įvairiose vartotojų aplinkose.
Suspense integravimas su globaliomis programomis
Kuriant programas pasaulinei auditorijai, keli veiksniai, susiję su našumu ir vartotojo patirtimi, tampa kritiškai svarbūs. Suspense siūlo reikšmingų privalumų šiose srityse:
1. Kodo padalijimas ir internacionalizacija (i18n)
Programoms, palaikančioms kelias kalbas, dinamiškas konkrečios kalbos komponentų ar lokalizacijos failų įkėlimas yra įprasta praktika. React.lazy kartu su Suspense gali būti naudojamas šiems ištekliams įkelti tik tada, kai jų prireikia.
Įsivaizduokite scenarijų, kai turite didelius, konkrečiai šaliai skirtus vartotojo sąsajos elementus ar kalbų paketus:
// CountrySpecificBanner.js
// This component might contain localized text and images
import React from 'react';
function CountrySpecificBanner({ countryCode }) {
// Logic to display content based on countryCode
return
Welcome to our service in {countryCode}!
;
}
export default CountrySpecificBanner;
// App.js
import React, { Suspense, useState, useEffect } from 'react';
import ErrorBoundary from './ErrorBoundary';
// Dynamically load the country-specific banner
const LazyCountryBanner = React.lazy(() => {
// In a real app, you'd determine the country code dynamically
// For example, based on user's IP, browser settings, or a selection.
// Let's simulate loading a banner for 'US' for now.
const countryCode = 'US'; // Placeholder
return import(`./${countryCode}Banner`); // Assuming files like USBanner.js
});
function App() {
const [userCountry, setUserCountry] = useState('Unknown');
// Simulate fetching user's country or setting it from context
useEffect(() => {
// In a real app, you'd fetch this or get it from a context/API
setTimeout(() => setUserCountry('JP'), 1000); // Simulate slow fetch
}, []);
return (
Global User Interface
Loading banner...
}>
{/* Pass the country code if needed by the component */}
{/* */}
Content for all users.
);
}
export default App;
Šis požiūris užtikrina, kad bus įkeltas tik konkrečiam regionui ar kalbai reikalingas kodas, optimizuojant pradinį įkėlimo laiką. Vartotojai Japonijoje nesiųstų kodo, skirto vartotojams Jungtinėse Valstijose, todėl pradinis atvaizdavimas būtų greitesnis, o patirtis geresnė, ypač mobiliuosiuose įrenginiuose ar lėtesniuose tinkluose, kurie yra dažni kai kuriuose regionuose.
2. Laipsniškas funkcijų įkėlimas
Sudėtingos programos dažnai turi daug funkcijų. Suspense leidžia jums laipsniškai įkelti šias funkcijas vartotojui sąveikaujant su programa.
Čia FeatureA ir FeatureB įkeliami tik paspaudus atitinkamus mygtukus. Tai užtikrina, kad vartotojai, kuriems reikia tik tam tikrų funkcijų, nemokės už kodo, skirto funkcijoms, kurių jie galbūt niekada nenaudos, atsisiuntimą. Tai yra galinga strategija didelės apimties programoms su įvairiais vartotojų segmentais ir skirtingu funkcijų pritaikymo lygiu įvairiose pasaulio rinkose.
3. Tinklo kintamumo valdymas
Interneto greitis visame pasaulyje labai skiriasi. Suspense gebėjimas pateikti nuoseklią atsarginę vartotojo sąsają, kol vykdomos asinchroninės operacijos, yra neįkainojamas. Užuot matę sugadintas vartotojo sąsajas ar nepilnas dalis, vartotojams pateikiama aiški įkėlimo būsena, gerinant suvokiamą našumą ir mažinant nusivylimą.
Apsvarstykite vartotoją regione su dideliu vėlavimu (latency). Kai jie pereina į naują skiltį, kuriai reikia gauti duomenis ir tingiai įkelti komponentus:
Artimiausia Suspense riba rodo savo atsarginį variantą (pvz., karkaso įkėlimo indikatorių).
Šis atsarginis variantas lieka matomas, kol gaunami visi reikalingi duomenys ir kodo dalys.
Vartotojas patiria sklandų perėjimą, o ne staigius atnaujinimus ar klaidas.
Šis nuoseklus nenuspėjamų tinklo sąlygų valdymas leidžia jūsų programai atrodyti patikimesnei ir profesionalesnei pasaulinei vartotojų bazei.
Pažangūs Suspense šablonai ir aspektai
Integruojant Suspense į sudėtingesnes programas, susidursite su pažangiais šablonais ir aspektais:
Suspense yra sukurtas veikti su atvaizdavimu serveryje (SSR), siekiant pagerinti pradinio įkėlimo patirtį. Kad SSR veiktų su Suspense, serveris turi atvaizduoti pradinį HTML ir perduoti jį klientui srautu. Kai komponentai serveryje sustabdomi, jie gali išsiųsti vietos rezervavimo ženklus (placeholders), kuriuos kliento pusės React vėliau gali „hidratuoti“.
Bibliotekos, tokios kaip Next.js, teikia puikų integruotą Suspense palaikymą su SSR. Serveris atvaizduoja sustabdomą komponentą kartu su jo atsarginiu variantu. Tada kliento pusėje React „hidratuoja“ esamą žymėjimą ir tęsia asinchronines operacijas. Kai duomenys kliento pusėje yra paruošti, komponentas iš naujo atvaizduojamas su tikruoju turiniu. Tai lemia greitesnį pirmo turinio atvaizdavimą (First Contentful Paint - FCP) ir geresnį SEO.
2. Suspense ir lygiagrečios funkcijos (Concurrent Features)
Suspense yra vienas iš React lygiagrečių funkcijų pagrindų, kuriomis siekiama padaryti React programas jautresnes, leidžiant React vienu metu dirbti su keliais būsenos atnaujinimais. Lygiagretus atvaizdavimas leidžia React pertraukti ir tęsti atvaizdavimą. Suspense yra mechanizmas, kuris nurodo React, kada pertraukti ir tęsti atvaizdavimą remiantis asinchroninėmis operacijomis.
Pavyzdžiui, įjungus lygiagrečias funkcijas, jei vartotojas paspaudžia mygtuką gauti naujus duomenis, kol vyksta kitas duomenų gavimas, React gali suteikti prioritetą naujam gavimui, neblokuodamas vartotojo sąsajos. Suspense leidžia sklandžiai valdyti šias operacijas, užtikrinant, kad perėjimo metu būtų tinkamai rodomi atsarginiai variantai.
3. Individualios Suspense integracijos
Nors populiarios bibliotekos, tokios kaip Relay ir Apollo Client, turi integruotą Suspense palaikymą, taip pat galite sukurti savo integracijas individualiems duomenų gavimo sprendimams ar kitoms asinchroninėms užduotims. Tai apima resurso sukūrimą, kurio `read()` metodas, jį iškvietus, arba iš karto grąžina duomenis, arba išmeta pažadą.
Svarbiausia yra sukurti resurso objektą su `read()` metodu. Šis metodas turėtų patikrinti, ar duomenys yra prieinami. Jei taip, juos grąžinti. Jei ne, o asinchroninė operacija vyksta, išmesti su ta operacija susijusį pažadą. Jei duomenų nėra ir jokia operacija nevyksta, jis turėtų inicijuoti operaciją ir išmesti jos pažadą.
4. Našumo aspektai globaliems diegimams
Diegiant globaliai, apsvarstykite:
Kodo padalijimo detalumas: Padalinkite savo kodą į tinkamo dydžio dalis. Per daug mažų dalių gali sukelti per daug tinklo užklausų, o labai didelės dalys panaikina kodo padalijimo naudą.
CDN strategija: Užtikrinkite, kad jūsų kodo paketai būtų teikiami iš turinio pristatymo tinklo (CDN) su kraštinėmis lokacijomis (edge locations) arti jūsų vartotojų visame pasaulyje. Tai sumažina vėlavimą gaunant tingiai įkeliamus komponentus.
Atsarginės vartotojo sąsajos dizainas: Kurkite atsargines vartotojo sąsajas (įkėlimo indikatorius, karkaso ekranus), kurios būtų lengvos ir vizualiai patrauklios. Jos turėtų aiškiai nurodyti, kad turinys įkeliamas, per daug neatitraukiant dėmesio.
Klaidų pranešimų aiškumas: Pateikite aiškius, veiksmingus klaidų pranešimus vartotojo kalba. Venkite techninio žargono. Pasiūlykite veiksmus, kurių vartotojas gali imtis, pvz., bandyti dar kartą ar susisiekti su palaikymo tarnyba.
Kada naudoti Suspense
Suspense yra naudingiausias:
Kodo padalijimui: Dinamiškam komponentų įkėlimui naudojant React.lazy.
Duomenų gavimui: Naudojant bibliotekas, kurios integruojasi su Suspense duomenų gavimui (pvz., Relay, Apollo Client).
Įkėlimo būsenų valdymui: Supaprastinant logiką, skirtą įkėlimo indikatoriams rodyti.
Suvokiamo našumo gerinimui: Užtikrinant vieningą ir sklandesnę įkėlimo patirtį.
Svarbu pažymėti, kad Suspense vis dar tobulėja, ir ne visos asinchroninės operacijos yra tiesiogiai palaikomos iš karto be bibliotekų integracijų. Grynai asinchroninėms užduotims, kurios neapima atvaizdavimo ar duomenų gavimo taip, kad Suspense galėtų jas perimti, vis dar gali prireikti tradicinio būsenos valdymo.
Išvada
React Suspense yra reikšmingas žingsnis į priekį valdant asinchronines operacijas React programose. Suteikdamas deklaratyvų būdą tvarkyti įkėlimo būsenas ir klaidas, jis supaprastina komponentų logiką ir žymiai pagerina vartotojo patirtį. Kūrėjams, kuriantiems programas pasaulinei auditorijai, Suspense yra neįkainojamas įrankis. Jis leidžia efektyviai padalinti kodą, laipsniškai įkelti funkcijas ir taikyti atsparesnį požiūrį į įvairias tinklo sąlygas ir vartotojų lūkesčius, su kuriais susiduriama visame pasaulyje.
Strategiškai derindami Suspense su React.lazy ir klaidų ribomis (Error Boundaries), galite sukurti programas, kurios yra ne tik našios ir stabilios, bet ir teikia sklandžią bei profesionalią patirtį, nepriklausomai nuo to, kur yra jūsų vartotojai ar kokią infrastruktūrą jie naudoja. Priimkite Suspense, kad pakeltumėte savo React kūrimo lygį ir kurtumėte tikrai pasaulinio lygio programas.