
در آخرین قسمت از این فصل باید به سراغ مبحث lazyloading آدرس ها یا همان URL ها برویم. اگر به برنامه خود برویم (در صفحه اصلی) دو لینک Home و User را داریم. لینکِ Home، همان صفحه اصلی است که در آن هستیم (به آدرس http://localhost:8080/) اما اگر روی User کلیک نکنیم آیا به کدهای آن نیاز داریم؟ پاسخ قطعا منفی است. با این حساب آیا واقعا لازم است که تمام کدها را در همان ابتدا بارگذاری کنیم و کاربر همه چیز را یکجا دانلود کند؟ قطعا پاسخ در اینجا هم منفی است. شاید در برنامه ساده ما که فقط چند کامپوننت بسیار کوچک دارد، lazy load کردن کامپوننت ها و مسیر ها تغییری ایجاد نکند اما در برنامه های بزرگ و واقعی که هزاران خط کد دارند، بارگذاری صفحه اول سریع تر از بارگذاری تمام کامپوننت ها به صورت یکجا است.
اگر در طول دوره مثل من جلو آمده و از Vue-cli استفاده کرده باشید، الان محیط توسعه webpack را دارید. همانطور که می دانیم محیط توسعه webpack تمام فایل های ما را درون یک فایل قرار می دهد که برای برنامه های کوچک یا شاید متوسط هیچ مشکلی ندارد اما برای برنامه های بزرگ مشکل زا است. درست است که ادغام تمام فایل ها در یک فایل باعث کاهش تعداد درخواست های HTTP می شود اما اگر کدهایتان بسیار زیاد باشد، حجم bundle نهایی (فایل نهایی که ترکیبی از تمام فایل ها است) بسیار بزرگ می شود و بارگذاری سایت شما را به تاخیر می اندازد. همانطور که می دانید، تحقیقات اکثر متخصصین سئو و گوگل نشان می دهد که تاخیر بیشتر از 2 ثانیه می تواند ضربه مهلکی به سایت شما بزند. در واقع در یکی از این تحقیقات کاربران موبایل فقط 3 ثانیه برای بارگذاری یک سایت صبر کرده بودند و پس از آن پنجره مرورگر را بسته و به سایت دیگری می رفتند. بنابراین باید نقطه تعادلی بین کاهش تعداد درخواست های HTTP و افزایش سایز bundle نهایی پیدا کنید.
lazy loading نوعی بارگذاری صفحات به صورت تاخیری است. به زبان ساده تر فقط عناصری را بارگذاری می کنیم که به آن ها نیاز داشته باشیم. مثلا در برنامه ما زمانی که کاربر برای اولین بار وارد برنامه می شود نیازی به بارگذاری تمام صفحات نیست. چرا؟ به دلیل اینکه کاربر ابتدا صفحه Home را می بیند و شاید اصلا نخواهد به صفحه User برود. بنابراین چرا کاربر را مجبور کنیم که کدهای آن صفحه را نیز دانلود کند؟ روش های پیاده سازی lazy loading بسیار زیاد و متنوع هستند و شما می توانید برای هر محیط توسعه ای که دارید، روش های خاص خودش را پیدا کنید. کافی است نام آن محیط توسعه را به همراه عبارت lazy loading در گوگل جست و جو کنید. ما در این دوره از webpack استفاده می کنیم بنابراین روش پیاده سازی lazy loading روی webpack را توضیح خواهم داد.
<div class=”exlink”><a href=”https://www.roxo.ir/series/webpack-tutorials/”>آموزش کامل webpack</a></div>/
lazy loading با webpack
ابتدا به فایل routes.js بروید. باید بدانید، هر چیزی که در بالای صفحه به صورت import وجود داشته باشد به سرعت و بدون ملاحظات دیگر، بارگذاری خواهد شد. بنابراین دستورات import بالای این صفحه (به جز Home و Header را) حذف می کنیم. توجه داشته باشید که Home و Header جزء صفحه اول هستند بنابراین همیشه باید بارگذاری شوند:
import Home from './components/Home.vue'; import Header from './components/Header.vue'; export const routes = [ { path: '', name: 'Home', components: { default: Home, 'header-top': Header } }, // بقیه کدها //
در مرحله بعد باید از syntax خاصی استفاده کنیم که webpack آن را شناسایی می کند و به جای ترکیب فایل های آن در bundle اصلی، چندین bundle جداگانه می سازد (در ادامه مشاهده خواهید کرد). حالا فکر کنید که می خواهیم کامپوننت User را به صورت lazy load بارگذاری کنیم. اگر از دستورات با syntax دیگری استفاده کنیم (مثلا syntax زبان Node.js) باز هم مانند import، بارگذاری سریعا اتفاق می افتد:
import Home from './components/Home.vue'; import Header from './components/Header.vue'; require('./components/user/User.vue');
بنابراین نمی توانیم از این کد استفاده کنیم. روش انجام صحیح آن بدین شکل است که یک ثابت تعریف می کنیم که یک تابع باشد:
import Home from './components/Home.vue'; import Header from './components/Header.vue'; const User = resolve => { require.ensure(['./components/user/User.vue'], () => { resolve(require('./components/user/User.vue')); }); }
همانطور که گفتم این نحو (syntax) کمی عجیب است و شما باید آن را حفظ کنید. در واقع کد بالا یک تابع است که require.ensure را صدا می زند. ensure دو آرگومان می گیرد که اولی یک آرایه است و شامل مسیرهایی است که باید بارگذاری شوند و من آدرس User.vue را به آن داده ام. یعنی این آدرس و فایل را زیر نظر بگیر و زمانی که نیاز به بارگذاری آن داریم، آرگومان دوم را اجرا کن که خودش یک تابع است و فایل User.vue را بارگذاری می کند.
حالا همین کار را برای بقیه کامپوننت ها نیز انجام می دهیم:
import Home from './components/Home.vue'; import Header from './components/Header.vue'; const User = resolve => { require.ensure(['./components/user/User.vue'], () => { resolve(require('./components/user/User.vue')); }); }; const UserStart = resolve => { require.ensure(['./components/user/UserStart.vue'], () => { resolve(require('./components/user/UserStart.vue')); }); }; const UserEdit = resolve => { require.ensure(['./components/user/UserEdit.vue'], () => { resolve(require('./components/user/UserEdit.vue')); }); }; const UserDetail = resolve => { require.ensure(['./components/user/UserDetail.vue'], () => { resolve(require('./components/user/UserDetail.vue')); }); }; export const routes = [ { path: '', name: 'Home', components: { default: Home, 'header-top': Header } }, { path: '/user', components: { default: User, // بقیه کدها //
برای تست کردن این کدها می توانید به dev tools مرورگر رفته (معمولا کلید f12) و سربرگ network را باز کنید. با refresh کردن صفحه اصلی فایل build.js را می بینید که فایل اصلی ما است و همان صفحه اصلی را در بر می گیرد. بقیه فایل های بارگذاری شده مربوط به webpack هستند و با آن ها کاری نداریم. حالا اگر روی User کلیک کنید، دو فایل دیگر (معمولا با نام هایی شبیه به 4.build.js و 5.build.js) بارگذاری می شوند. بنابراین هر قدم که جلوتر می رویم یک فایل جدید بارگذاری می شود.
نکته: اگر بخواهیم به جای جدا کردن هر کامپوننت درون یک bundle (فایل) جداگانه، چندین کامپوننت را درون یک فایل بگذاریم باید آرگومان سومی را به require.ensure پاس بدهیم که نام یک گروه است. در واقع شما یک نام دلخواه را به آن پاس می دهید و کامپوننت هایی که این نام را داشته باشند درون یک bundle قرار خواهند گرفت:
const User = resolve => { require.ensure(['./components/user/User.vue'], () => { resolve(require('./components/user/User.vue')); }, 'user'); }; const UserStart = resolve => { require.ensure(['./components/user/UserStart.vue'], () => { resolve(require('./components/user/UserStart.vue')); }, 'user'); }; const UserEdit = resolve => { require.ensure(['./components/user/UserEdit.vue'], () => { resolve(require('./components/user/UserEdit.vue')); }, 'user'); }; const UserDetail = resolve => { require.ensure(['./components/user/UserDetail.vue'], () => { resolve(require('./components/user/UserDetail.vue')); }, 'user'); };
من نام user را انتخاب کرده ام بنابراین تمام کامپوننت های بالا درون یک bundle قرار می گیرند که نهایتا می شود دو bundle: یک bundle اصلی برای صفحه Home و یکی دیگر هم bundle دوم ما برای این کامپوننت ها در کد بالا.
- نصب و راهاندازی فریمورک VueJS
- مثالی قویتر و نصب محلی Vue
- درکی ساده از Tamplateها در Vue
- درک بهتر Directiveها + برخی از Directiveهای مشهور
- تعامل با Event Listenerها
- قدرت Vue با انواع Modifierها
- مبحث two-way-binding و پاسخ به تغییرات
- خصوصیات محاسبهشده (Computed Properties)
- روش جایگزین خصوصیات Computed
- استایلدهی پویا با اشیاء
- استایلدهی پویا اسمی بدون استفاده از کلاسها
- ایجاد شرط با v-if
- نمایش لیستها با v-for
- گردش درون اشیاء
- رهگیری عناصر در v-for
- اولین پروژه تمرینی – آمادهسازی اولیه
- پیادهسازی منطق شروع بازی
- تکمیل دکمه Attack
- کدنویسی متدهای باقیمانده در بازی
- نمایش log و اتمام پروژه
- آشنایی و تعامل بیشتر با شیء Vue
- نحوه مدیریت دادهها در شیء Vue
- استفاده از ref$ در قالبهای HTML
- آشنایی با Mount کردن Templateها
- نحوه بهروزرسانی DOM و چرخه زندگی شیء Vue
- استفاده از Lifecycleها در عمل
- راهاندازی سرور محلی Vue
- آشنایی با Vue CLI
- درک بهتر فایلهای Vue
- آشنایی با کامپوننتها
- ساخت کامپوننتها
- استفاده از کامپوننتها و قوانین آن
- ارتباط بین کامپوننتها با Props
- اعتبارسنجی Props
- رویدادهای شخصیسازیشده
- ارتباط بین کامپوننتهای خواهر و برادر
- استفاده از یک شیء سراسری Vue
- آشنایی با Slotها
- بررسی جزئیات بیشتری از Slotها
- قابلیتی جدید به نام Dynamic Components
- مرگ کامپوننتهای پویا
- فصل جدید و پروژه جدید
- پروژه Quote – پاسدادن دادهها با Prop
- پروژه Quote – تکمیل ثبت Quote
- تکمیل پروژه Quoteها
- فصل جدید، کار با فرمها
- کار با عناصر Textarea
- عناصر Checkbox و Radiobutton
- کار با منوهای آبشاری و جزئیات v-model
- تعریف عناصر شخصیسازیشده
- نگاهی عمیقتر به Directiveها
- ساخت یک Directive شخصی
- ثبت محلی Directiveها + قدمی پیشرفتهتر
- آشنایی با Filterها
- جایگزینی برای Filterها
- آشنایی با Mixinها
- جزئیات تکمیلی در مورد Mixinها
- آشنایی با انیمیشنها در Vue
- استفاده عملی از Transition و Animation
- ترکیب Transition و Animation
- استفاده از کلاسهای CSS مختلف
- تبدیل عناصر مختلف به یکدیگر با انیمیشن
- اعمال انیمیشن با جاوا اسکریپت
- کدنویسی متدهای مربوط به hookهای جاوا اسکریپتی
- تکمیل انیمیشن جاوا اسکریپتی + کامپوننتهای پویا
- ساخت یک لیست برای انیمیشنهای گروهی
- اضافهکردن انیمیشن به لیست ساختهشده
- مینی پروژه فصل – سوالات ریاضی
- تکمیل پروژه و اضافهکردن انیمیشن
- فصل جدید، درخواستهای HTTP
- ارسال اطلاعات به Firebase
- دریافت دادهها از Firebase
- آشنایی با Interceptorها در Vue-Resource
- آشنایی با مفهوم Resource در Vue-Resource
- جزئیات تکمیلی Resourceها
- فصل جدید، آشنایی با Routing
- آشنایی با Routing Modes و اضافهکردن لینکها
- استایلدهی لینک فعال
- ایجاد Navigation با کد و پارامترهای URL
- واکنش به تغییرات URL و پارامترهای آن
- ساخت URLهای پویاتر با Named Routes
- مباحث Query Parameter و Redirection
- مبحث Redirect و اضافهکردن انیمیشن
- پاسدادن # و کنترل عملیات اسکرول
- محافظت از Routeها با استفاده از Gaurdها (قسمت اول)
- محافظت از Routeها با استفاده از Gaurdها (قسمت دوم)
- بارگذاری Routeها به صورت lazy
- فصل جدید، آشنایی با VueX
- نحوهی پیادهسازی اولیهی پکیج VueX
- آشنایی با Getterها در VueX
- اتصال خودکار Getterها به خصوصیات
- حل مشکل ترکیب Getterها و Computed Props
- آشنایی با مبحث Mutation در VueX
- آشنایی با Actionها در Mutations
- درک عملیاتهای پشت صحنه در mapActions
- خلاصهی جلسات قبل + معرفی مشکلی جدید
- اعمال two-way-binding در VueX
- ماژولار کردن مدیریت State در VueX
- استفاده از Namespaceها در VueX
- فصل جدید، پروژهی نهایی دوره
- پیادهسازی Header یا Navigation سایت
- ایجاد ساختار برای قسمت سهام (stocks)
- اضافهکردن منطق دکمهی Buy
- پیادهسازی VueX روی پروژه
- تعریف Mutationهای ماژول Portfolio در VueX
- پیادهسازی Getters برای ماژول Portfolio در VueX
- تکمیل کامپوننت Portfolio و نمایش سهام
- اعتبارسنجی برای فروش سهام و استفاده از فیلترها
- نمایش Funds و اعتبارسنجی برای خرید سهام
- پایان دادن به روز + اضافه کردن انیمیشن به صفحات
- پیادهسازی drop-down و راهاندازی Firebase
- ذخیره و دریافت قیمتها با درخواستهای PUT و GET
- تکمیل دکمهی Load Data و کار با Vue dev Tools
- خروجیگرفتن نهایی از برنامه برای قرارگیری روی سرور
- فصل پیوست ۱: استفاده از axios به جای vue-resource
- فصل پیوست ۱: درخواست GET در axios
- فصل پیوست ۱: استفاده از Interceptorها در Axios
- فصل پیوست ۲: احراز هویت در برنامههای SPA
- فصل پیوست ۲: ساخت کاربر جدید با ایمیل و رمز عبور
- فصل پیوست ۲: دریافت توکن احراز هویت در مرورگر
- فصل پیوست ۲: تکمیل منطق برنامه و کدهای باقیمانده
- فصل پیوست ۲: پیوست توکن به درخواستهای خروجی
- فصل پیوست ۲: بهینهسازی برنامه و Path Guard
- فصل پیوست ۲: اضافهکردن مکانیسم logout از حساب
- فصل پیوست ۲: پیادهسازی logout خودکار از حساب
- فصل پیوست ۲: ذخیرهی دادهها در localStorage
- فصل پیوست ۲: پیادهسازی فرآیند login خودکار
- فصل پیوست ۳: فصل جدید، اعتبارسنجی دادههای کاربر
- فصل پیوست ۳: ارائهی فیدبک اعتبارسنجی در UI
- فصل پیوست ۳: آشنایی با Validatorهای عددی
- فصل پیوست ۳: آشنایی با Validatorهای رمز عبور
- فصل پیوست ۳: آشنایی با requiredUnless
- فصل پیوست ۳: اعتبارسنجی آرایههای پویا
- فصل پیوست ۳: ثبت فرم و اعتبارسنجیهای ناهمگام
- فصل پیوست ۴: نسخهی 3 از Vue CLI
- فصل پیوست ۴: آشنایی با پروژه در CLI جدید
- فصل پیوست ۴: استفاده و کار با پلاگینها در CLI جدید
- فصل پیوست ۴: آشنایی با Environment Variables
- فصل پیوست ۴: خروجی گرفتن از برنامه نهایی
- فصل پیوست ۴: شخصیسازی بیشتر Build
- فصل پیوست ۴: استفاده از GUI