سفارشی سازی صفحه‌ی اول برنامه‌های Angular CLI توسط ASP.NET Core
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: پنج دقیقه

در مطلب «Angular CLI - قسمت پنجم - ساخت و توزیع برنامه» با نحوه‌ی ساخت و توزیع برنامه‌های Angular، در دو حالت محیط توسعه و محیط ارائه‌ی نهایی آشنا شدیم. همچنین در مطلب «یکپارچه سازی Angular CLI و ASP.NET Core در VS 2017» نحوه‌ی ترکیب یک برنامه‌ی ASP.NET Core و Angular را بررسی کردیم. در اینجا می‌خواهیم فایل index.html ایی را که Angular CLI تولید می‌کند، با فایل Layout برنامه‌های ASP.NET Core جایگزین کنیم؛ تا بتوانیم در صورت نیاز، سفارشی سازی‌های بیشتری را به صفحه‌ی اول سایت اعمال نمائیم.


استفاده از Tag Helpers ویژه‌ی ASP.NET Core برای مدیریت محیط‌های توسعه و تولید

فایل‌های برنامه‌ی تک صفحه‌ای تولید شده‌ی توسط Angular CLI، در نهایت یک چنین شکلی را خواهند داشت:


این فایل‌ها نیز در حالت توسعه تهیه شده‌اند. در یک برنامه‌ی واقعی، صفحه‌ی ساده‌ی index.html تولیدی آن، تنها می‌تواند یک قالب شروع به کار باشد و نه فایل نهایی که قرار است ارائه شود. نیاز است به این فایل تگ‌های بیشتری را اضافه کرد و سفارشی سازی‌های خاصی را به آن اعمال نمود. در این حالت با توجه به بازنویسی و تولید مجدد این فایل در هر بار ساخت برنامه، می‌توان از فایل Layout پروژه‌ی ASP.NET Core جاری استفاده کرد. به این ترتیب از مزایای Razor و تمام زیرساختی که در اختیار داریم نیز محروم نخواهیم شد.
بنابراین تنها کاری را که باید انجام دهیم، کپی ساختار فایل index.html تولیدی به فایل Layout برنامه است.

مشکل! در حالت توسعه، نام فایل‌های تولید شده به همین سادگی است که ملاحظه می‌کنید. اما در حالت ارائه‌ی نهایی، این فایل‌ها به همراه یک هش نیز تولید می‌شوند (پیاده سازی مفهوم cache busting و اجبار به به‌روز رسانی کش مرورگر، باتوجه به تغییر آدرس فایل‌ها)؛ مانند vendor.ea3f8329096dbf5632af.bundle.js

راه حل اول: تولید فایل‌های نهایی بدون هش
 ng build -prod --output-hashing=none
در حین ساخت و تولید یک برنامه‌ی Angular CLI در حالت ارائه‌ی نهایی، تنها کافی است سوئیچ output-hashing، به none تنظیم شود، تا این هش‌ها به نام فایل‌های تولیدی اضافه نشوند.
درکل بهتر است از این روش استفاده نشود، چون با وجود پروکسی‌های کش کردن اطلاعات در بین راه، احتمال اینکه کاربران نگارش‌های قدیمی برنامه را مشاهده کنند، بسیار زیاد است.

راه حل دوم: تگ Script در ASP.NET Core اجازه‌ی ذکر تمام فایل‌های اسکریپت یک پوشه را نیز می‌دهد
 <script type="text/javascript" asp-src-include="*.js"></script>
هرچند این قابلیت جالب است و سبب الحاق یکجای تمام فایل‌های js موجود در پوشه‌ی wwwroot خواهد شد، اما پاسخگوی کار ما نخواهد بود؛ چون ترتیب قرارگیری این فایل‌ها مهم است.

راه حل واقعی
در اینجا کدهای کامل فایل Views\Shared\_Layout.cshtml را که می‌تواند جایگزین فایل index.html تولیدی توسط Angular CLI باشد، ملاحظه می‌کنید:
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="icon" type="image/x-icon" href="favicon.ico">
    <title>ng2-lab</title>
    <base href="/">

    <environment names="Development">
    </environment>
    <environment names="Staging,Production">
        <link rel="stylesheet" asp-href-include="~/styles*.css" />
    </environment>
</head>
<body>
    @RenderBody()

<app-root></app-root>
<environment names="Development">
    <script type="text/javascript" src="/inline.bundle.js"></script>
    <script type="text/javascript" src="/polyfills.bundle.js"></script>
    <script type="text/javascript" src="/scripts.bundle.js"></script>
    <script type="text/javascript" src="/styles.bundle.js"></script>
    <script type="text/javascript" src="/vendor.bundle.js"></script>
    <script type="text/javascript" src="/main.bundle.js"></script>
</environment>
<environment names="Production,Staging">
    <script type="text/javascript" asp-src-include="~/inline*.js"></script>
    <script type="text/javascript" asp-src-include="~/polyfills*.js"></script>
    <script type="text/javascript" asp-src-include="~/scripts*.js"></script>
    <script type="text/javascript" asp-src-include="~/vendor*.js"></script>
    <script type="text/javascript" asp-src-include="~/main*.js"></script>
</environment>
</body>
</html>
در اینجا دو حالت توسعه و همچنین ارائه‌ی نهایی مدنظر قرار گرفته‌اند. در حالت توسعه، دقیقا از همان نام‌های ساده‌ی تولیدی استفاده شده‌است و در حالت ارائه‌ی نهایی چون نام فایل‌ها به صورت
[name].[hash].bundle.js
تولید می‌شوند، می‌توان قسمت هش را با * جایگزین کرد؛ مانند "asp-src-include="~/vendor*.js
همچنین باید دقت داشت که در حالت توسعه، تمام شیوه نامه‌های برنامه در فایل styles.bundle.js قرار می‌گیرند. اما در حالت ارائه‌ی نهایی، این فایل وجود نداشته و با نام کلی styles*.css تولید می‌شود که باید در head صفحه قرار گیرد (مانند تنظیمات حالت تولید در Layout فوق).


اصلاح قسمت URL Rewrite برنامه

در حالت کار با برنامه‌های تک صفحه‌ای وب، در اولین درخواست رسیده‌ی به برنامه ممکن است آدرسی درخواست شود که معادل کنترلر و اکشن متدی را در برنامه‌ی سمت سرور نداشته باشد. در این حالت کاربر را به همان صفحه‌ی index.html هدایت می‌کنیم تا سیستم مسیریابی سمت کلاینت، کار نمایش آن صفحه را انجام دهد:
app.Use(async (context, next) =>
{
    await next();
    var path = context.Request.Path.Value;
    if (path != null &&
        context.Response.StatusCode == 404 &&
        !Path.HasExtension(path) &&
        !path.StartsWith("/api/", StringComparison.OrdinalIgnoreCase))
        {
            context.Request.Path = "/index.html";
            await next();
        }
});
از آنجائیکه پس از اصلاحات فوق دیگر از این فایل استفاده نمی‌شود، باید تغییر ذیل را نیز اعمال کرد:
 //context.Request.Path = "/index.html";
context.Request.Path = "/"; // since we are using views/shared/_layout.cshtml now.


کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید.
  • #
    ‫۷ سال و ۱ ماه قبل، یکشنبه ۲۹ مرداد ۱۳۹۶، ساعت ۱۰:۰۴
    در پروژه سفارشی سازی DNTIdentity  اومدید برای پیاده سازی دسترسی‌ها و نمایش منو‌ها به کاربر از تگ هلپر  SecurityTrimming   استفاده کردین  توی همون پروژه اگه بخوایم همچین چیزی رو با انگولار پیاده سازی کنیم پیشنهادتون چیه ؟ استفاده کردن تگ هلپر در انگولار مثل این پروژه https://github.com/RobertDyball/A2SPA   ( تو readme  لینکاشو نگاه کنید) یا روش دیگه ای سراغ دارین؟
    توی همین پروژه DNTIdentity توی پارشیال ویو _UserMenu.cshtml   با razor اومدید  @inject IUsersPhotoService PhotoService
    @{
        var displayName = User.Identity.GetUserDisplayName();
        var photoUrl = PhotoService.GetCurrentUserPhotoUrl();
    }
     displayName کاربری که لاگین کرده رو گرفتید برای همچین کاری تو angular چیکار باید کرد؟ ممنون
  • #
    ‫۶ سال و ۱۲ ماه قبل، دوشنبه ۳ مهر ۱۳۹۶، ساعت ۱۴:۳۶
    آیا پس از توزیع یک برنامه آنگولار تک صفحه ای صرفا با اجرای index.html در مرورگر بدون نیاز به وب سرور ( در مواردی مانند web api که داده‌ها یه صورت json و از راه دور تامین می‌شوند ) مشکلی نخواهد بود و مواردی مانند مسیریابی صرفا توسط جاوا اسکریپت هندل خواهند شد ؟
    • #
      ‫۶ سال و ۱۲ ماه قبل، دوشنبه ۳ مهر ۱۳۹۶، ساعت ۱۴:۴۲
      «... بدون نیاز به وب سرور ...»
      به یک حداقل وب سروری نیاز دارد. برای مثال دستور ng serve -o یک وب سرور آزمایشی را بر روی پورت 4200 ایجاد می‌کند؛ برای اجرا و ارائه‌ی برنامه. اجرای مستقیم index.html بدون وب سرور، یعنی پروتکل //:file و این پروتکل دسترسی محدودی را برای اجرای هر نوع برنامه‌ی وب و یا بارگذاری فایل‌ها را در مرورگر دارد. به همین جهت به پروتکل //:http نیاز خواهید داشت و بله ... این مورد هیچ نوع وابستگی به نوع وب سرور ندارد. همینقدر که توانایی پردازش پروتکل http را داشته باشد کافی است.

      «... مواردی مانند مسیریابی ...»
      در این مورد مفصل در سری مسیریابی برنامه‌های Angular بحث شده‌است و دو قسمت تنظیمات سمت سرور و سمت کلاینت را به همراه دارد.
  • #
    ‫۶ سال و ۴ ماه قبل، یکشنبه ۱۶ اردیبهشت ۱۳۹۷، ساعت ۱۷:۳۶
    یک نکته‌ی تکمیلی
    فایل Views\Shared\_Layout.cshtml در نگارش 6، یک چنین شکلی را پیدا می‌کند.