رفتن به محتوا

Nuxt 4.6.2: پاک‌سازی head در server islandها، route ruleهای بدون حساسیت به حروف و فهرستی از رفع باگ‌ها

۶ دقیقه مطالعه
nuxt
nitro
security

نسخهٔ v4.6.2 Nuxt در ۱۶ اکتبر، یک هفته بعد از 4.6.1 منتشر شد. یادداشت انتشار آن را patch می‌نامد و راهنمای ارتقا ندارد، اما چند مورد در changelog رفتاری را عوض می‌کند که ممکن است به آن تکیه کرده باشید. این نوشته موارد را بر اساس چیزی که بعد از ارتقا باید بررسی کنید مرتب کرده است.

دو تغییر که باید عمدی بررسی شوند

head در server islandها از قواعد useHeadSafe عبور می‌کند

این نسخه قواعد useHeadSafe را روی head تولیدشده توسط server islandها اعمال می‌کند. useHeadSafe نسخهٔ محدودشدهٔ useHead است: برای هر عنصر فقط فهرستی از attributeهای مجاز را نگه می‌دارد و بقیه را حذف می‌کند، مثل innerHTML روی scriptها یا http-equiv روی metaها. مستندات توصیه می‌کنند هر جا داده‌های head از محتوای تولیدشده توسط کاربر می‌آید از آن استفاده کنید.

یادداشت انتشار فقط یک خط توضیح می‌دهد، پس نمی‌توانم دقیق بگویم کدام ورودی‌های head از یک island اکنون فیلتر می‌شوند. برداشت عملی این است که یک island دیگر نمی‌تواند محتوای دلخواه script یا attributeهای خطرناک meta را در head صفحهٔ میزبان بنویسد. اگر یک server island فعلاً به این رفتار تکیه دارد، مثلاً با تزریق یک script درون‌خطی از طریق useHead، بعد از ارتقا <head> رندرشده را بررسی کنید.

vue
<script setup lang="ts">
// Inside a .server.vue island component
useHead({
  title: "Profile",
  meta: [{ name: "description", content: "Public profile" }], // plain meta survives
  // script: [{ innerHTML: "..." }]   // the kind of entry that useHeadSafe rules drop
});
</script>

این تغییر ادامهٔ انتشار امنیتی 4.5.1 است که طبق فهرست انتشارها چند مشکل server island را رفع کرد. 4.6.2 را ادامهٔ سخت‌سازی همان سطح بدانید، نه یک قابلیت تازه.

route ruleهای سمت سرور بدون حساسیت به حروف تطبیق می‌شوند

route ruleهای سرور اکنون بدون حساسیت به بزرگی و کوچکی حروف تطبیق داده می‌شوند، مگر اینکه routing حساس به حروف تنظیم شده باشد. Route ruleها راهی هستند برای تعیین رفتار هر مسیر مثل redirect، proxy، headers، swr، isr و prerender:

ts
// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    "/admin/**": { headers: { "cache-control": "no-store" } },
    "/proxy/**": { proxy: "https://api.example.com/**" },
  },
});

اهمیت موضوع: قاعده‌ای که برای /admin/** نوشته شده و فقط مسیرهای با حروف کوچک را می‌گیرد، اگر خود router درخواست /Admin/x را هم حل کند، به‌راحتی دور زده می‌شود. هم‌خوان کردن تطبیق قاعده‌ها با routing این شکاف را می‌بندد. صفحه‌ای در مستندات Nuxt پیدا نکردم که خود گزینهٔ حساسیت به حروف را توضیح دهد، پس نام کلید پیکربندی را ذکر نمی‌کنم؛ بررسی کنید برنامه‌تان چطور با حساسیت routing رفتار می‌کند و چند URL با حروف ترکیبی را روی ruleهایی که header یا cache تعیین می‌کنند آزمایش کنید.

اگر از ruleهای swr یا isr استفاده می‌کنید، یادتان باشد 4.5.1 قبلاً توصیه کرده بود بعد از رفع‌های آن CDN یا edge cache پاک شود. 4.6.2 این توصیه را تکرار نمی‌کند.

رفع باگ‌ها بر اساس حوزه

ناوبری و routing

  • وقتی ناوبری لغو یا قطع شود، error state حفظ می‌شود (#36546).
  • وقتی صفحه‌ای برای ترک وجود ندارد، page transition شروع نمی‌شود (#36535).
  • scroll offset برای IDهایی که با رقم شروع می‌شوند کار می‌کند (#36524).
  • layout مربوط به middleware هنگام بازگردانی مسیر prerender شدهٔ deferred حفظ می‌شود (#36560).
  • appMiddleware به شکل رشته یا آرایه نرمال‌سازی می‌شود (#36565).
  • پارامترهای router از مسیری که h3 تطبیق داده خوانده می‌شوند.

اگر رفتار scroll سفارشی یا anchorهایی مثل #2026-roadmap دارید، رفع مربوط به IDهای شروع‌شونده با رقم را دوباره آزمایش کنید.

سرور و Nitro

  • response headerها به listenerهای render:response داده می‌شوند (#36583).
  • وقتی پوشهٔ build جابه‌جا شود tsconfig سرور حفظ می‌شود (#36494).
  • importهای بلااستفادهٔ h3 در runtime مربوط به nuxt/server حذف شدند (#36609).
  • presetهای h3 و Nitro فقط وقتی nitroAutoImports خاموش است غیرفعال می‌شوند (#36548).
  • AnyFetchPath برای typeهای route سرور تولیدشده دوباره export می‌شود (#36610).
  • dependencyهای زیر مسیرهای مطلق transpile دیگر inline نمی‌شوند (#36540).

تغییر render:response برای نویسندگان ماژول از همه محسوس‌تر است: hookهایی که headerها را بررسی یا لاگ می‌کنند اکنون آن‌ها را دریافت می‌کنند. همراه با بازنویسی $fetch تایپ‌دار در 4.6.0، دوباره export شدن AnyFetchPath حالتی را رفع می‌کند که declarationهای تولیدشده به typeای ارجاع می‌دادند که مصرف‌کننده نمی‌توانست import کند.

Vite و dev server

  • overlay خطای کامپایل فقط برای صفحه‌های تازه‌بارگذاری‌شده دوباره پخش می‌شود (#36611).
  • ورودی SSR در dev از یک Nitro plugin گرم می‌شود (#36615).
  • vue inline شده در dev به نسخهٔ bundler خود resolve می‌شود (#36569).
  • CSS مجازی با null-byte در dev از طریق /@id/ لینک می‌شود (#36549).
  • محل SPA loading template در vite-server رعایت می‌شود (#36536).

Kit و schema

  • پوشه‌های ماژول با نقطه در نام دیگر از tsconfig برنامه کنار گذاشته نمی‌شوند (#36331).
  • dependencyهای ماژول از ماژولی که آن‌ها را اعلام کرده resolve می‌شوند (#36542).
  • متد handler مشتق‌شده از نام فایل روی Nitro v2 به حروف کوچک تبدیل می‌شود (#36567).
  • experimental.typescriptPlugin مقدار پیش‌فرض می‌گیرد (#36561).

اگر فایل‌های سرور را مثل users.GET.ts نام‌گذاری می‌کنید و روی Nitro v2 اجرا می‌کنید، رفع متد handler مهم است: متد مشتق‌شده از نام فایل اکنون با حروف کوچک است. نویسندگان ماژول به تغییر resolve dependency توجه کنند، چون resolve از ماژول اعلام‌کننده از برداشتن نسخهٔ برنامهٔ مصرف‌کننده جلوگیری می‌کند.

Vapor

Nuxt اکنون slotهای Vapor را با rawVaporSlotKey از Vue تشخیص می‌دهد (#36614). این با کار Vapor که در نوشته‌های release candidate نسخهٔ Vue 3.6 آمد هماهنگ است؛ فقط اگر روی کامپوننت‌های Vapor آزمایش می‌کنید به شما مربوط است.

چک‌لیست ارتقا

  1. npx nuxt upgrade را اجرا کنید و اجازه دهید lockfile dedupe شود؛ یادداشت‌های 4.5.1 --dedupe را توصیه کرده بودند.
  2. صفحه‌ای که server island دارد را رندر کنید و <head> آن را با نسخهٔ قبل مقایسه کنید.
  3. چند مسیر محافظت‌شده یا cache شده را با URLهای حروف ترکیبی درخواست کنید و headerها و رفتار cache را بررسی کنید.
  4. اگر ماژول می‌نویسید، fixtureهای تست را دوباره اجرا کنید: resolve از ماژول اعلام‌کننده و تغییر کنار گذاشتن tsconfig هر دو آنچه ماژول می‌بیند را تغییر می‌دهند.
  5. هر hook سفارشی render:response را بررسی کنید؛ حالا response headerها را می‌گیرد.

بده‌بستان‌ها و ملاحظات

  • یادداشت‌های انتشار مختصرند. چند مورد در آن صفحه شمارهٔ PR ندارند و فقط commit hash دارند، پس جزئیات دقیق در commitهاست. دیف مواردی را که به آن‌ها تکیه دارید بخوانید و به خلاصه‌ای، از جمله همین نوشته، اکتفا نکنید.
  • مدیریت سخت‌گیرانه‌تر head در islandها می‌تواند پیکربندی‌های مشروع اما غیرمعمول را بشکند. سود آن سطح تزریق کوچک‌تر است؛ هزینه‌اش این است که هر چیز بیرون از فهرست مجاز بی‌صدا ناپدید می‌شود.
  • تطبیق بدون حساسیت به حروف برای ruleهایی که رفتار را محافظت می‌کنند پیش‌فرض امن‌تری است، اما کسی که عمداً برای حروف مختلف ruleهای جدا داشته غافلگیر می‌شود.
  • تغییر شکننده‌ای فهرست نشده، که برای یک patch منطقی است، اما «بدون راهنمای ارتقا» یعنی «بدون تغییر رفتار» نیست، همان‌طور که دو مورد بالا نشان می‌دهند.

منابع