تاریخ انتشار: ۲۳ نوامبر ۲۰۲۴
توسعه مبتنی بر ماژول برخی از مزایای واقعی را از نظر حافظه پنهان ارائه می دهد و به شما کمک می کند تعداد بایت هایی را که برای ارسال به کاربران خود نیاز دارید کاهش دهید. جزئیات دقیق کد نیز به بارگذاری داستان کمک می کند و به شما امکان می دهد کدهای مهم را در برنامه خود اولویت بندی کنید.
با این حال، وابستگی های ماژول یک مشکل بارگذاری را ایجاد می کند، به این ترتیب که مرورگر باید منتظر بماند تا یک ماژول بارگذاری شود تا بفهمد وابستگی های آن چیست. یکی از راههای حل این مشکل، بارگذاری پیشفرض وابستگیها است، به طوری که مرورگر از همه فایلها از قبل مطلع شود و بتواند اتصال را مشغول نگه دارد.
<link rel="preload">
<link rel="preload">
روشی است برای درخواست آشکار منابع از قبل، قبل از اینکه مرورگر به آنها نیاز داشته باشد.
<head>
<link rel="preload" as="style" href="critical-styles.css">
<link rel="preload" as="font" crossorigin type="font/woff2" href="myfont.woff2">
</head>
این امر بهویژه با منابعی مانند فونتها که اغلب در فایلهای CSS پنهان میشوند، به خوبی کار میکند. در این شرایط، مرورگر باید قبل از اینکه بفهمد که باید یک فایل فونت بزرگ را واکشی کند، منتظر چندین بار رفت و برگشت باشد، در حالی که میتوانست از آن زمان برای شروع دانلود و استفاده از پهنای باند اتصال کامل استفاده کند.
<link rel="preload">
و معادل سرصفحه HTTP آن، روشی ساده و شفاف را برای اطلاع دادن فوری به مرورگر در مورد فایلهای مهمی که به عنوان بخشی از پیمایش فعلی مورد نیاز هستند، ارائه میکند. وقتی مرورگر پیش بارگذاری را میبیند، بارگیری با اولویت بالا را برای منبع شروع میکند، به طوری که تا زمانی که واقعاً به آن نیاز است، یا قبلاً واکشی شده باشد یا تا حدی وجود داشته باشد. با این حال، برای ماژول ها کار نمی کند.
چرا <link rel="preload">
برای ماژول ها کار نمی کند؟
اینجاست که همه چیز پیچیده می شود. چندین حالت اعتبار برای منابع وجود دارد، و برای به دست آوردن ضربه کش باید مطابقت داشته باشند، در غیر این صورت در نهایت دوبار منبع را واکشی می کنید. نیازی به گفتن نیست که واکشی مضاعف بد است، زیرا پهنای باند کاربر را هدر می دهد و باعث می شود بدون هیچ دلیل موجهی بیشتر منتظر بمانند.
برای تگهای <script>
و <link>
، میتوانید حالت اعتبار را با ویژگی crossorigin
تنظیم کنید. با این حال، به نظر می رسد که یک <script type="module">
بدون ویژگی crossorigin
، یک حالت اعتبارنامه omit
را نشان می دهد، که برای <link rel="preload">
وجود ندارد. این بدان معنی است که شما باید ویژگی crossorigin
را در هر دو <script>
و <link>
خود به یکی از مقادیر دیگر تغییر دهید، و ممکن است راه آسانی برای انجام این کار نداشته باشید اگر آنچه میخواهید از قبل بارگذاری کنید یک وابستگی باشد. از ماژول های دیگر
علاوه بر این، واکشی فایل تنها اولین قدم در اجرای واقعی کد است. ابتدا مرورگر باید آن را تجزیه و کامپایل کند. در حالت ایده آل، این باید زودتر از موعد اتفاق بیفتد، به طوری که زمانی که ماژول مورد نیاز است، کد آماده اجرا شود. با این حال، V8 (موتور جاوا اسکریپت کروم) ماژول ها را متفاوت از جاوا اسکریپت های دیگر تجزیه و کامپایل می کند. <link rel="preload">
هیچ راهی برای نشان دادن اینکه فایل در حال بارگذاری یک ماژول است ارائه نمی دهد، بنابراین تمام کاری که مرورگر می تواند انجام دهد این است که فایل را بارگیری کرده و در حافظه پنهان قرار دهد. هنگامی که اسکریپت با استفاده از یک تگ <script type="module">
بارگیری می شود (یا توسط ماژول دیگری بارگیری می شود)، مرورگر کد را به عنوان یک ماژول جاوا اسکریپت تجزیه و کامپایل می کند.
بنابراین آیا <link rel="modulepreload">
فقط <link rel="preload">
برای ماژول ها است؟
به طور خلاصه، بله. با داشتن یک نوع link
خاص برای بارگذاری ماژولها، میتوانیم HTML ساده بنویسیم بدون اینکه نگران این باشیم که از چه حالت اعتباری استفاده میکنیم. پیش فرض ها فقط کار می کنند.
<head>
<link rel="modulepreload" href="super-critical-stuff.mjs">
</head>
[...]
<script type="module" src="super-critical-stuff.mjs">
و از آنجایی که مرورگر اکنون میداند که چیزی که از قبل بارگذاری میکنید یک ماژول است، میتواند هوشمند باشد و بهمحض اینکه واکشی ماژول را انجام داد، به جای اینکه منتظر بماند تا زمانی که اجرا شود، آن را تجزیه و کامپایل کند.
اما در مورد وابستگی های ماژول ها چطور؟
خنده دار است که باید بپرسید! در واقع چیزی وجود دارد که این مقاله پوشش نداده است: بازگشت.
مشخصات <link rel="modulepreload">
در واقع اجازه بارگیری اختیاری نه تنها ماژول درخواستی، بلکه تمام درخت وابستگی آن را نیز می دهد. مرورگرها مجبور نیستند این کار را انجام دهند، اما می توانند.
بنابراین بهترین راه حل بین مرورگر برای از پیش بارگذاری یک ماژول و درخت وابستگی آن چیست، زیرا برای اجرای برنامه به درخت وابستگی کامل نیاز دارید؟
مرورگرهایی که انتخاب میکنند وابستگیها را به صورت بازگشتی از قبل بارگذاری کنند، باید ماژولها را از پیش بارگذاری کنند، بنابراین به طور کلی بهترین کار این است که ماژول و لیست مسطح وابستگیهای آن را اعلام کنیم و به مرورگر اعتماد کنیم که یک ماژول را دو بار واکشی نکند.
<head>
<!-- dog.js imports dog-head.js, which in turn imports
dog-head-mouth.js, which imports dog-head-mouth-tongue.js. -->
<link rel="modulepreload" href="dog-head-mouth-tongue.mjs">
<link rel="modulepreload" href="dog-head-mouth.mjs">
<link rel="modulepreload" href="dog-head.mjs">
<link rel="modulepreload" href="dog.mjs">
</head>
آیا پیش بارگذاری ماژول ها به عملکرد کمک می کند؟
بارگذاری پیشبار میتواند به به حداکثر رساندن استفاده از پهنای باند کمک کند، با گفتن اینکه مرورگر در مورد آنچه باید واکشی کند، به طوری که در طول این رفت و برگشتهای طولانی هیچ کاری برای انجام دادن گیر نکند. اگر با ماژولها آزمایش میکنید و به دلیل درختهای وابستگی عمیق با مشکلات عملکرد مواجه میشوید، ایجاد یک لیست صاف از پیشبارگذاریها قطعاً میتواند به شما کمک کند.
همانطور که گفته شد، عملکرد ماژول هنوز در حال کار است، بنابراین مطمئن شوید که با ابزار Developer Tools به اتفاقاتی که در برنامه شما می افتد نگاهی دقیق بیندازید و در این بین برنامه خود را به چند بخش دسته بندی کنید. با این حال، ماژولهای زیادی در کروم در حال انجام است، بنابراین ما به باندلرها نزدیکتر میشویم که به خوبی به دست آوردهاند!