عنوان:

‫مدیریت مسیر پایه (Base Path) در برنامه‌های Blazor: از چالش‌های استقرار تا راهکار دات‌نت ۱۱


نویسنده: وحید نصیری
تاریخ: ۱۴۰۵/۰۳/۲۹ ۱۰:۱۰
آدرس: www.dntips.ir
هنگام توسعه برنامه‌های مدرن وب با فریم‌ورک Blazor، یکی از مهم‌ترین مفاهیمی که در زمان استقرار (Deployment) برنامه اهمیت پیدا می‌کند، نحوه‌ی مدیریت مسیر پایه یا همان base href است. برنامه‌های تک‌صفحه‌ای (SPA) برای مسیریابی صحیح (Routing) در سمت کاربر و همچنین یافتن منابع استاتیک خود (مانند فایل‌های CSS، جاوااسکریپت و DLLها) به این مسیر وابسته‌اند. در این مقاله، ابتدا به بررسی چالش‌های رایج تنظیم مسیر پایه در برنامه‌های Blazor می‌پردازیم، راهکارهای سنتی آن را بررسی می‌کنیم و در نهایت می‌بینیم که چگونه دات‌نت ۱۱ (NET 11.) با یک راهکار بومی و ظریف، این دغدغه را برای توسعه‌دهندگان برطرف کرده است.

توضیح و بررسی فنی

۱. چالش استقرار در زیرپوشه‌ها (Subdirectories)
در حالت پیش‌فرض، زمانی که یک پروژه Blazor ایجاد می‌کنید، فایل index.html (یا App.razor در نسخه‌های جدیدتر) شامل تگ زیر در بخش است:
<base href="/" />
این تنظیم به مرورگر می‌گوید که ریشه (Root) برنامه همان دامنه اصلی سایت است. اما فرض کنید قصد دارید برنامه خود را در یک زیرپوشه به نام blazor مستقر کنید؛ به طوری که برنامه از طریق آدرس http://example.com/blazor در دسترس باشد.
در این سناریو، اگر تغییری در base href ایجاد نکنید، پس از ورود به لینک، تنها صفحه در حال بارگذاری (Loading) را مشاهده خواهید کرد و برنامه متوقف می‌شود.
دلیل این اتفاق چیست؟ مرورگر تلاش می‌کند فایل‌های حیاتی Blazor (مانند _framework/blazor.webassembly.js) را از ریشه سرور (یعنی http://example.com/_framework/...) دانلود کند، در حالی که این فایل‌ها اکنون در زیرپوشه blazor قرار دارند.
برای رفع این مشکل در روش سنتی، باید مقدار href را به صورت زیر تغییر دهیم:
<base href="/blazor/" />
(نکته: همیشه از وجود اسلش در ابتدا و انتهای مسیر اطمینان حاصل کنید.)

۲. دردسرهای حساسیت به حروف (Case Sensitivity)
تغییر دستی تگ base شاید ساده به نظر برسد، اما یک چالش پنهان دارد: حساسیت به بزرگی و کوچکی حروف.
فرض کنید شما مسیر را به صورت تنظیم کرده‌اید. اگر کاربری آدرس سایت را با حروف بزرگ در مرورگر وارد کند (مثلاً http://example.com/Blazor)، Blazor در زمان مسیریابی دچار سردرگمی شده و با خطای زیر در کنسول مرورگر مواجه می‌شوید:
System.ArgumentException: The URI is not contained by the base URI

راهکار سنتی (مبتنی بر جاوااسکریپت):
تا پیش از نسخه‌های جدید دات‌نت، توسعه‌دهندگان برای دور زدن این مشکل، تگ base را به صورت پویا (Dynamic) و با استفاده از جاوااسکریپت تنظیم می‌کردند. در این روش، قطعه کد زیر پیش از اسکریپت اصلی Blazor قرار می‌گرفت تا مسیر پایه را بر اساس آدرسی که کاربر وارد کرده است، استخراج و مقداردهی کند:
<script>
  // استخراج بخش اول مسیر از URL فعلی کاربر
  var path = window.location.pathname.split('/');
  var baseTag = document.getElementsByTagName('base');
  
  // تنظیم پویای مسیر پایه
  baseTag[0].setAttribute('href', '/' + path[1] + '/');
</script>
این هکِ جاوااسکریپتی مشکل را حل می‌کرد، اما از ظرافت کدهای دات‌نت می‌کاست و مدیریت فایل‌های HTML را کمی پیچیده‌تر می‌کرد.

۳. راهکار قطعی در دات‌نت ۱۱: کامپوننت جدیدBasePath
مایکروسافت در .NET 11 برای برنامه‌های Blazor Web، یک راهکار بومی، تمیز و کاملاً یکپارچه با فریم‌ورک ارائه داده است: کامپوننت BasePath. با معرفی این کامپوننت، دیگر نیازی به مدیریت دستی تگ یاد شده یا نوشتن هک‌های جاوااسکریپتی ندارید. این کامپوننت به صورت خودکار، در زمان اجرای برنامه (Runtime) مسیر پایه صحیح را بر اساس NavigationManager.BaseUri پردازش و رندر می‌کند. برای استفاده از آن، کافی است تگ استاتیک را حذف کرده و از این کامپوننت استفاده کنید:
@using Microsoft.AspNetCore.Components.Endpoints

<!DOCTYPE html>
<html>
<head>
    <BasePath />
    <link rel="stylesheet" href="css/app.css" />
</head>
<body>
    @RenderBody()
</body>
</html>
مزیت اصلی: اگر برنامه در مسیرهایی مانند /dashboard یا /app مستقر شود، این کامپوننت بدون هیچ دردسری مسیر صحیح را تشخیص می‌دهد. همچنین در صورتی که نتواند مسیر را تجزیه و تحلیل کند، به عنوان یک راهکار پشتیبان (Fallback)، همان مسیر ریشه (/) را برمی‌گرداند. بدین ترتیب، مشکل حساسیت به حروف (Case Sensitivity) نیز در سمت سرور به زیبایی مدیریت می‌شود.

یک استثنای مهم: برنامه‌های Standalone Blazor WebAssembly
باید توجه داشت که قابلیت پویای به دلیل نیاز به پردازش در زمان رندر (Server-side)، برای برنامه‌های Blazor Web (نسخه‌های Server یا Auto) طراحی شده است. اگر پروژه شما از نوع Standalone Blazor WebAssembly است (یعنی برنامه‌ای که صرفاً شامل فایل‌های استاتیک است و هیچ سرور دات‌نتی در پشت‌صحنه آن را هاست نمی‌کند)، همچنان باید از تگ استاتیک HTML استفاده کنید:
<base href="/" />
دلیل این امر آن است که در برنامه‌های Standalone، هیچ سروری وجود ندارد که بتواند پیش از ارسال فایل HTML به مرورگر کلاینت، کامپوننت <BasePath /> را رندر کرده و مقدار آن را محاسبه کند.


نتیجه‌گیری
مدیریت base href در گذشته یکی از بخش‌های پردردسر در فرآیند پابلیش و استقرار برنامه‌های Blazor (به خصوص در زیرپوشه‌ها) بود. حساسیت به حروف و نیاز به اسکریپت‌های جانبی باعث می‌شد تا کدها از حالت استاندارد خارج شوند. خوشبختانه با انتشار .NET 11، معرفی کامپوننت قدرتمند <BasePath /> نشان داد که تیم توسعه‌ی دات‌نت به بازخورد برنامه‌نویسان توجه ویژه‌ای دارد. اکنون توسعه‌دهندگان می‌توانند بدون نگرانی از خطاهای مسیریابی و با کدی بسیار تمیزتر، برنامه‌های خود را در هر آدرس و زیرپوشه‌ای مستقر کنند. با این حال، درک تفاوت ساختاری بین برنامه‌های Server-Rendered و Standalone WASM برای انتخاب رویکرد درست، همچنان الزامی است.