شبکه

چرا سایتم روی نت ملی کند می‌شود؟ عیب‌یابی و حذف وابستگی‌های خارجی صفحه

افزایش سرعت سایت در نت ملی: صفحه‌ای که سرورش داخل ایران است اما فونت و کتابخانه و ویجتش از دامنه‌های خارجی می‌آید و کندترین وابستگی سرعت صفحه را تعیین می‌کند

افزایش سرعت سایت در نت ملی را تقریباً همه‌ی مقاله‌های فارسی از سمت اشتباه روایت می‌کنند: هرچه درباره‌ی «نت ملی» نوشته شده برای کاربری است که می‌خواهد به سایت‌های خارجی برسد. این راهنما سمت مقابل را می‌گیرد — شما صاحب سایت هستید و بازدیدکننده‌ی ایرانی‌تان می‌گوید سایت کند شده یا نیمه‌شکسته بالا می‌آید. در ادامه نشان می‌دهیم چرا این اتفاق می‌افتد، چطور با دو دستور تکرارپذیر آن را اندازه بگیرید و مقصر را پیدا کنید، کدام وابستگی‌های خارجی را باید حذف کنید، کدام‌ها را نباید دست بزنید، و نود لبه‌ی داخل ایران دقیقاً چه بخشی از ماجرا را حل می‌کند و چه بخشی را نه.

«نت ملی» برای صاحب سایت یعنی چه؟ مسیر داخلی سالم، مسیر بین‌الملل شکننده

برای وب‌مستر، «نت ملی» یک محصول نیست؛ توصیف وضعیتی است که در آن مسیرهای داخل کشور سرحال کار می‌کنند و گذرگاه بین‌الملل کند، پرنوسان یا موقتاً بسته است. شبکه به‌کل قطع نیست — بازدیدکننده هنوز به سرورهای داخلی می‌رسد و انتظار دارد سایت شما هم کار کند.

نکته‌ی کلیدی این است: سایت شما به‌عنوان یک واحد از کار نمی‌افتد، بلکه تکه‌تکه از کار می‌افتد. سند HTML از سرور داخلی در چند ده میلی‌ثانیه می‌رسد، اما اگر همان سند به فونت گوگل، کتابخانه‌ی جاوااسکریپت روی CDN خارجی و اسکریپت آمار خارجی اشاره کند، مرورگر برای هر کدام از گذرگاه شکننده رد می‌شود. حاصلش همان «سایت بالا می‌آید ولی نصفه است»: متن هست ولی با قلم دیگری، منو باز نمی‌شود، صفحه ده ثانیه سفید می‌ماند. مسئله «سرعت سرور» نیست؛ مسئله این است که صفحه‌ی شما چند بار مجبور است از مرز رد شود.

چرا سایت روی نت ملی نصفه بالا می‌آید؟ منابع مسدودکننده‌ی رندر و تجزیه

مرورگر یک فایل نمی‌گیرد؛ یک سند HTML می‌گیرد و می‌خواندش تا بفهمد چه چیز دیگری لازم دارد. هر src و href به میزبان دیگر یک شاخه‌ی تازه است و هزینه‌اش فقط دانلود فایل نیست: برای هر میزبان جدید یک‌بار DNS حل می‌شود، یک اتصال TCP برقرار می‌شود و یک دست‌دادن TLS انجام می‌گیرد. این شاخه‌ها هم‌وزن نیستند:

  • مسدودکننده‌ی رندر. یک <link rel="stylesheet"> به میزبان خارجی جلوی اولین نمایش صفحه را می‌گیرد؛ تا آن فایل نرسد یا اتصالش شکست نخورد، مرورگر چیزی روی صفحه نمی‌کشد. این همان صفحه‌ی سفید طولانی است.
  • مسدودکننده‌ی تجزیه. یک <script> بدون defer یا async خواندن بقیه‌ی سند را متوقف می‌کند تا خودش برسد و اجرا شود.
  • غیرمسدودکننده. تصویر و iframe (ویدیو و نقشه‌ی جاسازی‌شده) نه رندر را متوقف می‌کنند نه تجزیه‌ی سند را، اما جای خالی و پرش چیدمان می‌سازند — و iframe رویداد load صفحه را تا رسیدن پاسخ نگه می‌دارد، پس اسپینر تب می‌چرخد و اسکریپت‌های وابسته به onload اجرا نمی‌شوند.

و یک واقعیت ناخوشایند: مرورگرها برای اتصالی که پاسخ نمی‌دهد مهلت‌هایی در حد ده‌ها ثانیه قائل‌اند. میزبان خارجیِ بی‌جواب بدتر از میزبان کند است — کند بالاخره جواب می‌دهد، بی‌جواب کاربر را پشت صفحه‌ی سفید نگه می‌دارد. پس «سایت در نت ملی باز نمی‌شود» تقریباً همیشه یعنی یک وابستگی مسدودکننده‌ی خارجی در مسیر بحرانی نشسته، نه اینکه سرور شما خاموش باشد.

چطور TTFB سایت را از داخل ایران اندازه بگیریم؟ تفکیک DNS، TCP و TLS

پیش از هر تغییری یک عدد پایه لازم دارید. دقیق‌ترین ابزار ساده خود curl است که زمان هر مرحله را جدا گزارش می‌کند:

# taken on the origin server itself, 2026-08 — a no-network baseline
curl -o /dev/null -sL -w 'dns:   %{time_namelookup}\ntcp:   %{time_connect}\ntls:   %{time_appconnect}\nttfb:  %{time_starttransfer}\ntotal: %{time_total}\nbytes: %{size_download}\ncode:  %{http_code}\nhops:  %{num_redirects}\n' https://mehranhost.cloud/

dns:   0.000719
tcp:   0.000960
tls:   0.026693
ttfb:  0.260044
total: 0.260251
bytes: 141079
code:  200
hops:  1

این خروجی عمداً از خودِ سرور مبدأ گرفته شده تا خط پایه‌ی «بدون شبکه» را نشان بدهد: فاصله‌ی dns تا tcp کمتر از یک‌چهارم میلی‌ثانیه است و از هیچ شبکه‌ی مشتری واقعی درنمی‌آید. همین دستور را از دستگاهی روی شبکه‌ی داخلی هم بگیرید؛ تفاوت دو خروجی سهم مسیر است. سوئیچ -L هم اختیاری نیست: اگر hops صفر نباشد دامنه ریدایرکت می‌کند و بدون آن فقط همان پاسخ ۳۰۱ چندصدبایتی را می‌سنجید.

اعداد تجمعی‌اند، پس زمان هر مرحله از تفریق دو خط پشت‌سرهم به دست می‌آید. dns بالا یعنی حل‌کردن نام طول کشیده، اما مقصر لزوماً نیم‌سرورهای شما نیستند: این عدد مسیر «دستگاه تا resolver» را می‌سنجد و در اجرای دوم از کش خوانده و تقریباً صفر می‌شود؛ برای سنجیدن خودِ نیم‌سرورها dig @ns1.example.ir example.ir بگیرید و به Query time نگاه کنید. فاصله‌ی tcp تا tls هزینه‌ی دست‌دادن رمزنگاری است و تابع فاصله‌ی شبکه. فاصله‌ی tls تا ttfb یک رفت‌وبرگشت کامل شبکه است به‌علاوه‌ی زمان ساختن پاسخ در سرور؛ برای جدا کردنشان فاصله‌ی dns تا tcp را — که تقریباً یک رفت‌وبرگشت خالص است — از آن کم کنید: باقی‌مانده سهم اپلیکیشن و دیتابیس شماست. با مبدأ خارج از ایران بخش بزرگی از این عدد خودِ گذرگاه بین‌الملل است و با بهینه‌کردن کوئری‌ها تکان نمی‌خورد. و فاصله‌ی ttfb تا total هم تابع حجم HTML شماست و هم تابع پهنای باند مؤثر مسیر. همین ابزار را در راهنمای کاهش پینگ سرور از ایران برای سنجش تأخیر مسیر به کار برده‌ایم؛ اینجا می‌خواهیم بفهمیم وقت کجا می‌سوزد.

آستانه‌های آزمون سرعت سایت مهران هاست نقطه‌ی شروع خوبی برای قضاوت است: TTFB زیر ۴۰۰ میلی‌ثانیه قبول، ۴۰۰ تا ۸۰۰ هشدار، بالای ۸۰۰ مردود؛ مجموع TCP و TLS زیر ۲۵۰ قبول و بالای ۵۰۰ مردود؛ پاسخ DNS زیر ۱۵۰ قبول و بالای ۴۰۰ مردود؛ حجم کل صفحه زیر ۱٫۵ مگابایت قبول و بالای ۳ مگابایت مردود؛ تعداد درخواست‌ها تا ۴۵ قبول و بالای ۹۰ مردود. دو نکته‌ی صادقانه هم بگوییم. اول اینکه curl اتصال خودتان را می‌سنجد، نه تجربه‌ی همه‌ی کاربران. دوم اینکه هیچ ابزار آنلاینی — از جمله آزمون خودِ ما — از شبکه‌ی خانگی کاربران شما اندازه نمی‌گیرد، چون درخواست را از سرور خودش می‌فرستد. پس تقسیم کار روشن است: عددهای ساختاری صفحه — حجم، تعداد درخواست، وجود CDN، وضعیت SSL — را از ابزار بگیرید و عددهای مسیر شبکه را با curl از همان شبکه‌ای که برایتان مهم است. برای شناخت شبکه‌های واقعی کاربرانتان راهنمای آمار بازدیدکنندگان را ببینید.

💡 یک عدد بی‌فایده است، سه عدد تشخیص می‌دهند. همیشه سه چیز را با هم بردارید: TTFB با تفکیک مراحلش، حجم کل صفحه به‌همراه تعداد درخواست‌ها، و تعداد میزبان‌های خارجی متمایز. هر تغییری که می‌دهید باید دست‌کم یکی از این سه را جابه‌جا کند؛ اگر هیچ‌کدام تکان نخورد، آن تغییر بی‌اثر بوده است.

چطور منابع خارجی سایت را پیدا کنیم؟ فهرست میزبان‌ها با یک دستور

رایج‌ترین توصیه باز کردن تب Network ابزار توسعه‌دهنده است، اما آن نما به کش مرورگر، افزونه‌ها و وضعیت لحظه‌ای اتصال شما آلوده است. چیزی که می‌شود تحویل کسی داد یک دستور تکرارپذیر است که HTML خام را می‌شمارد (روی لینوکس با grep و sed گنو تست شده؛ روی macOS ggrep و gsed بگذارید یا از داخل خود سرور اجرا کنید):

curl -sL --max-time 25 https://mehranhost.cloud/ \
  | grep -oiE '(src|href)=["'"'"'](https?:)?//[^"'"'"']+' \
  | grep -oiE '(https?:)?//[^/"'"'"']+' \
  | tr 'A-Z' 'a-z' \
  | sed -E 's#^(https?:)?//##' \
  | sort | uniq -c | sort -rn

     66 www.mehranhost.cloud
      1 www.googletagmanager.com
      1 trustseal.enamad.ir

خروجی بالا اندازه‌گیری واقعی صفحه‌ی اصلی همین سایت در شهریور ۱۴۰۵ است: ۶۶ ارجاع به دامنه‌ی خودمان و دو میزبان شخص‌ثالث — گوگل تگ منیجر که واقعاً خارجی است، و مُهر اعتماد الکترونیکی که روی trustseal.enamad.ir و داخل ایران است و باید از دامنه‌ی خودش بیاید. روی یک سایت وردپرسی دست‌نخورده همین دستور معمولاً چهار تا هفت سطر می‌دهد و fonts.googleapis.com، cdn.jsdelivr.net و secure.gravatar.com بینشان‌اند. قرار نیست وانمود کنیم عدد صفر ساده به دست می‌آید؛ قرار است هر سطر را عمداً نگه داشته باشید.

هر سطری که دامنه‌ی خودتان نیست یک شاخه‌ی شخص‌ثالث است؛ حالا دامنه‌های .ir و میزبان‌های ایرانی را کنار بگذارید — چیزی که می‌ماند از مرز رد می‌شود. جزئیات دستور هم عمدی‌اند: (https?:)?// آدرس‌های پروتکل‌نسبی مثل //fonts.googleapis.com را می‌گیرد که در قالب‌های وردپرس فراوان‌اند، کلاس نویسه‌ی دوگانه صفت‌های تک‌کوتیشنی src='…' را می‌بیند، و tr با حروف بزرگ کنار می‌آید. نسخه‌ی ساده‌ترِ رایج در آزمایش ما از چهار میزبان خارجی فقط یکی را پیدا کرد.

یک لایه‌ی پنهان هم هست که این دستور نمی‌بیند: ارجاع‌های داخل فایل‌های CSS، مثل @import به فونت گوگل یا url() به تصویری روی میزبان دیگر. همان روش را یک لایه پایین‌تر تکرار کنید:

curl -sL https://example.ir/wp-content/themes/mytheme/style.css \
  | grep -oiE '(@import|url\()[^;)]*(https?:)?//[^"'"'"')]+' | sort -u

محدودیتش را صادقانه بگوییم: این دستورها فقط چیزی را می‌بینند که در HTML و CSS خام نوشته شده. اگر اسکریپتی هنگام اجرا میزبان تازه‌ای تزریق کند — تگ منیجر، ویجت چت، تبلیغ — در فهرست نمی‌آید و برای دیدنش به مرورگر واقعی نیاز دارید.

۸ وابستگی خارجی که تقریباً هر سایت ایرانی دارد

فهرست شما احتمالاً زیرمجموعه‌ای از این هشت مورد است. ستون وسط مهم‌ترین ستون است، چون از روی نشانه می‌شود بدون ابزار حدس زد کدام وابستگی مقصر است:

وابستگی خارجینشانه روی نت ملیجایگزین محلی
فونت گوگل با link یا importصفحه چند ثانیه سفید می‌ماند، بعد متن با قلم سیستم ظاهر می‌شود و چیدمان می‌پردمیزبانی woff2 زیرمجموعه‌شده روی دامنه‌ی خودتان با font-display: swap
کتابخانه‌ی جاوااسکریپت از CDN خارجیاسلایدر، منوی موبایل و فرم‌ها بی‌جواب می‌مانندنسخه‌ی پین‌شده روی سرور خودتان با نام فایل نسخه‌دار
فونت آیکون خارجیبه‌جای آیکون، مربع یا حرف تصادفی دیده می‌شودSVG درون‌خطی برای آیکون‌های پرکاربرد
آواتار گراواتار در نظراتبخش نظرات دیر کامل می‌شود و ردیف‌ها هنگام رسیدن تصاویر می‌پرندآواتار پیش‌فرض محلی یا آپلود روی هاست خودتان
ویدیو یا نقشه‌ی جاسازی‌شدهمستطیل خالی که هرگز کامل نمی‌شودسرویس ویدیوی ایرانی؛ برای نقشه یک تصویر ثابت با پیوند
اسکریپت آمار و تگ منیجر خارجیصفحه دیر کامل می‌شود و آمار بازدید ناقص ثبت می‌شودآمارگیر روی همان هاست یا سرویس آمار ایرانی
ویجت نظرات یا تبلیغ خارجیبلوکی که هرگز پر نمی‌شود و ارتفاع صفحه را جابه‌جا می‌کندسامانه‌ی نظرات خود سیستم مدیریت محتوا
تصویر میزبانی‌شده روی سرویس خارجیجای خالی تصویر، به‌ویژه در محتوای قدیمیِ کپی‌شدهانتقال فایل‌ها به سرور خودتان و بازنویسی آدرس‌ها

سه ردیف اول ظاهر و کارکرد صفحه را می‌شکنند و اولویت فوری‌اند؛ بقیه روی زمان تکمیل صفحه اثر می‌گذارند و نوبت دومی‌اند.

حذف فونت گوگل از وردپرس و میزبانی فونت فارسی روی دامنه‌ی خودتان

فونت فارسی تقریباً همیشه سنگین‌ترین وابستگی یک سایت ایرانی است: هم حجیم است و هم با link مسدودکننده‌ی رندر می‌شود.

۱ — فقط woff2 و فقط زیرمجموعه‌ی لازم

طبق راهنمای فونت وب در web.dev فرمت WOFF2 حدود ۳۰ درصد بهتر از WOFF فشرده می‌شود و مرورگرهای امروزی به فرمت دیگری نیاز ندارند. قدم بعد زیرمجموعه‌سازی است، چون فونت‌های فارسی معمولاً لاتین گسترده، یونانی، سیریلیک و ده‌ها ویژگی OpenType بلااستفاده را هم حمل می‌کنند. ابزار استانداردش pyftsubset از بسته‌ی fontTools است:

pyftsubset Vazirmatn.woff2 \
  --output-file=Vazirmatn-fa.woff2 --flavor=woff2 \
  --layout-features=ccmp,init,medi,fina,isol,rlig,liga,calt,locl,mark,mkmk,curs,kern \
  --unicodes="U+0020-007E,U+00A0,U+00AB,U+00BB,U+00D7,U+0600-06FF,U+200C-200F,U+2010-2015,U+2018-201D,U+2022,U+2026,U+2212,U+FB50-FDFF,U+FE70-FEFF"

دو جزئیات این محدوده را جدی بگیرید. گیومه‌های فارسی («»)، خط تیره‌ی بلند (—) و سه‌نقطه (…) در بلوک عربی نیستند و در فهرست‌های کوتاهی که در وب فارسی دست‌به‌دست می‌شود جا می‌افتند؛ نگهشان ندارید، متن فارسی شما با مربع خالی رندر می‌شود. و کل بلوک U+0600-06FF را نگه داشته‌ایم، نه فقط از U+0621 به بعد، تا متن واردشده‌ی کاربران هم سالم بماند.

نتیجه روی همین سایت با fontTools 4.27.1 در شهریور ۱۴۰۵: Vazirmatn از ۱۰۹ به ۶۱ کیلوبایت رسید — ۴۳ درصد کوچک‌تر — و مجموع چهار قلم لازم صفحه‌ها از ۱۸۸ به ۱۲۶ کیلوبایت آمد: حدود ۶۲ کیلوبایت کمتر در هر بازدید اول. ساخت واقعی سایت هر نویسه‌ای را که صفحه‌ها رندر می‌کنند هم نگه داشته، پس دستور بالا کمی کوچک‌تر درمی‌آید (۵۹ کیلوبایت). عددی که مهم است درصد است، نه بایت دقیق.

⚠️ سوئیچ --layout-features را دست‌کم نگیرید: اگر ویژگی‌های شکل‌دهی عربی — ccmp، init، medi، fina، isol، rlig، calt، mark و kern — را نگه ندارید، حروف فارسی به هم نمی‌چسبند. رایج‌ترین راه خراب‌کردن اتصال حروف همین است؛ دو راه کم‌پیش‌آمدتر هم هست: font-variant-ligatures: none یا font-feature-settings نادرست در CSS، و استک قلم جایگزینی که هیچ فونت عربی‌دار در آن نیست. بعد از هر زیرمجموعه‌سازی «می‌شود» و «کتاب‌های» را چشمی بررسی کنید.

۲ — اعلام فونت در CSS با font-display: swap

طبق مستندات font-display در MDN، مقدار swap «یک دوره‌ی انسداد بسیار کوتاه و یک دوره‌ی تعویض بی‌نهایت» می‌دهد: مرورگر تقریباً بلافاصله متن را با قلم جایگزین نشان می‌دهد و هر وقت فونت اصلی رسید جایش می‌گذارد. روی شبکه‌ی کند، تفاوت «متن را می‌خوانم» و «صفحه سفید است» همین یک خط است.

@font-face {
  font-family: "Vazirmatn";
  src: url("/assets/fonts/Vazirmatn-fa.woff2") format("woff2");
  font-weight: 100 900;      /* one variable file instead of five static ones */
  font-display: swap;
}

۳ — پیش‌بارگذاری، آن هم فقط یک وزن

مرورگر تا CSS را نخواند نمی‌فهمد فونتی لازم دارد و preload این تأخیر را حذف می‌کند. فایل فونت حتی روی دامنه‌ی خودتان هم از مسیر CORS درخواست می‌شود، پس صفت crossorigin اجباری است و بدون آن مرورگر فایل را دو بار می‌گیرد؛ و فقط یک وزن را پیش‌بارگذاری کنید، چون اولویت را از منابع دیگر می‌گیرد.

<link rel="preload" href="/assets/fonts/Vazirmatn-fa.woff2"
      as="font" type="font/woff2" crossorigin>

و بخش صادقانه، چون در این باره ادعاهای نادرست زیاد گفته می‌شود: اگر فونت وب نرسد، مرورگر به قلم سیستمی برمی‌گردد و متن فارسی درست و خوانا رندر می‌شود — نیم‌فاصله سر جایش می‌ماند و حروف به هم می‌چسبند، چون این کار موتور شکل‌دهی متنِ سیستم‌عامل است نه کار فونت شما. آنچه واقعاً خراب می‌شود عرض متفاوت حروف است: طول خطوط عوض می‌شود، لحظه‌ی رسیدن فونت اصلی صفحه محسوس می‌پرد و تایپوگرافی فارسی از دست می‌رود.

اسکریپت‌ها، آیکون‌ها و کتابخانه‌ها: از CDN خارجی به سرور خودتان

الگوی کار برای هر کتابخانه‌ای یکسان است. اول نسخه‌ی دقیقی را که همین حالا استفاده می‌کنید پیدا کنید — نه «آخرین نسخه»، چون به‌روزرسانی و انتقال را نباید هم‌زمان انجام داد. بعد فایل را در شاخه‌ای مثل /assets/vendor/ با نام نسخه‌دار بگذارید و آدرس را عوض کنید. و قدمی که همه فراموش می‌کنند: هدرهای تحویل را بررسی کنید.

curl -sI --compressed https://example.ir/assets/vendor/lib-3.7.1.min.js | grep -iE 'HTTP/|cache-control|content-encoding|content-length'

HTTP/2 200
cache-control: public, max-age=31536000, immutable
content-encoding: br
content-length: 31544

سوئیچ --compressed ضروری است: بدون آن curl هدر Accept-Encoding نمی‌فرستد و content-encoding هرگز در خروجی ظاهر نمی‌شود — یعنی روی سروری که Brotli‌اش درست کار می‌کند هم به نتیجه‌ی غلط «فشرده‌سازی خاموش است» می‌رسید. روی یک فایل همین سایت، بدون این سوئیچ فقط content-length: 11006 دیده می‌شود و با آن content-encoding: br و content-length: 3418. خواندن بقیه ساده است: cache-control کوتاه یعنی فقط فاصله را کم کرده‌اید و هنوز در هر بازدید هزینه‌ی دانلود را می‌پردازید؛ و اگر با --compressed هم رمزگذاری خالی بماند، فشرده‌سازی واقعاً روشن نیست. چون نام فایل نسخه‌دار است، عمر کش یک‌ساله بی‌خطر است.

برای آیکون‌ها راه بهتری هست: بیشتر سایت‌ها از یک فونت آیکونِ چندصدکیلوبایتی فقط ده تا پانزده آیکون استفاده می‌کنند؛ همان‌ها را به‌صورت SVG درون‌خطی در قالب بگذارید تا وابستگی و درخواستش با هم حذف شود. در وردپرس منشأ این آدرس‌ها معمولاً قالب یا افزونه است و اصولی‌ترین راه ثبت دوباره‌ی همان منبع با آدرس محلی است — در راهنمای افزایش سرعت وردپرس بازش کرده‌ایم.

⚠️ با محلی‌کردن یک کتابخانه، مسئولیت وصله‌کردنش را هم تحویل می‌گیرید. نسخه‌ای که امروز دانلود می‌کنید تا ابد همان می‌ماند مگر خودتان به‌روزش کنید، و یک کتابخانه‌ی قدیمی با آسیب‌پذیری شناخته‌شده مشکل بزرگ‌تری از کندی است. نسخه و تاریخ هر فایل را یادداشت و فصلی یک‌بار مرور کنید.

چه چیزهایی را نباید محلی کنید

حذف وابستگی خارجی هدف مطلق نیست؛ بعضی سرویس‌ها باید از میزبان اصلی خودشان بارگذاری شوند و کپی‌کردنشان یا کار نمی‌کند یا خطرناک است.

  • reCAPTCHA و سرویس‌های ضدربات مشابه. مدل امنیتی این ابزارها بر پایه‌ی ارتباط مستقیم مرورگر با سرور ارائه‌دهنده است و کپی محلی اسکریپت بی‌معناست. اما یک راه‌حل رسمی و کمتر شناخته‌شده هست: پرسش‌های متداول reCAPTCHA می‌گوید وقتی www.google.com در دسترس نیست، از www.recaptcha.net در کد خود استفاده کنید. راه‌حل عوض‌کردن میزبان است، نه محلی‌کردن — اما کامل نیست: خودِ api.js که از recaptcha.net می‌آید هنوز به www.gstatic.com ارجاع می‌دهد؛ با همان دستور بخش قبل روی آن فایل ببینیدش. اگر باز هم فرم‌ها روی نت ملی کار نکردند سراغ کپچای خودمیزبان یا سرویس ضدربات ایرانی بروید. و نکته‌ی ۱۴۰۵: طبق راهنمای مهاجرت reCAPTCHA کلاسیک در Google Cloud کلیدهای قدیمی به Google Cloud منتقل شده‌اند و سقف رایگان روی ۱۰٬۰۰۰ ارزیابی در ماه نشسته است.
  • اسکریپت درگاه پرداخت. هر کدی که در مسیر تراکنش است باید مستقیماً از خود ارائه‌دهنده بیاید. خبر خوب اینکه درگاه‌های پرداخت ایرانی داخلی‌اند و از گذرگاه بین‌الملل عبور نمی‌کنند.
  • هر چیزی که پروانه‌اش بازتوزیع را ممنوع کرده — نقشه‌های تجاری، فونت‌های با پروانه‌ی محدود و APIهای کلیددار.
  • هر چیزی که نمی‌توانید به‌روز نگه دارید. اگر برای کتابخانه‌ای فرایند به‌روزرسانی ندارید، نسخه‌ی میزبانی‌شده‌ی ارائه‌دهنده امن‌تر از نسخه‌ی فراموش‌شده‌ی شماست.

برای موارد باقی‌مانده به‌جای حذف، تنبل‌سازی کنید: ویدیو و نقشه را با تصویری ثابت و سبک جایگزین و بارگذاری واقعی را به کلیک کاربر موکول کنید.

وزن صفحه و هدرهای کش: چطور حجم و تعداد درخواست را کم کنیم؟

یک خطای ذهنی رایج این است که همه‌ی کندی را به فاصله نسبت می‌دهیم. اما وقتی گذرگاه بین‌الملل تحت فشار است فقط تأخیر بالا نمی‌رود؛ پهنای باند مؤثر هر اتصال هم پایین می‌آید و صفحه‌ی چهار مگابایتی حتی از نزدیک‌ترین نود ممکن هم تجربه‌ی خوبی نمی‌سازد. کم‌کردن بایت‌ها به اندازه‌ی کوتاه‌کردن مسیر ارزش دارد — و برخلاف کاهش TTFB که به مسیر و سرور گره خورده، تمامش در اختیار خودتان است.

سه اهرم، به ترتیب بازدهی: تصاویر که بزرگ‌ترین سهم را دارند و تبدیلشان به WebP یا AVIF اغلب نیمی از وزن صفحه را حذف می‌کند؛ فشرده‌سازی متن با Brotli یا دست‌کم gzip که یک تنظیم یک‌باره روی وب‌سرور است؛ و هدرهای کش که بازدید دوم را تقریباً بی‌هزینه می‌کنند — فایل‌های ایستای نسخه‌دار با max-age=31536000, immutable و خودِ HTML با عمر کوتاه. معنای دقیق هر هدر در مستندات کش HTTP در MDN آمده است.

و اهرم چهارم: تعداد درخواست. هر فایل جدا حتی روی HTTP/2 هزینه‌ی خودش را دارد و روی شبکه‌ی پرنوسان چند برابر می‌شود؛ صفحه‌ای با بیش از ۹۰ درخواست تقریباً همیشه ارزش یک مرور خط‌به‌خط را دارد؛ در وردپرس منشأ بیشترِ این درخواست‌ها معمولاً قالب و افزونه‌هایی است که فایل‌هایشان را در هر صفحه بار می‌کنند، حتی جایی که استفاده نمی‌شوند. تصاویر پایین صفحه را با loading="lazy" عقب بیندازید — اما هرگز روی تصویر اصلی بالای صفحه.

CDN با نود ایران چه می‌کند و چه نمی‌کند؟

وقتی وابستگی‌های خارجی حذف شد، قرار دادن یک نود لبه‌ی داخل ایران جلوی سایت معنا پیدا می‌کند. رکورد عمومی دامنه به‌جای آی‌پی سرور اصلی به نودهای لبه اشاره می‌کند و درخواست هر بازدیدکننده اول به نزدیک‌ترین نود می‌رسد — مکانیک HIT و MISS را در راهنمای CDN چیست باز کرده‌ایم. آنچه اینجا اهمیت دارد مرز توانایی این کار است.

دیاگرام افزایش سرعت سایت در نت ملی: مسیر داخلی بازدیدکننده تا نود لبه‌ی ایران در برابر مسیرهای خارجی صفحه به فونت، اسکریپت و آمار بیرون از مرز

نود لبه‌ی داخل ایران چه می‌کند: اگر مبدأ شما داخل ایران باشد و نود ایران در محدوده‌ی سایت قرار بگیرد، تمام محتوای ایستای کش‌شده — تصویر، CSS، جاوااسکریپت، فونت — برای بازدیدکننده‌ی ایرانی از داخل کشور سرو می‌شود؛ اگر مبدأ بیرون از کشور باشد همان محتوا از نزدیک‌ترین نود بین‌الملل می‌آید که باز هم نزدیک‌تر از مبدأ است. در هر دو حالت آی‌پی سرور اصلی پنهان می‌ماند و لبه می‌تواند سقف نرخ درخواست بگذارد.

و نود لبه چه نمی‌کند: وابستگی‌های خارجیِ صفحه‌ی شما را محلی نمی‌کند. اگر قالب شما هنوز به فونت گوگل اشاره کند، مرورگر کاربر مستقیماً سراغ گوگل می‌رود و CDN شما در آن مسیر نیست. اگر سرور اصلی خارج از ایران باشد، هر پاسخ کش‌نشده — تقریباً همه‌ی HTML شخصی‌شده و هر عمل دینامیکی — همچنان یک رفت‌وبرگشت کامل از گذرگاه بین‌الملل است. و کش لبه چیزی نیست که خودتان روشنش کنید: HTML از پیش مدت کوتاهی و فایل‌های ایستا مدت طولانی کش می‌شوند و تنها تنظیم دست شما «شدت کش» است — استاندارد، تهاجمی با HTML شش‌ساعته، یا بدون کش. پس ترتیب کارها مهم است: اول وابستگی‌ها را حذف کنید، بعد نود را جلو بنشانید.

در پنل مهران هاست این کار کنار هر رکورد A با یک کلید انجام می‌شود و محدوده‌ی نودها قابل‌انتخاب است. روی «خودکار»، سامانه بررسی می‌کند سرور مبدأ کجاست و بر همان اساس تصمیم می‌گیرد: مبدأ داخل ایران باشد همه‌ی نودها فعال می‌شوند؛ مبدأ بیرون باشد — یا اندازه‌گیری قطعی نباشد — فقط نودهای بین‌الملل، که انتخاب امنِ پیش‌فرض است. هر کدام را دستی هم می‌توانید تعیین کنید، ولی گزینه‌ی «همه‌ی نودها» در پنل صراحتاً برای مبدأ داخل ایران برچسب خورده است. اگر رکورد A برایتان تازه است، راهنمای رکوردهای DNS را ببینید.

سرور مبدأ کجا باشد؟ هاست ایران یا هاست خارج

محل سرور مبدأ را نود لبه کم‌اهمیت می‌کند اما حذف نمی‌کند، چون هر پاسخ کش‌نشده مستقیماً به مبدأ می‌رود. قاعده‌ی تصمیم عددی است، نه سلیقه‌ای: از لاگ سرور سهم درخواست‌های کش‌نشدنی را دربیاورید — HTML شخصی‌شده، سبد خرید، پیشخوان، جست‌وجو. هرچه این سهم بزرگ‌تر باشد، محل مبدأ تعیین‌کننده‌تر است و نود لبه کمتر از دستتان می‌گیرد. اگر بیشتر بازدیدکنندگان داخل ایران‌اند و سرویس شما الزامی برای ماندن در خارج ندارد، مبدأ داخل ایران هر رفت‌وبرگشت کش‌نشده را هم داخلی می‌کند؛ معیارهای عددی این انتخاب در مقایسه‌ی هاست ایران و هاست خارج آمده است.

اما بعضی بارها واقعاً باید بیرون بمانند: سرویسی که به APIهای خارجی وابسته است، یا سایتی که مخاطب اصلی‌اش بیرون از کشور است. اینجا باید صریح باشیم، چون توصیه‌ی رایج غلط است: نشاندن نود ایران جلوی یک مبدأ خارجی کمکی نمی‌کند و معمولاً کندتر هم درمی‌آید، چون بازدیدکننده‌ی ایرانی را می‌فرستد به نود داخل کشور و از آنجا دوباره به آن‌سوی مرز — به همین دلیل روی «خودکار» با مبدأ خارجی، نود ایران عمداً کنار گذاشته می‌شود. راه‌حل واقعی این است: مبدأ همان‌جا بماند، سایت پشت نودهای بین‌الملل برود، و تمام انرژی خرج حذف وابستگی‌های خارجی صفحه و کم‌کردن وزن آن شود. اگر می‌خواهید بازدیدکننده‌ی ایرانی برای خودِ متن هم از مرز رد نشود، راهش آوردن مبدأ به داخل ایران است. محاسبه‌ی ترافیک بین مبدأ و لبه در راهنمای پهنای باند سرور مجازی آمده است.

چک‌لیست ده قدمی افزایش سرعت سایت در نت ملی

چک‌لیست زیر همه‌ی کاری است که برای افزایش سرعت سایت در نت ملی لازم دارید؛ ترتیبش عمدی است — از ارزان‌ترین و پرتأثیرترین تا تصمیم‌های زیرساختی.

  1. خط پایه بگیرید: دستور زمان‌بندی curl را از شبکه‌ی داخلی اجرا و شش عدد را ذخیره کنید.
  2. فهرست میزبان‌های خارجی صفحه را با grep بگیرید و تعدادشان را یادداشت کنید.
  3. فایل‌های CSS اصلی را جدا برای @import و url() خارجی بررسی کنید.
  4. فونت را محلی، زیرمجموعه و woff2 کنید و ویژگی‌های شکل‌دهی عربی را نگه دارید.
  5. یک وزن فونت را با crossorigin پیش‌بارگذاری و font-display: swap را اعلام کنید.
  6. کتابخانه‌های جاوااسکریپت را با نسخه‌ی پین‌شده به سرور خودتان بیاورید.
  7. فونت آیکون را با SVG درون‌خطی جایگزین کنید.
  8. ویدیو، نقشه و ویجت‌های خارجی باقی‌مانده را تنبل کنید.
  9. فشرده‌سازی و هدرهای کش را بررسی و تصاویر را به WebP یا AVIF ببرید.
  10. نود لبه‌ی داخل ایران را جلوی سایت بنشانید و درباره‌ی محل مبدأ تصمیم بگیرید.

و قدم آخر که در واقع قدم اول بود: همان سه عدد را دوباره بگیرید. اگر میزبان‌های خارجی از هفت به دو رسیده و حجم صفحه نصف شده، کار درست انجام شده؛ اگر هیچ‌کدام تکان نخورده، هر ادعایی درباره‌ی «بهبود سرعت» فقط حس شخصی است.

ابزار و CDN مهران هاست

آزمون رایگان سرعت و سلامت سایت ثبت‌نام نمی‌خواهد و برای مهمان‌ها روزانه سه بررسی روی هر دامنه اجازه می‌دهد، به‌علاوه‌ی یک سقف روزانه برای هر اتصال؛ با ورود به حساب کاربری محدودیت هر دامنه برداشته می‌شود. اندازه‌گیری از سرور خودِ سرویس انجام می‌شود — نه از شبکه‌ی کاربران شما — پس آن را برای عددهای ساختاری صفحه به کار ببرید و مسیر شبکه را جداگانه با curl بسنجید. گزارش، TTFB را به مراحل DNS، TCP، TLS و زمان پردازش سرور می‌شکند، تعداد درخواست‌ها را می‌شمارد و حجم کل صفحه را از روی نمونه‌ای از فایل‌های آن تخمین می‌زند — در گزارش هم همین را با برچسب «تخمینی» صریح می‌گوید — وجود CDN را تشخیص می‌دهد، آی‌پی و ASN میزبان و وضعیت SSL را نشان می‌دهد و نمره‌ای صفر تا صد در چهار دسته‌ی سرعت، بهینه‌سازی، امنیت و «کیفیت و سئو» می‌دهد، با وزن‌های ۴۰، ۲۵، ۲۰ و ۱۵ درصد و همان آستانه‌هایی که بالاتر نقل کردیم.

CDN مهران هاست نودهایش در ایران و اروپا مستقرند، با یک کلید کنار رکورد A روشن می‌شود، آی‌پی مبدأ را پنهان می‌کند، SSL را خودکار صادر می‌کند، Brotli و HTTP/2 و HTTP/3 دارد، سقف نرخ درخواست می‌گذارد، آمار هر نود را جدا نشان می‌دهد و تبدیل JPEG و PNG به WebP و AVIF روی لبه را در اختیارتان می‌گذارد — گزینه‌ای که برای هر سایت جداگانه روشن می‌کنید و در حالت «بدون کش» اعمال نمی‌شود. روی دامنه‌ای که DNS آن به مهران هاست سپرده شده هزینه‌ی جداگانه‌ای ندارد، و برای آوردن مبدأ به داخل ایران صفحه‌ی میزبانی وب گزینه‌ها را نشان می‌دهد. اما همان نکته‌ی بخش CDN را تکرار می‌کنیم: هیچ‌کدام خط فونت گوگل را از قالب شما پاک نمی‌کند. آن قدم اول است و مال شماست.

سؤالات پرتکرار

چرا سایتم روی نت ملی کند می‌شود ولی روی اینترنت بین‌الملل سریع است؟

سایت روی نت ملی کند می‌شود چون صفحه‌ی شما به میزبان‌هایی بیرون از ایران اشاره می‌کند و مرورگر برای هر کدام باید از گذرگاه بین‌الملل عبور کند؛ رایج‌ترینشان فونت گوگل، کتابخانه‌های جاوااسکریپت روی CDN خارجی، فونت آیکون و اسکریپت آمار است. سرور خودتان ممکن است سالم و داخل ایران باشد؛ آنچه کند می‌شود شاخه‌های خارجی صفحه است و با curl و grep روی HTML خام پیدا می‌شود.

حذف فونت گوگل از وردپرس چطور انجام می‌شود و چه چیزی را خراب می‌کند؟

حذف فونت گوگل از وردپرس در چهار قدم انجام می‌شود: فایل woff2 فونت را روی سرور خودتان بگذارید، با pyftsubset به محدوده‌ی فارسی زیرمجموعه کنید، در CSS با font-display: swap اعلامش کنید و آدرس فونت گوگل را بردارید. اگر فونت نرسد مرورگر به قلم سیستمی برمی‌گردد و متن فارسی همچنان درست و متصل رندر می‌شود؛ آنچه خراب می‌شود تناسب تایپوگرافی و یک پرش چیدمان است. رایج‌ترین راه شکستن اتصال حروف، حذف ویژگی‌های شکل‌دهی عربی هنگام زیرمجموعه‌سازی است.

چطور از داخل ایران سرعت سایتم را تست کنم؟

برای تست سرعت سایت از داخل ایران، معتبرترین راه اجرای دستور curl با قالب خروجی سفارشی از دستگاهی است که روی همان شبکه نشسته باشد — نه از خود سرور — چون زمان DNS، TCP، TLS و اولین بایت را جدا گزارش می‌کند. ابزارهای آنلاین، از جمله آزمون سرعت سایت مهران هاست، درخواست را از سرور خودشان می‌فرستند و مسیر شبکه‌ی شما را نمی‌بینند؛ در عوض حجم صفحه، تعداد درخواست‌ها، تشخیص CDN و وضعیت SSL را می‌دهند که به شبکه وابسته نیستند.

آیا CDN با نود ایران مشکل کندی نت ملی را کامل حل می‌کند؟

CDN با نود ایران مشکل کندی نت ملی را کامل حل نمی‌کند. نود لبه‌ی داخل ایران محتوای ایستای کش‌شده را از داخل کشور تحویل می‌دهد — به شرط آنکه سرور مبدأ هم داخل ایران باشد — اما وابستگی‌های خارجی صفحه را محلی نمی‌کند: اگر قالب شما به فونت گوگل اشاره کند، مرورگر کاربر مستقیماً سراغ گوگل می‌رود و CDN در آن مسیر نیست. ترتیب درست: اول حذف وابستگی‌ها، بعد نود لبه.

سایتم روی نت ملی اصلاً باز نمی‌شود؛ از کجا شروع کنم؟

سایتی که روی نت ملی اصلاً باز نمی‌شود به احتمال زیاد یک وابستگی مسدودکننده‌ی خارجی در مسیر بحرانی دارد — معمولاً فایل CSS یا اسکریپتی بدون defer روی میزبانی که پاسخ نمی‌دهد؛ مرورگر ده‌ها ثانیه صبر می‌کند و کاربر صفحه‌ی سفید می‌بیند. اول با curl بررسی کنید سرور خودتان پاسخ می‌دهد یا نه، سپس فهرست میزبان‌های خارجی را بگیرید و ارجاع‌های مسدودکننده را حذف کنید.

آموزش‌های مرتبط

آماده‌ی تمرین عملی هستید؟

سرور ابری ساعتی مهران هاست در ۶۰ ثانیه تحویل می‌شود — تمرین کنید و فقط بابت همان ساعت‌ها پرداخت کنید. هزینه را پیش از ثبت‌نام با محاسبه‌گر برآورد کنید.