Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Tarafından Fiyaz Hasan
Uyarı
Bu makalede açıklanan özellikler, ASP.NET Core 3.0 itibarıyla kullanımdan kaldırılmaktadır. Microsoft.AspNetCore.SpaServices.Extensions NuGet paketinde daha basit bir SPA çerçeveleri tümleştirme mekanizması sağlanır. Daha fazla bilgi için bkz . [Duyuru] Microsoft.AspNetCore.SpaServices ve Microsoft.AspNetCore.NodeServices'i kullanımdan kaldırma.
Tek Sayfalı Uygulama (SPA), doğası gereği zengin kullanıcı deneyimi nedeniyle popüler bir web uygulaması türüdür. Angular veya React gibi istemci tarafı SPA çerçevelerini veya kitaplıklarını ASP.NET Core gibi sunucu tarafı çerçevelerle tümleştirmek zor olabilir. JavaScript Hizmetleri, tümleştirme sürecindeki uyuşmaları azaltmak için geliştirilmiştir. Farklı istemci ve sunucu teknolojisi yığınları arasında sorunsuz işlem sağlar.
JavaScript Hizmetleri nedir?
JavaScript Hizmetleri, ASP.NET Core için istemci tarafı teknolojilerinden oluşan bir koleksiyondur. Amacı, ASP.NET Core'un SPA'lar oluşturmak için geliştiricilerin tercih ettiği sunucu tarafı platformu olarak konumlandırmaktır.
JavaScript Hizmetleri iki ayrı NuGet paketinden oluşur:
- Microsoft.AspNetCore.NodeServices (NodeServices)
- Microsoft.AspNetCore.SpaServices (SpaServices)
Bu paketler aşağıdaki senaryolarda kullanışlıdır:
- Sunucuda JavaScript çalıştırma
- SPA çerçevesi veya kitaplığı kullanma
- Webpack ile istemci tarafı varlıkları oluşturun
Bu makaledeki odağın büyük kısmı SpaServices paketini kullanmaya odaklanır.
SpaServices nedir?
SpaServices, ASP.NET Core'ı geliştiricilerin SPA'ları oluşturmak için tercih ettiği sunucu tarafı platformu olarak konumlandırmak için oluşturulmuştur. SpaServices'in ASP.NET Core ile SPA geliştirmesi gerekmez ve geliştiricileri belirli bir istemci çerçevesine kilitlemez.
SpaServices aşağıdakiler gibi kullanışlı bir altyapı sağlar:
- Sunucu tarafı ön işlemeyle render
- Webpack Geliştirici Ara Yazılımı
- Sıcak Modül Değiştirme
- Yönlendirme yardımcıları
Bu altyapı bileşenleri toplu olarak hem geliştirme iş akışını hem de çalışma zamanı deneyimini geliştirir. Bileşenler ayrı ayrı benimsenebilir.
SpaServices'i kullanma önkoşulları
SpaServices ile çalışmak için aşağıdakileri yükleyin:
npm kullanarak Node.js (sürüm 6 veya üzeri)
Bu bileşenlerin yüklendiğini ve bulunabildiğini doğrulamak için komut satırından aşağıdakileri çalıştırın:
node -v && npm -v
Azure web sitesine dağıtılıyorsa hiçbir eylem gerekmez;Node.js yüklenir ve sunucu ortamlarında kullanılabilir.
-
- Visual Studio 2017 kullanan Windows'ta SDK, .NET Core platformlar arası geliştirme iş yükü seçilerek yüklenir.
Microsoft.AspNetCore.SpaServices NuGet paketi
Sunucu tarafı önceden işleme
Evrensel (izomorfik olarak da bilinir) uygulaması, hem sunucuda hem de istemcide çalıştırabilen bir JavaScript uygulamasıdır. Angular, React ve diğer popüler çerçeveler, bu uygulama geliştirme stili için evrensel bir platform sağlar. Amaç, önce Node.jsaracılığıyla sunucuda çerçeve bileşenlerini işlemek ve ardından daha fazla işlemi istemciye devretmektir.
SpaServices tarafından sağlanan ASP.NET Çekirdek Etiket Yardımcıları , sunucudaki JavaScript işlevlerini çağırarak sunucu tarafı ön kayıt uygulamasını basitleştirir.
Sunucu tarafı ön kayıt önkoşulları
aspnet-prerendering npm paketini yükleyin:
npm i -S aspnet-prerendering
Sunucu tarafı ön kayıt yapılandırması
Etiket Yardımcıları, projenin _ViewImports.cshtml
dosyasındaki ad alanı kaydı aracılığıyla bulunabilir hale getirilir:
@using SpaServicesSampleApp
@addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers"
@addTagHelper "*, Microsoft.AspNetCore.SpaServices"
Bu Etiket Yardımcıları, görünümün içindeki HTML benzeri söz dizimi kullanarak alt düzey API'lerle doğrudan iletişim kurmanın karmaşıklıklarının üstünü örter.
<app asp-prerender-module="ClientApp/dist/main-server">Loading...</app>
asp-prerender-module Etiket Yardımcısı
Önceki kod örneğinde kullanılan asp-prerender-module
Etiket Yardımcısı, Node.jsaracılığıyla sunucuda ClientApp/dist/main-server.js
yürütür. Açıklık açısından, main-server
giriş noktası takma adını tanımlar; ve bu takma ad için bağımlılık grafiği geçişi ClientApp/boot-server.ts
dosyasında başlar.
entry: { 'main-server': './ClientApp/boot-server.ts' },
Aşağıdaki Angular örneğinde, ClientApp/boot-server.ts
dosyası Node.jsaracılığıyla sunucu işlemeyi yapılandırmak için createServerRenderer
npm paketinin RenderResult
işlevini ve aspnet-prerendering
türünü kullanır. Sunucu tarafı işlemeyi hedefleyen HTML işaretlemesi, kesin olarak türü belirlenmiş bir JavaScript Promise
nesnesine sarmalanan bir çözüm işlevi çağrısına geçirilir.
Promise
nesnesinin önemi, HTML işaretlemesini DOM'un yer tutucu öğesine eklenmek üzere sayfaya eşzamansız olarak sağlamasıdır.
import { createServerRenderer, RenderResult } from 'aspnet-prerendering';
export default createServerRenderer(params => {
const providers = [
{ provide: INITIAL_CONFIG, useValue: { document: '<app></app>', url: params.url } },
{ provide: 'ORIGIN_URL', useValue: params.origin }
];
return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {
const appRef = moduleRef.injector.get(ApplicationRef);
const state = moduleRef.injector.get(PlatformState);
const zone = moduleRef.injector.get(NgZone);
return new Promise<RenderResult>((resolve, reject) => {
zone.onError.subscribe(errorInfo => reject(errorInfo));
appRef.isStable.first(isStable => isStable).subscribe(() => {
// Because 'onStable' fires before 'onError', we have to delay slightly before
// completing the request in case there's an error to report
setImmediate(() => {
resolve({
html: state.renderToString()
});
moduleRef.destroy();
});
});
});
});
});
asp-prerender-data Etiket Yardımcısı
asp-prerender-module
Etiket Yardımcısı ile birlikte kullanıldığında, asp-prerender-data
görünümdeki Razor bağlamsal bilgileri sunucu tarafı JavaScript'e aktarmak için kullanılabilir. Örneğin, aşağıdaki işaretleme kullanıcı verilerini modüle main-server
geçirir:
<app asp-prerender-module="ClientApp/dist/main-server"
asp-prerender-data='new {
UserName = "John Doe"
}'>Loading...</app>
Alınan UserName
bağımsız değişken, yerleşik JSON seri hale getiricisi kullanılarak serileştirilir ve params.data
nesnesinde depolanır. Aşağıdaki Angular örneğinde veriler, bir h1
öğe içinde kişiselleştirilmiş bir karşılama oluşturmak için kullanılır:
import { createServerRenderer, RenderResult } from 'aspnet-prerendering';
export default createServerRenderer(params => {
const providers = [
{ provide: INITIAL_CONFIG, useValue: { document: '<app></app>', url: params.url } },
{ provide: 'ORIGIN_URL', useValue: params.origin }
];
return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {
const appRef = moduleRef.injector.get(ApplicationRef);
const state = moduleRef.injector.get(PlatformState);
const zone = moduleRef.injector.get(NgZone);
return new Promise<RenderResult>((resolve, reject) => {
const result = `<h1>Hello, ${params.data.userName}</h1>`;
zone.onError.subscribe(errorInfo => reject(errorInfo));
appRef.isStable.first(isStable => isStable).subscribe(() => {
// Because 'onStable' fires before 'onError', we have to delay slightly before
// completing the request in case there's an error to report
setImmediate(() => {
resolve({
html: result
});
moduleRef.destroy();
});
});
});
});
});
Etiket Yardımcıları'nda geçirilen özellik adları PascalCase gösterimiyle temsil edilir. JavaScript'te aynı özellik adlarının "camelCase" ile temsil edilmesine karşılık olarak. Bu fark, varsayılan JSON serileştirme yapılandırmasından sorumludur.
Yukarıdaki kod örneğini genişletmek için, işleve sağlanan özelliğin nemlendirilmesiyle veriler sunucudan globals
görünüme resolve
geçirilebilir:
import { createServerRenderer, RenderResult } from 'aspnet-prerendering';
export default createServerRenderer(params => {
const providers = [
{ provide: INITIAL_CONFIG, useValue: { document: '<app></app>', url: params.url } },
{ provide: 'ORIGIN_URL', useValue: params.origin }
];
return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {
const appRef = moduleRef.injector.get(ApplicationRef);
const state = moduleRef.injector.get(PlatformState);
const zone = moduleRef.injector.get(NgZone);
return new Promise<RenderResult>((resolve, reject) => {
const result = `<h1>Hello, ${params.data.userName}</h1>`;
zone.onError.subscribe(errorInfo => reject(errorInfo));
appRef.isStable.first(isStable => isStable).subscribe(() => {
// Because 'onStable' fires before 'onError', we have to delay slightly before
// completing the request in case there's an error to report
setImmediate(() => {
resolve({
html: result,
globals: {
postList: [
'Introduction to ASP.NET Core',
'Making apps with Angular and ASP.NET Core'
]
}
});
moduleRef.destroy();
});
});
});
});
});
postList
Nesnenin globals
içinde tanımlanan dizi, tarayıcının genel window
nesnesine eklenir. Genel kapsama alınan bu değişkenlerin "hoist" edilmesi, özellikle aynı verilerin öncelikle sunucuya ve ardından istemciye yüklenmesi işlemlerini azaltarak çaba tekrarını ortadan kaldırır.
Webpack Geliştirici Ara Yazılımı
Webpack Dev Ara Yazılımı , Webpack'in kaynakları isteğe bağlı olarak derlediği kolaylaştırılmış bir geliştirme iş akışı sunar. Ara yazılım, tarayıcıda bir sayfa yeniden yüklendiğinde istemci tarafı kaynaklarını otomatik olarak derler ve hizmet eder. Alternatif yaklaşım, bir üçüncü taraf bağımlılığı veya özel kod değiştiğinde projenin npm derleme betiği aracılığıyla Webpack'i el ile çağırmaktır. Dosyadaki package.json
bir npm derleme betiği aşağıdaki örnekte gösterilmiştir:
"build": "npm run build:vendor && npm run build:custom",
Webpack Geliştirme Ara Yazılımı önkoşulları
aspnet-webpack npm paketini yükleyin:
npm i -D aspnet-webpack
Webpack Geliştirme Ara Yazılımı yapılandırması
Webpack Dev Ara Yazılımı, dosyanın Startup.cs
yönteminde aşağıdaki kod aracılığıyla HTTP isteği işlem hattına Configure
kaydedilir:
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
// Call UseWebpackDevMiddleware before UseStaticFiles
app.UseStaticFiles();
UseWebpackDevMiddleware
uzantı yöntemi, statik dosya barındırmayı kaydetmeden önce UseStaticFiles
uzantı yöntemi aracılığıyla çağrılmalıdır. Güvenlik nedeniyle ara yazılımı yalnızca uygulama geliştirme modunda çalıştığında kaydedin.
Dosyanın webpack.config.js
output.publicPath
özelliği, ara yazılıma dist
klasöründeki değişiklikleri izlemesi için talimat verir:
module.exports = (env) => {
output: {
filename: '[name].js',
publicPath: '/dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
Sık Erişimli Modül Değiştirme
Webpack'in Sık Erişimli Modül Değiştirme (HMR) özelliğini Webpack Geliştirme Ara Yazılımının bir evrimi olarak düşünün. HMR tüm avantajları sunar, ancak değişiklikleri derledikten sonra sayfa içeriğini otomatik olarak güncelleştirerek geliştirme iş akışını daha da kolaylaştırır. Bunu tarayıcının yenilemesiyle karıştırmayın; bu, SPA'nın geçerli bellek içi durumu ve hata ayıklama oturumunu engeller. Webpack Geliştirme Ara Yazılımı hizmeti ile tarayıcı arasında canlı bağlantı vardır ve bu da değişikliklerin tarayıcıya gönderildiği anlamına gelir.
Anında Modül Değiştirme önkoşulları
Webpack-hot-middleware npm paketini yükleyin:
npm i -D webpack-hot-middleware
Sık Erişimli Modül Değiştirme yapılandırması
HMR bileşeni, Configure
yönteminde MVC'nin HTTP istek işlem hattına kaydedilmelidir.
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions {
HotModuleReplacement = true
});
Webpack Dev Ara Yazılımı'nda olduğu gibi, uzantı yöntemi diğer uzantı yönteminden önce çağrılmalıdır. Güvenlik nedeniyle ara yazılımı yalnızca uygulama geliştirme modunda çalıştığında kaydedin.
webpack.config.js
dosyası, boş bıraksa bile bir plugins
dizi tanımlamalıdır.
module.exports = (env) => {
plugins: [new CheckerPlugin()]
Uygulamayı tarayıcıda yükledikten sonra geliştirici araçlarının Konsol sekmesi HMR etkinleştirme onayı sağlar:
Yönlendirme yardımcıları
Çoğu ASP.NET Çekirdek tabanlı SPA'larda, sunucu tarafı yönlendirmeye ek olarak genellikle istemci tarafı yönlendirmesi de istenir. SPA ve MVC yönlendirme sistemleri, müdahale olmadan bağımsız olarak çalışabilir. Ancak zorluklara neden olan bir uç durum vardır: 404 HTTP yanıtını tanımlama.
Uzantısız bir yolun kullanıldığı senaryoyu /some/page
göz önünde bulundurun. İsteğin bir sunucu tarafı rotası ile eşleşmediği, ancak deseninin bir istemci tarafı rotası ile eşleştiğini varsayalım. Şimdi, genellikle sunucuda bir görüntü dosyası bulmayı bekleyen bir istek için gelen isteği /images/user-512.png
göz önünde bulundurun. İstenen kaynak yolu herhangi bir sunucu tarafı yolu veya statik dosyayla eşleşmiyorsa, istemci tarafı uygulamasının bunu işleme olasılığı düşüktür; genellikle 404 HTTP durum kodu döndürülmesi istenir.
Yönlendirme yardımcıları önkoşulları
İstemci tarafı yönlendirme npm paketini yükleyin. Örnek olarak Angular'ın kullanılması:
npm i -S @angular/router
Yönlendirme yardımcıları yapılandırması
yönteminde MapSpaFallbackRoute
adlı Configure
bir uzantı yöntemi kullanılır:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
Yollar, yapılandırıldıkları sırayla değerlendirilir. Sonuç olarak, default
önceki kod örneğindeki yol önce desen eşleştirme için kullanılır.
Yeni proje oluşturma
JavaScript Hizmetleri önceden yapılandırılmış uygulama şablonları sağlar. SpaServices bu şablonlarda Angular, React ve Redux gibi farklı çerçeveler ve kitaplıklarla birlikte kullanılır.
Bu şablonlar aşağıdaki komutu çalıştırarak .NET CLI aracılığıyla yüklenebilir:
dotnet new --install Microsoft.AspNetCore.SpaTemplates::*
Kullanılabilir SPA şablonlarının listesi görüntülenir:
Şablonlar | Kısa Ad | Dil | Etiketler |
---|---|---|---|
MVC ASP.NET Core ve Angular | açısal | [C#] | Web/MVC/SPA |
React.js ile MVC ASP.NET Core | Tepki | [C#] | Web/MVC/SPA |
React.js ve Redux ile MVC ASP.NET Core | reactredux | [C#] | Web/MVC/SPA |
SPA şablonlarından birini kullanarak yeni bir proje oluşturmak için dotnet new komutuna şablonun Kısa Adını ekleyin. Aşağıdaki komut, sunucu tarafı için yapılandırılmış ASP.NET Core MVC ile bir Angular uygulaması oluşturur:
dotnet new angular
Çalışma zamanı yapılandırma modunu ayarlama
İki birincil çalışma zamanı yapılandırma modu vardır:
-
Geliştirme:
- Hata ayıklamayı kolaylaştırmak için kaynak eşlemeleri içerir.
- İstemci tarafı kodunu performans için iyileştirmez.
-
Üretim:
- Kaynak eşlemeleri içermez.
- Paketleme ve küçültme yoluyla istemci tarafı kodunu iyileştirir.
ASP.NET Core, yapılandırma modunu depolamak için adlı ASPNETCORE_ENVIRONMENT
bir ortam değişkeni kullanır. Daha fazla bilgi için bkz . Ortamı ayarlama.
.NET CLI ile çalıştırma
Proje kökünde aşağıdaki komutu çalıştırarak gerekli NuGet ve npm paketlerini geri yükleyin:
dotnet restore && npm i
Uygulamayı derleyin ve çalıştırın:
dotnet run
Uygulama, çalışma zamanı yapılandırma moduna göre localhost'ta başlar. Tarayıcıda http://localhost:5000
adresine gidildiğinde giriş sayfası görüntülenir.
Visual Studio 2017 ile çalıştırma
.csproj
dotnet new komutu tarafından oluşturulan dosyayı açın. Gerekli NuGet ve npm paketleri proje açıldığında otomatik olarak geri yüklenir. Bu geri yükleme işlemi birkaç dakika kadar sürebilir ve uygulama tamamlandığında çalışmaya hazırdır. Yeşil çalıştırma düğmesine tıklayın veya tuşuna basın Ctrl + F5
; tarayıcı uygulamanın giriş sayfasında açılır. Uygulama, çalışma zamanı yapılandırma moduna göre localhost üzerinde çalışır.
Uygulamayı test etme
SpaServices şablonları Karma ve Jasmine kullanarak istemci tarafı testleri çalıştırmak için önceden yapılandırılmıştır. Jasmine, JavaScript için popüler bir birim testi çerçevesidir, Karma ise bu testler için bir test çalıştırıcısıdır. Karma, Webpack Geliştirici Ara Yazılımı ile çalışacak şekilde yapılandırılır, böylece geliştiricinin her değişiklik yapıldığında testi durdurması ve çalıştırması gerekmez. İster test çalışmasına karşı çalışan kod ister test çalışmasının kendisi olsun, test otomatik olarak çalışır.
Angular uygulamasını örnek kullanarak, CounterComponent
dosyasındaki counter.component.spec.ts
için iki Jasmine test vakası zaten sağlanmıştır.
it('should display a title', async(() => {
const titleText = fixture.nativeElement.querySelector('h1').textContent;
expect(titleText).toEqual('Counter');
}));
it('should start with count 0, then increments by 1 when clicked', async(() => {
const countElement = fixture.nativeElement.querySelector('strong');
expect(countElement.textContent).toEqual('0');
const incrementButton = fixture.nativeElement.querySelector('button');
incrementButton.click();
fixture.detectChanges();
expect(countElement.textContent).toEqual('1');
}));
ClientApp dizininde komut istemini açın. Şu komutu çalıştırın:
npm test
Betik, karma.conf.js
dosyasındaki tanımlanan ayarları okuyan Karma test çalıştırıcısını başlatır. Diğer ayarlar arasında, karma.conf.js
dizisi aracılığıyla files
yürütülecek test dosyalarını tanımlar:
module.exports = function (config) {
config.set({
files: [
'../../wwwroot/dist/vendor.js',
'./boot-tests.ts'
],
Uygulamayı yayımlayın
Azure'da yayımlama hakkında daha fazla bilgi için bu GitHub sorununa bakın.
Oluşturulan istemci tarafı varlıklarını ve yayımlanan ASP.NET Core yapıtlarını dağıtıma hazır bir pakette birleştirmek zahmetli olabilir. Neyse ki, SpaServices bu yayın işleminin tamamını adlı RunWebpack
özel bir MSBuild hedefiyle düzenler:
<Target Name="RunWebpack" AfterTargets="ComputeFilesToPublish">
<!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
<Exec Command="npm install" />
<Exec Command="node node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js --env.prod" />
<Exec Command="node node_modules/webpack/bin/webpack.js --env.prod" />
<!-- Include the newly-built files in the publish output -->
<ItemGroup>
<DistFiles Include="wwwroot\dist\**; ClientApp\dist\**" />
<ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
<RelativePath>%(DistFiles.Identity)</RelativePath>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</ResolvedFileToPublish>
</ItemGroup>
</Target>
MSBuild hedefi aşağıdaki sorumluluklara sahiptir:
- npm paketlerini geri yükleyin.
- Üçüncü taraf, istemci tarafı varlıkların üretim sınıfı bir derlemesini oluşturun.
- Özel istemci tarafı varlıklarının üretime hazır derlemesini oluşturun.
- Webpack tarafından oluşturulan varlıkları yayımlama klasörüne kopyalayın.
MSBuild hedefi çalıştırılırken çağrılır:
dotnet publish -c Release
Ek kaynaklar
ASP.NET Core