Blazor 5x - قسمت 34 - توزیع برنامه‌های Blazor بر روی IIS
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: چهار دقیقه

زمانیکه صحبت از توزیع برنامه‌های Blazor بر روی IIS است، عموما تنظیمات مرتبط با برنامه‌های Blazor Server و یا Hosted Blazor Apps که همان ترکیب WASM+Web API هستند، مطرح است؛ در غیراینصورت اگر برنامه‌ای صرفا از فایل‌های Blazor WASM تشکیل شده باشد، توزیع آن حتی بر روی صفحات static مربوط به GitHub هم میسر است و وابستگی خاصی به سروری ندارند. بنابراین در اینجا بیشتر هدف تنظیمات IIS مرتبط با قسمت ASP.NET Core این برنامه‌ها است و این مورد را پیشتر در مطلب «ارتقاء به ASP.NET Core 1.0 - قسمت 22 - توزیع برنامه توسط IIS» بررسی کرده‌ایم و نکته‌ی اضافه‌تری را به همراه ندارد.


مروری بر نحوه‌ی توزیع برنامه‌های Blazor بر روی IIS

1- پیش از هر کاری باید مطابق نگارش ASP.NET Core در حال استفاده (که به عنوان هاست Blazor Server و یا ارائه دهنده‌ی قسمت Web API برنامه‌ی سمت کلاینت WASM مطرح است)، بسته‌ی NET Core hosting bundle. را نصب کرد که عموما تحت عنوان «Hosting Bundle Installer» قابل دریافت است.
نکته‌ی مهم: همانند تمام نگارش‌های دات نت، در اینجا نیز باید Hosting Bundle را پس از نصب IIS، بر روی سیستم نصب کرد. اگر این ترتیب تغییر کند، یکبار دیگر نصاب آن‌را اجرا کرده و گزینه‌ی ترمیم نصب را انتخاب کنید تا یکپارچگی آن با IIS صورت گیرد.

2- نیاز است برنامه‌ی خود را اصطلاحا publish کرد تا به همراه فایل‌های نهایی قابل کپی باشد که در پوشه‌ای توسط IIS هاست خواهند شد. برای اینکار اگر از نگارش کامل ویژوال استودیو استفاده می‌کنید، فقط کافی است بر روی پروژه‌ی مدنظر کلیک راست کرده و از منوی باز شده، گزینه‌ی publish را انتخاب کنید و مراحل آن‌را طی نمائید و یا این مراحل را می‌توان توسط دستور خط فرمان زیر نیز خلاصه کرد که وابستگی خاصی، به IDE ویژه‌ای ندارد و چند سکویی است:
dotnet publish -o "c:\dir1\dir2" -c Release
این دستور، کار Build و توزیع پروژه را در پوشه‌ای که مشخص شده انجام می‌دهد. همچنین برای حالت build، نوع release را انتخاب می‌کند که به همراه بهینه سازی‌های بسیاری به همراه کاهش حجم نهایی فایل‌ها نیز هست.
و یا اگر فقط دستور dotnet publish -c Release را در ریشه‌ی پروژه اجرا کنیم، خروجی نهایی را در پوشه‌ی bin\Release\net5.0\publish می‌توان مشاهده کرد که به همراه یک web.config مخصوص برنامه‌های blazor هم هست و در آن mime typeهای متناظری، به همراه URL rewriting مناسب برنامه‌های تک صفحه‌ای وب از پیش تنظیم شده‌است. بنابراین در اینجا نصب ماژول URL rewrite بر روی IIS نیز الزامی است.

3- در اینجا نیز همانند تنظیمات برنامه‌های ASP.NET Core، باید application pool منتسب به برنامه را ویرایش کرده و NET Clr Version. آن‌را بر روی No Managed Code قرار داد.


روش فعالسازی توزیع مبتنی بر فشرده سازی Brotli در IIS

در حین عملیات publish استاندارد، به صورت پیش‌فرض از تمام فایل‌ها، سه نسخه‌ی اصلی، gz شده (gzip) و یا br شده (فشرده سازی Brotli که فایل‌های کم حجم‌تری را نسبت به gz ارائه می‌دهد) نیز تهیه می‌شوند که بسته به نوع مرورگر و پشتیبانی آن از روش‌های مختلف فشرده سازی، یکی از آن‌ها در اختیار کلاینت قرار خواهد گرفت که به این صورت کاربران، تجربه‌ی دریافت کم حجم‌تر و سریعتری را خواهند داشت.


باید دقت داشت Web.config ای که به همراه دستور dotnet publish ایجاد می‌شود، روش توزیع پیش‌فرض فایل‌های br. تولیدی را ندارد. برای اینکار نیاز است تنظیمات این فایل web.config توصیه شده‌ی توسط تیم Blazor را به web.config خود اضافه کرد تا در نهایت حجم دریافتی از سرور به شدت کاهش یابد.

یک نکته: اگر می‌خواهید فایل web.config سفارشی خودتان را داشته باشید، نمونه‌ای از آن‌را در ریشه‌ی پروژه قرار داده و سپس فایل csproj را به نحو زیر ویرایش کنید تا از آن در حین publish استفاده کند:
<PropertyGroup>
    <PublishIISAssets>true</PublishIISAssets>
</PropertyGroup>


در حین publish برنامه‌های Blazor WASM کار IL trimming نیز انجام می‌شود

برای کاهش حجم نهایی برنامه‌های Blazor WASM، در حین publish در حالت release، کار IL Trimming نیز به صورت خودکار انجام می‌شود تا کدهای IL ای که در برنامه نقش نداشته‌اند و مستقیما در جائی استفاده نشده‌اند، به صورت خودکار حذف شوند و به این ترتیب حجم ارائه‌ی نهایی به شدت کاهش یابد.
فقط باید دقت داشت که در این حالت اگر عملیات پویایی مانند reflection در کدهای شما صورت می‌گیرد، به علت نداشتن ارجاع استاتیکی به منابع مورد استفاده، در زمان اجرا با مشکل مواجه خواهد شد. اگر می‌خواهید اخطارهایی را در این زمینه مشاهده کنید، گزینه‌ی زیر را به فایل csproj اضافه نمائید:
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>


حذف مباحث بومی سازی در صورت عدم نیاز


اگر در برنامه‌ی خود از مباحث time-zones استفاده نمی‌کنید، می‌توانید با غیرفعال کردن آن در فایل csproj، حداقل 100 کیلوبایت از حجم برنامه‌ی نهایی را کاهش دهید:
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
و یا اگر نمی‌خواهید خروجی‌های تاریخ و یا مقادیر، بر اساس فرهنگ بومی کاربر تطابق پیدا کنند، می‌توانید invariant culture را فعال کنید:
<InvariantGlobalization>true</InvariantGlobalization>
  • #
    ‫۳ سال و ۴ ماه قبل، سه‌شنبه ۷ اردیبهشت ۱۴۰۰، ساعت ۱۸:۲۰
    یک نکته‌ی تکمیلی: چگونه می‌توان بررسی کرد که آیا مرورگر جاری از Web Assembly پشتیبانی می‌کند یا خیر؟
    function isWasmSupported() {
        try {
            if (typeof WebAssembly === "object"
                && typeof WebAssembly.instantiate === "function") {
                const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));
                if (module instanceof WebAssembly.Module)
                    return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
            }
        } catch (e) {
        }
        return false;
    }
      
    if(!isWasmSupported()) { 
      alert("WebAssembly is not available in your browser. Please try using the latest version of Chrome, Firefox, Edge or Safari.");
    }
    ماخذ
  • #
    ‫۳ سال و ۴ ماه قبل، سه‌شنبه ۷ اردیبهشت ۱۴۰۰، ساعت ۱۸:۳۷
    یک نکته‌ی تکمیلی: چگونه برنامه‌های blazor server را پس از برقراری ارتباط قطع شده، به صورت خودکار راه‌اندازی مجدد کنیم؟
    [_Host.cshtml]
    
    <script src="_framework/blazor.server.js"></script>
    <script>
    window.Blazor.defaultReconnectionHandler.onConnectionDown = function () {
         setTimeout(function () {
                 location.reload();
         }, 7000);
    }
    
    window.Blazor.defaultReconnectionHandler._reconnectCallback = function (d) {
        document.location.reload();
    }
    </script>
  • #
    ‫۳ سال و ۴ ماه قبل، سه‌شنبه ۷ اردیبهشت ۱۴۰۰، ساعت ۱۹:۲۵
    یک نکته‌ی تکمیلی: کاربرد base href در فایل index.html چیست؟

    فرض کنید برنامه‌ی شما قرار است از داخل زیر پوشه‌ی جدید blazor با آدرس http://example.com/blazor ارائه شود. در این حالت پس از مراجعه به این آدرس، فقط loading را مشاهده خواهید کرد و ... برنامه بارگذاری نمی‌شود. علت اینجا است که در حالت پیش‌فرض، base href تنظیم شده‌ی در فایل index.html، به ریشه‌ی سایت اشاره می‌کند:
    <!DOCTYPE html>
    <html>
    <head>
       <base href="/" />
    بنابراین در این حالت برنامه فایل‌های مورد نیاز خود را در ریشه‌ی وب سرور جستجو خواهد کرد و نه از زیر پوشه‌ی blazor. برای رفع این مشکل باید تغییر زیر صورت گیرد:
    <base href="/blazor/" />
    • #
      ‫۲ سال و ۸ ماه قبل، جمعه ۲۶ آذر ۱۴۰۰، ساعت ۲۳:۵۰
      یک نکته: base href حساس به بزرگی و کوچکی حروف است!
      بین تنظیم
      <base href="/blazor/" />
      و تنظیم زیر
      <base href="/Blazor/" />
      تفاوت وجود دارد. یعنی اگر اولی تنظیم شده باشد و کاربر در مرورگر http://localhost/Blazor را وارد کند، با پیام خطای زیر مواجه می‌شود:
      System.ArgumentException: The URI is not contained by the base URI
      فعلا برای رفع این مشکل می‌توان قطعه کد زیر را پیش از تگ js مربوط به blazor قرار داد تا base href را به صورت پویا تنظیم کند:
      <script>
        var path = window.location.pathname.split('/');
        var baseTag = document.getElementsByTagName('base');
        baseTag[0].setAttribute('href', '/' + path[1] + '/');
      </script>
      اطلاعات بیشتر
    • #
      ‫۲ سال و ۸ ماه قبل، شنبه ۲۷ آذر ۱۴۰۰، ساعت ۰۰:۰۴
      یک نکته: استفاده از base href و url‌های برنامه
      اگر قرار است base href را مقدار دهی کنید، در کدهای برنامه هیچ مسیری را با / شروع نکنید. شروع با / به معنای پردازش از ریشه‌ی سایت خواهد بود و نه از زیر پوشه‌ی برنامه. برای مثال اگر قرار است برنامه در مسیر http://site/app ارائه شود، اگر url ای را با / شروع کردید، به http://site اشاره می‌کند و نه http://site/app. این مورد حتی برای urlهای api‌ها هم باید رعایت شود و آن‌ها هم نباید با مثلا api/ شروع شوند که به ریشه‌ی سایت اشاره می‌کند. این مورد را باید به عنوان یک best practice، در حین توسعه‌ی برنامه‌های blazor رعایت کرد.
  • #
    ‫۳ سال و ۳ ماه قبل، سه‌شنبه ۲۸ اردیبهشت ۱۴۰۰، ساعت ۱۵:۲۲
    یک نکته‌ی تکمیلی: بهبود IL Trimming در NET 6x.
    در دات نت 5، IL Trimming فقط اسمبلی‌های استفاده نشده را حذف می‌کند. در دات نت 6، این حالت پیش‌فرض به link تغییر پیدا کرده؛ یعنی نه فقط اسمبلی‌های استفاده نشده را حذف می‌کند، بلکه متدها و اعضایی را هم که در برنامه استفاده نشده‌اند نیز حذف می‌کند.
    • #
      ‫۲ سال و ۱ ماه قبل، یکشنبه ۲ مرداد ۱۴۰۱، ساعت ۱۶:۳۸
      سلام 
      در دات نت 6 ، من این موارد را فعال کردم 
      <PublishTrimmed>true</PublishTrimmed>
      <TrimMode>link</TrimMode>
      اما هنگام پابلیش ، تو پوشه _framework هنوز حدود 200  dll قرار میگیره (با احتساب .gz, .br ) میشه حدود 600 تا و دانلود اینها تو مرورگر لود را میبره بالا .
      آیا راهکاری برای کاهش اینها وجود داره یا حداقل lazy loading بشند ؟ 
      لود اولیه سایت بالاست . من کارهای زیر را هم انجام دادم
      - استفاده از web.config پیشنهادی
      - فعال کردن  compression در  iis
      - فعال کردن  lazy loading برای  dll هایی که خودم ایجاد کردم .

      • #
        ‫۲ سال و ۱ ماه قبل، یکشنبه ۲ مرداد ۱۴۰۱، ساعت ۱۷:۱۴
        اما هنگام پابلیش ، تو پوشه _framework هنوز حدود 200  dll قرار میگیره و دانلود اینها تو مرورگر لود را میبره بالا . 
        به ازای هر فایل نگارش اصلی dll، نگارش gz. و یا br. آن هم جداگانه تولید و نگهداری می‌شود که به ظاهر تعداد آن‌ها زیاد است. از هر کدام از این‌ها فقط «یکی» بر اساس تنظیمات سرور و نحوه‌ی درخواست مرورگر ارائه خواهد شد و نه تمام آن‌ها. همچنین در طی publishهای بعدی، بر اساس امضای دیجیتال فایل‌های دریافتی و کش شده‌ی در مرورگر، موارد تکراری دریافت نخواهند شد.
        • #
          ‫۲ سال و ۱ ماه قبل، یکشنبه ۲ مرداد ۱۴۰۱، ساعت ۱۷:۳۴
          ممنون . بله با احتساب اونها میشه حدود 600 فایل .
          ابن لود به خصوص روی گوشی بالاتر از سیستم هست . آیا کارهایی که انجام شده درسته و نیازی هست کار دیگه ای انجام بشه ؟
  • #
    ‫۳ سال و ۱ ماه قبل، یکشنبه ۲۰ تیر ۱۴۰۰، ساعت ۱۶:۵۴
    نمونه‌ای از راه اندازی یک برنامه‌ی Blazor WASM در IIS

    الف) به قسمت application pools در IIS Manager مراجعه کرده و گزینه‌ی add application pool را انتخاب کنید. سپس یک نمونه‌ی جدید را برای مثال به نام no-managed ایجاد کنید که net clr version. آن به گزینه‌ی no managed code اشاره می‌کند.
    ب) پس از publish برنامه مطابق مطلب فوق (برای مثال با اجرای دستور dotnet publish -c Release) و معرفی مسیر پوشه‌ی publish به IIS (برای مثال به عنوان یک Application جدید ذیل default web site با کلیک راست بر روی default web site و انتخاب گزینه‌ی Add application)، این application pool جدید را به برنامه‌ی خود در IIS نسبت دهید. برای اینکار basic settings سایت را باز کرده و بر روی دکمه‌ی select که در کنار نام application pool هست، کلیک کرده و گزینه‌ی no-managed قسمت الف را انتخاب کنید.

    نکته 1: برنامه‌های blazor wasm، یا standalone هستند و یا hosted. مورد standalone یعنی کاری به Web API ندارد و به خودی خود، به صورت یک سایت استاتیک قابل مشاهده‌است. حالت hosted یعنی به همراه web api هم هست و توسط دستور برای مثال «dotnet new blazorwasm -o BlazorIIS --hosted --no-https» ایجاد می‌شود که به همراه سه پوشه‌ی کلاینت، سرور و shared است. برای توزیع حالت متکی به خود، فقط محتویات پوشه‌ی publish، به عنوان مسیر برنامه، در IIS معرفی خواهند شد. در حالت hosted، مسیر اصلی، پوشه‌ی publish مربوط به پروژه‌ی سرور است؛ یعنی: Server\bin\Release\net5.0\publish. در این حالت پوشه‌ی Client\bin\Release\net5.0\publish باید به داخل همین پوشه‌ی publish سرور کپی شود. یعنی پوشه‌ی publish پروژه‌ی client باید به درون پوشه‌ی publish پروژه‌ی server کپی شود تا با هم یک برنامه‌ی قابل توزیع توسط IIS را تشکیل دهند.
    در اینجا تنها فایل‌هایی که تداخل پیدا می‌کنند، فایل‌های web.config هستند که باید یکی شوند. فایل web.config برنامه‌ی web api با برنامه‌ی client یکی نیست، اما می‌توان محتویات این دو را با هم یکی کرد.
    نکته 2: محل اجرای دستور dotnet publish -c Release مهم است. اگر این دستور را در کنار فایل sln پروژه‌ی hosted اجرا کنید، سه خروجی نهایی publish را تولید می‌کند و پس از آن باید فایل‌های کلاینت را به سرور، به صورت دستی کپی کرد. اما اگر دستور publish را درون پوشه‌ی سرور اجرا کنید، کار کپی فایل‌های کلاینت را به درون پوشه‌ی نهایی publish تشکیل شده، به صورت خودکار انجام می‌دهد؛ علت اینجا است که اگر به فایل csproj. پروژه‌ی سرور دقت کنید، ارجاعی را به پروژه‌ی کلاینت نیز دارد (هر چند ما از کدهای آن در برنامه‌ی web api استفاده نمی‌کنیم). این ارجاع تنها کمک حال دستور dotnet publish -c Release است و کاربرد دیگری را ندارد.

    ج) اکنون اگر برنامه را برای مثال با مسیر فرضی جدید http://localhost/blazortest اجرا کنید، خطای 500.19 را دریافت می‌کنید. علت آن‌را در مطلب «بررسی خطاهای ممکن در حین راه اندازی اولیه برنامه‌های ASP.NET Core در IIS» بررسی کرده‌ایم. باید IIS URL Rewrite ماژول را نصب کرد؛ تا این مشکل برطرف شود. همچنین دلیل دیگر مشاهده‌ی این خطا، عدم نصب بسته‌ی هاستینگ متناظر با شماره نگارش NET. مورد استفاده‌است (اگر برنامه‌ی شما از نوع hosted است و web api هم دارد).
    د) پس از آن باز هم برنامه اجرا نمی‌شود! اگر در خطاها دقت کنید، به دنبال اسکریپت‌هایی شروع شده از مسیر localhost است و نه از پوشه‌ی جدید blazortest. برای رفع این مشکل باید فایل publish\wwwroot\index.html را مطابق نکته‌ی base-URL که کمی بالاتر ذکر شد، ویرایش کرد تا blazor بداند که فایل‌ها، در چه مسیری قرار دارند (و در ریشه‌ی سایت واقع نشده‌اند):
    <head>
    <base href="/blazortest/" />
    اکنون برنامه بدون مشکل بارگذاری و اجرا می‌شود.
    • #
      ‫۳ سال و ۱ ماه قبل، چهارشنبه ۳۰ تیر ۱۴۰۰، ساعت ۱۵:۵۱
      سلام با توجه به تنظیمات فوق پیش رفتم اما خطای زیر را دریافت کردم ممنون میشم راهنمایی بفرمایید

      • #
        ‫۳ سال و ۱ ماه قبل، چهارشنبه ۳۰ تیر ۱۴۰۰، ساعت ۱۶:۴۷
        در مورد خطای «SignalR Error 405 (method not allowed)»
        - ممکن هست سرور IIS شما قدیمی باشد و متد در حال اجرا را پشتیبانی نکند.
        - ممکن است به CORS نیاز باشد و تنظیم نشده باشد.
        - ممکن است ترتیب معرفی میان‌افزارها را اشتباه کرده باشید.
        - ممکن است بسته‌ی نیوگت سیگنال‌آر اشتباهی را در حال استفاده هستید و یا این بسته قدیمی است.
        • #
          ‫۳ سال و ۱ ماه قبل، پنجشنبه ۳۱ تیر ۱۴۰۰، ساعت ۰۰:۵۹
          ممنون از پاسخگویی شما.
          بله درسته بسته نیوگت سیگنال آر نسخه قدیمی‌تر بود.
    • #
      ‫۲ سال و ۳ ماه قبل، سه‌شنبه ۲۷ اردیبهشت ۱۴۰۱، ساعت ۰۱:۱۴
      اگر برنامه خود را توسط دستور dotnet new blazorwasm -o BlazorIIS --hosted --no-https  ایجاد نکردیم و یا گزینه hosting module را در ویژوال استودیو نزدیم، چگونه برنامه blazor wasm خود را بهمراه api آن در یک سایت iss پابلیش کنیم؟

      - پکیج زیر را به پروژه سرور خود اضافه کنید
      Microsoft.AspNetCore.Components.WebAssembly.Server
      - در فایل program.cs پروژه سرور، کد‌های زیر را در پایین UseHttpsRedirection اضافه کنید:
      app.UseBlazorFrameworkFiles();
      app.UseStaticFiles();
      
      app.UseRouting();
      - پایین MapControllers  کد زیر را اضافه کنید:
      app.MapFallbackToFile("index.html");
      - پروژه کلاینت (پروژه blazor wasm) که دقیقا با پروژه سرور در یک solution رفرنس داده شده است را به پروژه سرور رفرنس دهید.
      یعنی پروژه blazor wasm شما باید در پروژه API شما رفرنس داده شود.
      نکته: در این جا میتوانید برای پیاده سازی منطق از یک assembly یکسان جهت کنترل مشترک logic بین دو پروژه استفاده کنید.
      کار تمام شده است و میتوانید توسط دستو dotnet publish که در مقاله و نظرات، کامل به آن اشاره شده است، استفاده کنید
  • #
    ‫۳ سال قبل، شنبه ۱۶ مرداد ۱۴۰۰، ساعت ۱۴:۴۴
    روش درست کردن دمو برای پروژه‌های blazor در Github (یا روش توزیع پروژه‌های Blazor WASM در Github-Pages)

    ابتدا فایل yml زیر را در پوشه‌ی github\workflows\deploy.yml. قرار دهید (پوشه‌ای را به این نام، در ریشه‌ی پروژه‌ی خود ایجاد کنید):
    name: Deploy to GitHub Pages
    
    # Run workflow on every push to the main branch
    on:
      push:
        branches: [ main ]
    
    jobs:
      deploy-to-github-pages:
        # use ubuntu-latest image to run steps on
        runs-on: ubuntu-latest
        steps:
        # uses GitHub's checkout action to checkout code form the main branch
        - uses: actions/checkout@v2
        
        # sets up .NET Core SDK
        - name: Setup .NET Core SDK
          uses: actions/setup-dotnet@v1
          with:
            dotnet-version: 5.0.302
    
        # publishes Blazor project to the release-folder
        - name: Publish .NET Core Project
          run: dotnet publish ./src/DNTPersianComponents.Blazor.WasmSample/Server/DNTPersianComponents.Blazor.WasmSample.Server.csproj -c Release -o release --nologo
        
        # changes the base-tag in index.html from '/' to 'DNTPersianComponents.Blazor' to match GitHub Pages repository subdirectory
        - name: Change base-tag in index.html from / to DNTPersianComponents.Blazor
          run: sed -i 's/<base href="\/" \/>/<base href="\/DNTPersianComponents.Blazor\/" \/>/g' release/wwwroot/index.html
        
        # copy index.html to 404.html to serve the same file when a file is not found
        - name: copy index.html to 404.html
          run: cp release/wwwroot/index.html release/wwwroot/404.html
    
        # add .nojekyll file to tell GitHub pages to not treat this as a Jekyll project. (Allow files and folders starting with an underscore)
        - name: Add .nojekyll file
          run: touch release/wwwroot/.nojekyll
          
        - name: Commit wwwroot to GitHub Pages
          uses: JamesIves/github-pages-deploy-action@3.7.1
          with:
            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
            BRANCH: github-pages
            FOLDER: release/wwwroot
    در این قالب، چهار مورد را باید ویرایش کنید:
    - نام شاخه‌ی اصلی پروژه؛ که یا main است و یا master.
    - شماره نگارش دات نت مورد استفاده.
    - مسیر فایل csproj پروژه‌ی wasm.
    - نام اصلی مخزن کد.


    سپس آن‌را به مخزن کد خود commit کنید. بعد به قسمت settings->pages در github مراجعه کرده و source را بر روی نام شاخه‌ی جدید github-pages (فوق در قسمت آخر کار) قرار داده و آن‌را ذخیره کنید. الان سایت دموی شما در مسیری که در همین قسمت pages پس از ذخیره سازی، نمایش می‌دهد، آماده‌است.


    یک نکته‌ی مهم

    چون base href، توسط action فوق اصلاح می‌شود تا به پوشه‌ی نسبی محل قرارگیری برنامه اشاره کند، نیاز است navlink‌ها با href شروع شده‌ی با / نباشند؛ چون به ریشه‌ی سایت اشاره می‌کنند و نه مسیر نسبی محل قرارگیری برنامه. کلا در هر قسمتی از برنامه، این نکته باید رعایت شود. مثلا اگر فونت وبی را در فایل app.css تعریف کرده‌اید، مسیر آن نباید با / شروع شود؛ وگرنه یافت نخواهد شد. یک مثال:
    فایل app.css برنامه در مسیر wwwroot\css\app.css قرار دارد و داخل آن فایل، فونت‌های پوشه‌ی دیگر wwwroot\lib\samim-font را به صورت زیر تعریف کرده‌ایم؛ که یعنی مسیر فونت را از ریشه‌ی سایت پیدا کن:
    src: url('/lib/samim-font/Samim-Bold.eot?v=4.0.5');
    این مسیر، باید به مسیر نسبی زیر که به یک پوشه‌ی بالاتر (از محل قرار گیری app.css) اشاره می‌کند، اصلاح شود:
    src: url('../lib/samim-font/Samim-Bold.eot?v=4.0.5');
  • #
    ‫۲ سال و ۹ ماه قبل، چهارشنبه ۲۶ آبان ۱۴۰۰، ساعت ۱۴:۲۸
    اضافه شدن قابلیت کامپایل AOT به Blazor 6x

    Blazor WebAssembly 6x به همراه قابلیتی است به نام ahead-of-time (AOT) compilation که در این حالت، کدهای دات نتی برنامه، مستقیما به native WebAssembly کامپایل می‌شوند. این مورد سبب بالا رفتن کارآیی برنامه خواهد شد؛ در عوض بالا رفتن حجم نهایی قابل توزیع.
    اگر از AOT compilation استفاده نشود (یعنی حالت متداول)، Blazor WebAssembly در مرورگر، به کمک مفسر IL یا همان NET Intermediate Language. که به صورت WebAssembly تهیه شده‌است، اجرا خواهد شد. یک چنین حالتی به دلیل استفاده‌ی از مفسر، نسبت به حالت استفاده‌ی از JIT سمت سرور (یا همان NET just-in-time (JIT) runtime.)، اندکی کندتر است. AOT compilation جهت رفع یک چنین کمبودی ارائه شده‌است تا کدهای دات نتی را مستقیما و بدون نیاز به مفسر، تبدیل به یک native WebAssembly کند. این مورد سرعت و کارآیی برنامه‌هایی را که کارهای محاسباتی مبتنی بر CPU را انجام می‌دهند، به نحو قابل ملاحظه‌ای افزایش می‌دهد. در مقابل باید درنظر داشت که حجم نهایی WebAssembly‌های واقعی تولید شده، از نمونه‌ی IL آن‌ها بالاتر است (حدود 2 برابر) که مدت زمان ابتدایی دریافت برنامه را افزایش می‌دهند.

    روش فعالسازی کامپایل AOT

    ابتدا نیاز است work load آن‌را توسط دستور زیر دریافت کرد (ابزارهای کامپایل AOT، جزئی از SDK نیستند):
    dotnet workload install wasm-tools
    سپس برای فعالسازی آن می‌توان تنظیم زیر را به فایل csporj پروژه‌های WASM اضافه کرد:
    <PropertyGroup>
      <RunAOTCompilation>true</RunAOTCompilation>
    </PropertyGroup>
    در این حالت با publish برنامه توسط دستور dotnet publish -c Release، مراحل تولید native WebAssemblyها طی می‌شوند و باید درنظر داشت که به علت کند بودن این پروسه، تنها در زمان publish نهایی، شاهد این عملیات خواهید بود و نه در زمان اجرای برنامه در حالت توسعه.

    یک نکته: هنوز در نگارش 6.0 RTM، یکسری از قابلیت‌های AOT اضافه نشده‌اند که باید منتظر سرویس‌پک‌های آن بود. برای مثال اگر این کامپایل، بر روی پروژه‌ای که فقط سورس کد است اجرا شود، با موفقیت به پایان می‌رسد؛ اما با اضافه شدن کتابخانه‌های ثالث ممکن است با شکست مواجه شود. اگر در این حالت خطایی را دریافت کردید، عملیات publish را به صورت dotnet publish -p:RunAOTCompilation=true -bl انجام دهید. سوئیچ bl- سبب می‌شود تا فایلی به نام msbuild.binlog در ریشه‌ی پروژه‌ی شما تولید شود. این فایل در حقیقت لاگ باینری MSBuild است که توسط برنامه‌ی Viewer آن قابل مشاهده‌است. در اینجا به دنبال exit code‌ها بگردید؛ یک نمونه‌ی آن.
  • #
    ‫۲ سال و ۸ ماه قبل، یکشنبه ۱۴ آذر ۱۴۰۰، ساعت ۱۹:۵۵
    یک نکته: کاهش زمان build پروژه‌های Blazor در حالت توسعه

    در پروژه‌های Blazor، خاصیت ویژه‌ی BlazorLinkOnBuild به true تنظیم شده‌است که سبب می‌شود تا موارد استفاده نشده‌ی در برنامه، از خروجی نهایی حذف شوند. این مورد هرچند حجم نهایی را کاهش می‌دهد، اما در زمان توسعه نیز فعال است و سبب بالا رفتن زمان build برنامه می‌شود؛ گاهی از اوقات تا 10 برابر! برای غیرفعال کردن آن در زمان debug و توسعه، می‌توان فایل csproj را به صورت زیر ویرایش کرد. این تنظیم در حین publish در حالت release، غیرفعال می‌شود:
    <PropertyGroup>
        <BlazorLinkOnBuild  Condition="'$(Configuration)'!='Release'">false</BlazorLinkOnBuild>
    </PropertyGroup>
  • #
    ‫۲ سال و ۲ ماه قبل، شنبه ۴ تیر ۱۴۰۱، ساعت ۲۳:۱۸
    باسلام. در blazor wasm پس از هربار پابلیش وبه روز رسانی، مروگر تغییرات اعمال شده رو نمایش نمیده و همواره از کش فایلها رو واکشی و بارگزاری میکنه. راه حل پاک کردن کش به صورت خودکار یا در معرض دید قراردادن تغییرات برای مرورگر به چه نحوی می‌باشد؟
    • #
      ‫۲ سال و ۲ ماه قبل، یکشنبه ۵ تیر ۱۴۰۱، ساعت ۰۱:۴۴
      - اسمبلی‌های دات نتی را که هربار به صورت خودکار دریافت می‌کند. یکی از کارهای اسکریپتی که در انتهای فایل index.html درج شده، دقیقا بررسی امضای دیجیتال موارد موجود در کش مرورگر و موارد بر روی سرور هست. بنابراین غیرممکن است که اسمبلی‌های جدید WASM، از کش خوانده شوند.
      - تنها مواردی که ممکن است از کش خوانده شوند، فایل‌های استاتیک برنامه هستند که دو رویه‌ی تنظیم هدر کش فایل‌های استاتیک (تنظیمات کش کردن چندسکویی فایل‌های ایستا در ASP.NET Core) و استفاده از روش‌های cache busting را باید مدنظر داشته باشید (مانند قرار دادن یک کوئری استرینگ بیانگر نگارش در انتهای فایل‌های css و js شبیه به asp-file-version) و این مورد در تمام برنامه‌های وب، یکسان است.
  • #
    ‫۱ سال و ۹ ماه قبل، شنبه ۵ آذر ۱۴۰۱، ساعت ۲۳:۱۳
    با سلام؛ پروژه بصورت WASM+Web API رو تغییر دادم و دات نت اون هم به  ورژن 7  ارتقا دادم. در موقع توسعه و محیط VS، برنامه بدون هیچ مشکلی کار میکند ولی بعد از publish و مستقر شدن در IIS خطای زیر صادر میکند.
    crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
          Unhandled exception rendering component: Arg_NoDefCTor, Wasm.Shared.MainLayout
    System.MissingMethodException: Arg_NoDefCTor, Wasm.Shared.MainLayout
       at System.RuntimeType.CreateInstanceMono(Boolean , Boolean )
       at System.RuntimeType.CreateInstanceDefaultCtor(Boolean , Boolean )
       at System.Activator.CreateInstance(Type , Boolean , Boolean )
       at System.Activator.CreateInstance(Type , Boolean )
       at System.Activator.CreateInstance(Type )
       at Microsoft.AspNetCore.Components.DefaultComponentActivator.CreateInstance(Type )
       at Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider , Type )
       at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateComponent(Type )
       at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(RenderTreeFrame& , Int32 )
       at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& , Int32 )
       at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& , Int32 )
       at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& , Int32 )
       at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& , Int32 , Int32 , Int32 , Int32 )
       at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer , RenderBatchBuilder , Int32 , ArrayRange`1 , ArrayRange`1 )
       at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder , RenderFragment , Exception& )
       at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry )
       at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue() blazor.webassembly.js:1:38555
    پس از بررسی متوجه شدم مشکل از CascadingAuthenticationState هست. وقتی فایل App.razor بصورت زیر هست خطا بر طرف میشود.
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <p role="alert">Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
    ولی بصورت زیر بعد از پابلیش خطا صادر میکند.
     <CascadingAuthenticationState>
          <Router AppAssembly="typeof(App).Assembly"  PreferExactMatches="true">
              <Found Context="routeData">
              <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                        <Authorizing>
                            <FocusOnNavigate RouteData="@routeData" Selector="h1"/>
                        </Authorizing>
                        <NotAuthorized>
    
                          @*  <RedirectToLogin/>*@
    
    
                        </NotAuthorized>
                    </AuthorizeRouteView>
                </Found>
                <NotFound>
                    <LayoutView Layout="@typeof(MainLayout)">
                          <span>Error</span>
                     </LayoutView>
                </NotFound>
            </Router>
        </CascadingAuthenticationState>
  • #
    ‫۱ سال و ۱ ماه قبل، پنجشنبه ۸ تیر ۱۴۰۲، ساعت ۱۶:۳۷
    یه پروژه  Blazor WebAssembly App با NET 7. ایجاد کردم، بدون تغییر تنظیماتی publish گرفتم و روی سرور قرار دادم اما به درستی لود نمیشه و خطا میده، راه حلی براش پیدا نکردم
    لود محتوای صفحه تا 93% میره و این خطا رخ میده

    • #
      ‫۱ سال و ۱ ماه قبل، پنجشنبه ۸ تیر ۱۴۰۲، ساعت ۱۷:۲۳
      قسمت «روش فعالسازی توزیع مبتنی بر فشرده سازی Brotli در IIS» را در متن مطالعه کنید. یک فایل web.config مخصوص دارد که یکسری mime-type جدید را تعریف می‌کند. این‌ها به صورت پیش‌فرض در IIS تعریف نشده‌اند. به همین جهت خطای 404 را در حین دریافت فایل‌هایی با پسوند blat. و امثال آن، دریافت می‌کنید.