ایمپورت دینامیک در جاوا اسکریپت – از صفر تا صد


ما از نسخه ES2020 به بعد به طور رسمی میتوانیم از امکان ایمپورت دینامیک استفاده کنیم. این قابلیت علاوه بر همه قابلیتهای دیگر نسخه جدید ES بسیار برجسته به نظر میرسد. در این راهنما به بررسی تفاوتهای بین ایمپورت معمولی و ایمپورت دینامیک در جاوا اسکریپت و بحث «درختتکانی» (Tree Shaking) میپردازیم.
درختتکانی یعنی چه؟
درختتکانی در واقع نامی دیگر برای حذف کدهای مرده است که به همراه Webpack وارد دنیای جاوا اسکریپت شده است. با این که این مفهوم از مدتها پیش مطرح بوده است، اما Webpack شروع به استفاده از این نام برای آن کرده و حتی روشی برای اجرای عملیات حذف کدهای مرده فراهم ساخته است.
درختتکانی میتواند موجب کاهش اندازه فایل باندلشده جاوا اسکریپت شود. این عملیات تنها با ساختار import و export کار میکند. بنابراین require که یک ساختار رایج جاوا اسکریپت است، پشتیبانی نمیشود. برای نمونه Webpack برای هر ماژول نامی تعیین میکند و شامل ماژولهایی است که از فایلهای دیگر در فایل باندل شده در زمان بیلد فراخوانی میشوند.
تنظیمات پروژه
ما در این راهنما از پروژه زیر استفاده میکنیم:
چهار تابع در فایل a.ts وجود دارند و یکی فایل اصلی پروژه است که تابع اکسپورت شده از a.ts را فرامیخواند.
Main.ts تنها add را ایمپورت میکند و آن را مورد استفاده قرار میدهد. تابعهای دیگر در این پروژه استفاده نمیشوند.
فایل تنظیمات Webpack به صورت زیر است:
mode را به صورت development تنظیم کردهایم، از این رو فایل باندل شده ویرایش نمیشود و به منظور درختتکانی، usedExported به صورت true تعیین میشود.
اکنون باید این کد را روی ترمینال اجرا کنیم.
نتیجه ایمپورت استاتیک (جزئی)
> npm run build
اینک فایل باندل شده است. فایل main.ts تابع pow را از a.ts با کلیدواژه import میگیرد.
// main.ts import { pow } from './a'; pow(1, 2);
در فایل bundle.js میتوانید کد زیر را ببینید:
علیرغم این که همه تابعهای اکسپورت شده در باندل گنجایش یافتهاند، اما تنها pow در عمل به دست میآید. همچنین پیام ...unused harmony export به اطلاع ما و وبپک میرساند که کدام یک اکسپورت شدهاند. نتیجه آن به صورت زیر است:
// main.ts import { pow, multiply } from './a'; pow(1, 2);
Multiply استفاده نشده است، گرچه ایمپورت شده است نتیجه فایل باندل شده یکسان است، یعنی وبپک متدهایی که در عمل استفاده شده را در لیست اکسپورت خود قرار داده است.
نتیجه ایمپورت استاتیک (کامل)
شاید کنجکاو باشید که در صورت ایمپورت کردن همه تابعها به صورت یکباره چه تفاوتی بروز مییابد؟
// main.ts import * as module from './a'; module.pow(1, 2);
نتیجه یکسان است. در مورد حالتی که تابع default وجود داشته باشد:
export default divide;
اکنون divide تابع پیشفرض است و هنگامی که تابعهای ایمپورت شونده ذکر نشده باشند، اکسپورت میشود.
// main.js import divide, { pow } from './a'; divide(1, 2); pow(1, 2);
نتیجه کمی متفاوت است:
اکنون وب پک divide را به صورت تابع اکسپورت پیشفرض اضافه میکند. اما نکته اینجا است که وبپک میداند کدام تابع در عمل استفاده میشود و آنها را به روش خاص خود دستهبندی میکند.
نکته
در مستندات رسمی وب پک اشاره شده است که تصمیمگیری واقعی در مورد این که کدام تابعها باید در فایلهای باندل قرار گیرند، کار بسیار دشواری است. همچنین در مورد عوارض جانبی هر تابع برای نمونه تغییر دادن مقادیر در دامنه بیرونی دامنه جاری صحبت شده است. تست کردن این مثال کاملاً آسان است.
نتیجه ایمپورت دینامیک
اکنون کد را طوری تغییر میدهیم که از ایمپورت دینامیک استفاده کند:
ایمپورت دینامیک یک promise بازگشت میدهد که میتوان به متدهای then یا catch وصل کرد. اگر فایل با موفقیت بارگذاری شود، نتیجه به then ارسال میشود. این متد یک پارامتر میگیرد که معمولاً نام آن module است. Module شامل تابع اکسپورت است. ایمپورت دینامیک اساساً به خاطر قابلیت غیر درختتکانی خود مشهور است. در ادامه وضعیت کنونی فایل باندل را بررسی میکنیم.
زمانی که دستور npm run build را اجرا میکنیم، یک فایل باندل جدید به نام 0.bundle.js ساخته میشود:
همه تابعها در لیست اکسپورت گنجایش یافتهاند. در حالت پروداکشن همه تابعهای استفاده نشده حذف میشوند. دلیل این که تابعهای استفاده نشده را نیز در فایلهای باندل شده میبینید، این است که mode در webpack.config.json به جای production روی development قرار دارد.
Mode را به صورت زیر عوض کنید:
این بخش را نیز حذف کنید:
اکنون دستور npm run build را اجرا کنید.
با ایمپورت استاتیک
چنان گه گفتیم ایمپورت دینامیک یک promise بازگشت میدهد که به then وصل میشود، اما به نظر میرسد که تنها تابع مورد استفاده در فایل باندل شده نیز گنجانده شده است.
فایلهای دیگری نیز وجود دارند:
همه تابعها در این فایل قرار گرفتهاند.
چرا ایمپورت دینامیک از درختتکانی پشتیبانی نمیکند؟
شاید تعجب کنید که چرا این قابلیت از درختتکانی پشتیبانی نمیکند. دلیل این امر آن است که زمانبندی ایمپورت کردن روشن نیست. برای نمونه فرض کنید تنها میخواهیم زمانی که عدد فرد است، ایمپورت کنیم:
وبپک نمیداند که آیا فایل در نهایت ایمپورت خواهد شد یا نه. زیرا isOdd تضمین نمیکند که همواره true باشد.
سخن پایانی
ایمپورت دینامیک قابلیتی عالی است زیرا زمان مورد نیاز برای بارگذاری همه تابعها و ماژولها را در زمان اجرا کاهش میدهد. همچنین میتوانید از ایمپورت کردن فایلهای غیرضروری در مواردی که نیازی به آنها ندارید خودداری کنید.
با این حال از آنجا که ایمپورت دینامیک امکان درختتکانی را نمیدهد، همه تابعهای آن ایمپورت خواهند شد و از این رو باید از این قابلیت به درستی استفاده شود.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای JavaScript (جاوا اسکریپت)
- مجموعه آموزشهای برنامهنویسی
- آموزش JavaScript ES6 (جاوا اسکریپت)
- ساخت اپلیکیشنهای مدرن با Webpack — به زبان ساده
- آموزش Webpack — مجموعه مقالات مجله فرادرس
==
سلام این مطلب شما از بسیاری از پاسخ به بعضی سوالات در خصوص موضوع مشابه در StackOverFlow بهتر بود. متشکرم.
اگر در مطلب پایانی
(window.webpackJsonp = window.webpackJsonp || []).push
کسی بخواهد یک تابع را از فایلی دیگر و یا کنسول فراخوانی کند چطور باید رفرنس بده.
مثلا این تابع:
var r = function(n, t) {
return Math.pow(n, t);