نحوه ساخت یک اپلیکیشن Angular 4 با ویژوال استودیو 2017

در این مقاله درباره ی نحوه ساخت یک اپلیکیشن Angular 4 با استفاده از ویژوال استودیو 2017 و چگونگی توسعه آن با یک مثال ساده صحبت خواهیم کرد.

نحوه ساخت یک اپلیکیشن Angular 4 با ویژوال استودیو 2017

پیکربندی و ایجاد اپلیکیشن های انگولار با ویژوال استودیو ساده نیست زیرا نیاز به برخی تنظیمات پیکربندی دستی و اضافه کردن بعضی فایل های .config می باشدخیلی خوب میشود اگریک قالب آماده استفاده داشته باشید داشتن یک قالب آماده باعث می شود از این دردسر راحت شوید و در زمان صرفه جویی کنید.با استفاده از ویژوال استودیو 2017، یک قالب برای ایجاد و اجرای  نمونه ی اپلیکیشن انگولار در دسترس است .این قالب به اندازه ی کافی خوب است که شما کار با انگولار را شروع کنید.

ابتدا شما باید نرم افزار های مورد نیاز را نصب کنید.

Node.js

.NET Core 2.0

Visual Studio 2017 Community (اگر نصب کرده اید ، پس فقط آن را به ورژن 15.4.2  آپدیت کنید)

ویژوال استودیو 2017 را باز کنید به قسمت File->New Project -> Select ASP.NET Core Web Application بروید .نام پروژه و مسیر جایی که می خواهید این پروژه را ایجاد کنید را انتخاب کنید سپس ok را بزنید.

در پنجره ی باز شده Angular را انتخاب کنید سپس ok را بزنید . ویژوال استودیو یک پروژه ASP.NET Core 2.0 با کانفیگ Angular 4 برای شما خواهد ساخت . شما باید ساختار پروژه زیر را ببینید.

ساختار پروژه با پوشه های controller ، View و wwwroot آشنا بنظر می رسد .  پوشه ی ClientApp حاوی Angular میباشد . شما همچنین می توانید webpack.config.js را درروت پروژه ببینید که این فایل بیانگر این است که webpack در این پروژه به عنوان module bundler استفاده میشود . این فایل webpack را درباره ی چگونگی bundle کردن کد کلاینت  راهنمایی می کند.

قبل از پرداختن به کد ، مهم است که به نکاتی توجه کنیم . این نمونه کد از JavaScriptServices برای ایجاد برنامه ی تک صفحه ای (single page application)  با ASP.NET Core استفاده میکند . JavaScriptServices  یک مجموعه ای از تکنولوژی های سمت کلاینت برای ASP.NET Core می باشد و هدفش این است که ASP.NET Core را عنوان پلت فرم سمت سرور برای ساختن SPA ها قرار دهد و هم چنین شامل پشتیبانی برای فریم ورک های سمت کلاینت می باشد – Angular ، Aurelia ، knockout.js ، React ، React + Redux و Vue.js

آشنایی با JavaScriptServices

این سرویس شامل سه ناگت پکیج منفاوت است

Microsoft.AspNetCore.NodeServices (NodeServices) :

به شما امکان اجرای JavaScript (در محیط Node.js ) روی سرور را میدهد . حتی شما میتوانید از پکیج های NPM  در زمان اجرا در برنامه .Net Core خود استفاده کنید

Microsoft.AspNetCore.SpaServices (SpaServices) :یک پلت فرم سمت سرور برای ساختن SPA ها ارائه میدهد . این پکیج حاوی ابزار های ضروری برای مدیریت prerendering سمت سرور ، پشتیبانی webpack middleware ، Hot Module Replacement و راهنمای مسیریابی (routing) برای همگام سازی مسیر های سمت کلاینت با مسیر سرور

Microsoft.AspNetCore.SpaTemplates (SpaTemplates) : این پکیج قالب های SPA (single page application) برای ASP.NET Core ارائه میدهد

همه ی این پکیج ها به عنوان بخشی از پکیج Microsoft.AspNetCore.All به برنامه شما اضافه شده اند. این متا پکیج در ASP.NET Core 2.0 معرفی شد

حال به سراغ بعضی از خطوط مهم کد میرویم تا ببینیم چگونه کار میکند . ابتدا ، Startup.cs باز کنید و به متد configure() نگاه کنید . دراین متد چند نکته وجود دارد

اول :

app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
    HotModuleReplacement = true
});

کد بالا WebpackDevMiddleware را در پایپ لاین درخواست HTTP رجیستر میکند . همان طور که می دانید webpack یک module bundler است و برای ساختن و bundle منابع سمت کلاینت استفاده می شود . به طور عادی ، یکی باید webpack را در خط فرمان برای bundle کردن چیز ها اجرا کند اما با این middleware همه ی این فرایند بصورت خودکار انجام می شود و نیاز نیست که شما نگران چیزی باشید در این جا  HotModuleReplacmentروی true گذاشته شده است

“Hot Module Replacement” (HMR) یک ویژگی برای تزریق ماژول های آپدیت شده درactive runtime (زمان اجرای فعال) است . بنابراین هر تغییری که در سمت کلاینت انجام شده است فورا اثر ان تغییر در مرورگر ،  بدون ریستارت کردن برنامه یا رفرش مرورگر ، دیده می شود

قطعه ی بعدی کد مربوط به مسیریابی(routing) است . همه ی ما با MapRoute() برای کانفیگ مسیریابی در ASP.NET Core MVC آشنا هستیم . متد جدید در این جا MapSpaFallbackRoute() می باشد . MapSpaFallbackRoute()  برای مدیریت مسیریابی سمت کلاینت می باشد .

اگر در خواست ، با هیچ کدام از فایل های استاتیک و MVC Controller یکی نباشد پس بدین معنی است که برای برنامه سمت کلاینت است (البته نه همیشه). به عبارت دیگر ، این سرور را  قادر میسازد که هر درخواستی که برای روتر انگولار است را مدیریت کند و در ازای آن درخواست یک اپلیکیشن انگولار را به مرورگر بر میگرداند . زمانی که اپلیکیشن در مرورگر بار گذاری می شود ، انگولار کنترل مسیر URL را بر عهده میگیرد

app.UseStaticFiles();
app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");

    routes.MapSpaFallbackRoute(
        name: "spa-fallback",
        defaults: new { controller = "Home", action = "Index" });
});

در اینجا ، MapSpaFallbackRoute همچنین ایندکس HomeController را مشخص می کند (مانند  MapRoute())

بنظر میرسد هر دوی آن ها کار یکسانی را انجام می دهند پس تفاوتشان کجاست ؟

MapRoute() مسیر پیش فرض را برای MVC application معین میکند و MapSpaFallbackRoute همیشه به HomeController اشاره می کند

سپس ، index.cshtml که در پوشه ی Home قرار دارد را باز کنید ، شما کد زیر را میبینید.

<app asp-prerender-module="ClientApp/dist/main-server">Loading...</app>

تگ هلپر asp-prerender-module برای مشخص کردن این که کدام ماژول رندر شود استفاده میشود (در این جا ClientApp/dist/main-server). این pre-rendering سمت سرور برنامه های SPA کلاینت را فعال میکند . شما باید فایل main-server.js در ClientApp/dist ببینید. این فایل یک نقطه ی ورود به برنامه انگولار است و توسط Node.js اجرا میشود و برای رندر js روی سرور ، قبل ازتزریق آن در response ، استفاده می شود.

Webpack یک نقطه ی ورود با نام مستعار main-server با مقدار فایل  “ClientApp/boot-server.ts”تعریف میکند . شما می توانید این  webpack.config.js را پیدا کنید. Boot – server.ts دارای تابع createServerRenderer برای کانفیگ رندر در سمت سرور و برگرداندن HTML به مرورگر می باشد . شما می توانید نسخه انگولار را در فایل package.json ببینید . در این مثال ما نسخه 4.2.5 می باشد

"@angular/core": "4.2.5",

 بیایید برنامه را اجرا کنیم پس از اجرا شما باید در مرورگر خود تصویر زیر را ببینید

شما می توانید ایتم های منو را با ساختار برنامه انگولار چک کنید. حال بیایید این پروژه را کمی توسعه بدهیم . در این جا کامپوننت fetch data یک API را برای بدست آوردن پیش بینی تصادفی آب و هوا صدا میزند

حال بیایید یک dropdown بالای این گرید برای فیلتر داده ها بر اساس مقدار انتخاب شده ، اضافه کنیم. در زیر کد API برای برگرداندن خلاصه ی پیش بینی وضعیت آب و هوایی وجود دارد. API جدید اضافه شده به نمونه کد، GetSummaries() نام دارد.

private static string[] Summaries = new[]
{
     "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

[HttpGet("[action]")]
public string[] GetSummaries()
{
    return Summaries;
}

در قدم بعدی کد اپدیت شده ی  fetchdata.component.ts را داریم .حال کانستراکتور(سازنده) ، GetSummaries را ، همراه با API ، WeatherForecasts صدا می زند. همچنین یک متد به نام filterForeCasts تعریف شده است که در هنگام رویداد تغییر dropdown ، صدا زده می شود . این متد لیست پیش بینی ها را بر اساس مقدار انتخاب شده فیلتر میکند و سپس نتیجه را بر می گرداند

import { Component, Inject } from '@angular/core';
import { Http } from '@angular/http';

@Component({
    selector: 'fetchdata',
    templateUrl: './fetchdata.component.html'
})
export class FetchDataComponent {
    public forecasts: WeatherForecast[];
    public cacheForecasts: WeatherForecast[];
    public summaries: any[];

    constructor(http: Http, @Inject('BASE_URL') baseUrl: string) {
        http.get(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => {
            this.forecasts = result.json() as WeatherForecast[];
            this.cacheForecasts = this.forecasts;
        }, error => console.error(error));
        http.get(baseUrl + 'api/SampleData/GetSummaries').subscribe(result => {
            this.summaries = result.json() as any[];
        }, error => console.error(error));
    }

    filterForeCasts(filterVal: any) {
        if (filterVal == "0")
            this.forecasts = this.cacheForecasts;
        else
        this.forecasts = this.cacheForecasts.filter((item) => item.summary == filterVal);
    }
}

interface WeatherForecast {
    dateFormatted: string;
    temperatureC: number;
    temperatureF: number;
    summary: string;
}

interface Summary {
    name: string;
}

و در آخر ، این HTML را در fetchdata.component.html قرار دهید تا خلاصه dropdown را نشان دهد

<div>
    <label>Summary: </label>
    <select (change)="filterForeCasts($event.target.value)">
        <option value="0">--All--</option>
        <option *ngFor="let summary of summaries" value={{summary}}>
            {{summary}}
        </option>
    </select>
</div>

برنامه را اجرا کنید و fetch data را انتخاب کنید . می توانید dropdown را ببینید که حاوی لیستی از همه ی خلاصه هاست. تغییر انتخاب dropdown  ، باعث بروز رسانی گرید پیش بینی وضعیت آب و هوا می شود

نتیجه گیری
ASP.NET Core  و Angular یک تجربه کاملا جدید در زمینه توسعه وب است و توسط ASP.NET Core JavaScriptServices و Webpack برای bundling پشتیبانی می شود.رندرینگ انگولار بر روی سرور دارای مزایایی مثل عملکرد بهتر ، بهینه سازی SEO ، ارسال سریع و ایمن محتوی به مرورگر میباشد.این پست درباره ی تفاوت پکیج های ناگت JavaScriptServices و درباره ی چگونگی pre-render شدن انگولار روی سرور صحبت می کند . همچنین وجود WebpackDevMiddleware و HMR بسیار عالی است زیرا باعث می شود پردازش webpack بصورت خودکار انجام شود.