احتمالاً تا حالا اسم Hotwire به گوشت خورده و شاید پیش خودت فکر کردی "چه اسم بامزه ای، ولی واقعاً چیه؟ و اصلاً من باید بهش اهمیت بدم؟"
منم دقیقاً همین سوال تو ذهنم بود، پس شروع کردم به تحقیق و هر چی یاد گرفتم رو نوشتم. اگه ۱۰ دقیقه وقت داری و کنجکاوی بدونی Hotwire و Turbo چیه، ادامه مطلب رو بخون.
نگران نباش! لازم نیست حتماً برنامه نویس Ruby on Rails باشی تا این موضوع رو بفهمی. ایده های پشت Hotwire و رندر سمت سرور الان دارن توی تکنولوژی های مختلف وب استفاده می شن. پلتفرم هایی مثل PHP/Laravel، Elixir/Phoenix، Python/Django هم ابزارهای مشابهی دارن که Hotwire رو پیاده سازی می کنن. حتی React هم به تازگی پشتیبانی از رندر سمت سرور رو اضافه کرده.
اینجا می خوایم مفاهیم رو کامل و ساده برات توضیح بدیم. پس یه فنجون قهوه بردار و شروع به خوندن کن. ☕😊
Hotwire در واقع یه روش برای ساخت اپلیکیشن های وبه، اما خودش یه تکنولوژی خاص نیست. می شه گفت یه "چتر" هست که سه تا تکنولوژی اصلی رو در بر گرفته: Turbo، StimulusJS و Strada (تو دنیای Ruby on Rails). ولی اون چیزی که واقعاً Hotwire رو به کار می ندازه، همون Turbo هست. توربو در واقع کدیه که این روش رو ممکن می کنه.
حتی اگه Turbo رو تیم Ruby on Rails ساخته باشه و یه جورایی نسخه پیشرفته Turbolinks باشه، اما اون فقط محدود به Rails نیست. این تکنولوژی رو می تونی تو زبان ها و فریمورک های بک اند دیگه مثل PHP، Python و... هم استفاده کنی. پس Turbo فقط برای Rails نیست.
Turbo به توسعه دهنده ها کمک می کنه که اپلیکیشن های وب رو سریع تر و ساده تر بسازن، بدون اینکه نیاز زیادی به جاوااسکریپت باشه. تو این روش، همه محاسبات و منطق ها روی سرور انجام می شن و مرورگر فقط HTML نهایی رو می گیره و نمایش می ده. این یعنی لازم نیست کلی کد جاوااسکریپت بنویسی تا داده ها رو از سرور بگیری و روی صفحه نشون بدی.
برای مقایسه، روش SPA (Single Page Application) رو در نظر بگیر. تو SPA ما داده های JSON رو از سرور می گیریم، بعد کلی جاوااسکریپت می نویسیم تا اون داده ها رو تبدیل کنیم به HTML و صفحه رو به روز کنیم. ولی تو Turbo، این کارا به سادگی و با کمترین جاوااسکریپت انجام می شه و بیشتر کارها رو سرور هندل می کنه.
وعده Turbo اینه که به جای اینکه وقتت رو برای نوشتن کلی کد جاوااسکریپت هدر بدی، می تونی بیشتر از زبان بک اند دلخواهت مثل Ruby، PHP یا Python استفاده کنی. همه منطق ها و محاسبات تجاری تو یه جا یعنی روی سرور قرار می گیرن. علاوه بر این، از پیچیدگی های استفاده از فریم ورک های جاوااسکریپتی و ابزارهایی مثل webpack خلاص می شی. تنها چیزی که نیاز داری، همون Turbo.js هست.
Turbo با چند تا بخش اصلی کار می کنه:
نکته: فرق WebSocket و SSE اینه که WebSocket ارتباط دوطرفه بین سرور و مرورگر رو ممکن می کنه، ولی تو SSE فقط سرور می تونه داده ها رو به مرورگر بفرسته.
خب، بیایم ببینیم Turbo Drive چطوری کار می کنه. هدفش اینه که همون سرعت بالای اپلیکیشن های تک صفحه ای (SPA) رو بهت بده، بدون اینکه لازم باشه از روش های پیچیده استفاده کنی. یه جورایی Turbo همه کارها رو مدیریت می کنه؛ نیازی به روتر سمت کلاینت نیست و لازم نیست حالت ها رو به دقت کنترل کنی.
Turbo Drive کلیک روی تمام لینک های <a href> که به همون دامنه اشاره می کنن رو رهگیری می کنه. یعنی چی؟ یعنی وقتی روی یه لینک کلیک می کنی، Turbo به جای اینکه مرورگر صفحه جدید رو بارگذاری کنه، خودش URL رو با استفاده از History API تغییر می ده، محتوای جدید رو با استفاده از fetch می گیره و بعد نتیجه رو به صورت HTML توی صفحه نشون می ده. اینطوری بدون اینکه کل صفحه بارگذاری بشه، فقط همون بخش های مورد نیاز تغییر می کنن.
نکته: History API بهت اجازه می ده تاریخچه مرورگر رو دستکاری کنی. مثلاً از تابع pushState() استفاده می کنه تا URL رو بدون بارگذاری دوباره صفحه به روز کنه، همون کاری که pjax قبلاً انجام می داد.
وقتی فرم ارسال می شه، Turbo Drive کل محتوای <body> صفحه رو جایگزین می کنه و محتوای داخل <head> رو به روزرسانی می کنه. جالب اینجاست که آبجکت های جاوااسکریپتی مثل window و document و حتی عنصر <html> بین بارگذاری های مختلف ثابت می مونن. این یعنی بدون نیاز به بارگذاری مجدد کل صفحه، صفحه با سرعت آپدیت می شه.
نکته جذاب اینجاست که این سرعت بالا رو فقط با رعایت چند تا قاعده ساده به دست میاری. البته اگه بخوای، می تونی خودت مستقیماً با Turbo Drive تعامل داشته باشی و کنترل بیشتری روی اینکه چطوری بازدید ها انجام بشن یا به چرخه حیات درخواست ها دسترسی پیدا کنی. ولی معمولاً با تنظیمات پیش فرضش هم کار رو به بهترین شکل انجام می ده.

حالا برسیم به Turbo Frames. این ابزار یه راه خیلی خوب برای اینه که بخش های مختلف یه صفحه رو به قسمت های مستقل تقسیم کنی. این بخش ها داخل یه عنصر به اسم turbo-frame قرار می گیرن و می تونن با تاخیر (یا همون lazy loading) بارگذاری بشن. نکته جالب اینجاست که وقتی داخل یه فریم روی لینک کلیک می کنی یا یه فرم ارسال می کنی، فقط همون بخش آپدیت می شه و بقیه صفحه همونطوری که هست، می مونه.
یه بار تو مصاحبه ای با DHH (سازنده Ruby on Rails) شنیدم که می گفت ایده Turbo Frames از اینجا اومده که می خواستن ایمیل های موبایلی تو سرویس Hey درست کار کنن.
مثلاً این کد رو ببین:
<turbo-frame id="new_message">
<form action="/messages" method="post">
...
</form>
</turbo-frame>وقتی این فرم رو ارسال می کنی، Turbo اون بخشی از پاسخ سرور که مربوط به همون فریم new_message هست رو می گیره و محتوای جدید رو تو همون فریم بارگذاری می کنه. بقیه صفحه اصلاً دست نمی خوره و همونطوری که بود باقی می مونه.
اگه بخوای یه بخش از صفحه رو با تاخیر بارگذاری کنی، می تونی از ویژگی src استفاده کنی:
<turbo-frame id="messages" src="/messages">
<p>This message will be replaced by the response from /messages.</p>
</turbo-frame>این یعنی وقتی صفحه لود شد، محتوای این بخش بعداً از /messages درخواست می شه و جایگزین پیام پیش فرض می شه.
شاید فکر کنی Turbo Frames شبیه iframes باشه، ولی نه! فرق دارن. Turbo Frames توی همون DOM صفحه اصلی هستن، همون CSS رو استفاده می کنن و توی همون کانتکست جاوااسکریپت قرار دارن. پس از اون مشکلات و عجیب وغریب بودن iframes خبری نیست!
تا اینجا با Turbo Frames آشنا شدی که بهت اجازه می دن بخش هایی از صفحه رو بر اساس تعاملات مستقیم مثل کلیک روی لینک یا ارسال فرم، به روزرسانی کنی. حالا Turbo Streams یه قدم جلوتر می ره و بهت امکان می ده هر قسمتی از صفحه رو بر اساس داده های زنده از WebSocket یا SSE به روز کنی، بدون اینکه نیاز باشه خودت دستی وارد عمل بشی.
یه نکته تاریخی جالب: مفهوم Streams در واقع ادامه همون چیزی هست که تو سال های قبل بهش RJS و بعدش SJR می گفتن. RJS که تو Rails 1.1 در سال ۲۰۰۶ معرفی شد، این ایده رو داشت که برای اضافه کردن قابلیت های Ajax نیازی نیست جاوااسکریپت بنویسی، می تونستی همون رو با نوشتن کد Ruby انجام بدی. ایده ای که هنوزم ادامه داره!
بعدش، SJR (Server-generated Javascript Response) که تو سال ۲۰۱۳ معرفی شد، خیلی شبیه به چیزی بود که الان با Turbo داریم. جریان کار اینطوری بود: یه فرم از طریق درخواست Ajax ارسال می شد، سرور یه پاسخ جاوااسکریپتی می فرستاد که شامل یه قالب HTML به روز شده بود و مرورگر این کد جاوااسکریپت رو اجرا می کرد تا DOM رو آپدیت کنه. با Streams، ما همین جریان رو ادامه می دیم ولی با این تفاوت که حالا دیگه نیازی به نوشتن جاوااسکریپت نیست و تمرکز روی ارسال HTML و به روزرسانی مستقیم DOM شده.
برخلاف RJS و SJR، در Turbo Streams به طور عمدی امکان ارسال جاوااسکریپت سفارشی رو نداری! این به این دلیل طراحی شده که تمرکز فقط روی ارسال HTML و به روزرسانی خودکار DOM باشه. اگه نیاز به رفتار خاصی داری، می تونی از اکشن ها و کال بک های Stimulus استفاده کنی تا رفتارهای اضافی رو مدیریت کنی.
این رویکرد جدید، یعنی به جای جاوااسکریپت تمرکز روی HTML و DOM، تجربه توسعه وب رو ساده تر می کنه و باعث می شه کمتر درگیر کدهای پیچیده جاوااسکریپتی بشی. این همون چیزیه که باعث می شه اپلیکیشن های وب مدرن سریع تر و بهتر کار کنن، درست مثل زمانی که در سال ۲۰۱۳ گفته شد ترکیب Turbolinks، Russian Doll-caching و SJR یه ترکیب جادویی برای ساخت اپ های سریع و زیباست.
حالا بیایم ببینیم Turbo Streams دقیقاً چطور کار می کنه. یه عنصر جدید به اسم <turbo-stream> معرفی می کنه که دو تا ویژگی مهم داره: action و target. اکشن ها کارهایی مثل append (اضافه کردن به انتهای یه بخش)، prepend (اضافه کردن به ابتدای یه بخش)، replace (جایگزینی یه بخش)، update (به روزرسانی یه بخش)، remove (حذف کردن) و چند تا چیز دیگه مثل before و after رو شامل می شه.
وقتی این عنصر رو توی HTML قرار بدی، Turbo خودش بقیه کارها رو انجام می ده. فقط کافیه که محتوای جدیدی که می خوای اضافه یا جایگزین بشه رو توی یه تگ <template> قرار بدی، و Turbo به طور خودکار اون رو به صفحه اضافه می کنه یا تغییرات رو اعمال می کنه.
نکته: تگ <template> توی HTML یه روشه برای نگه داشتن محتوایی که قرار نیست همون لحظه که صفحه لود می شه نمایش داده بشه، ولی بعداً می تونه با جاوااسکریپت به صفحه اضافه بشه.
Turbo Streams این کارو خیلی راحت و بدون نیاز به نوشتن کدهای پیچیده جاوااسکریپتی برات انجام می ده.
۱. استفاده مجدد از قالب های سمت سرور: Turbo Streams بهت این امکان رو می ده که همون قالب هایی که برای بار اول صفحه استفاده شدن رو برای آپدیت های زنده هم به کار ببری. یعنی لازم نیست دوباره از اول یه قالب جدید بنویسی. فقط گاهی ممکنه نیاز باشه با یه مقدار CSS، بعضی از عناصر رو مخفی یا نمایش بدی تا تو هر دو حالت درست کار کنه.
۲. ارسال HTML به جای JSON: یه ویژگی فوق العاده Turbo Streams اینه که دیگه نیازی به جاوااسکریپت سمت کلاینت (جز Turbo.js) نداری. این یعنی لازم نیست کلی وقت بذاری تا JSON رو بگیری و تبدیلش کنی به HTML. با Turbo، همون HTML از سرور میاد و مستقیماً توی صفحه استفاده می شه.
۳. جریان کنترلی ساده تر: با Turbo Streams، کنترل کارها خیلی راحت تر می شه. تو فقط به HTML نگاه می کنی و می بینی چه بخشی از صفحه داره تغییر می کنه. دیگه خبری از پیچیدگی های روتر سمت کلاینت، event bubbling و این جور چیزا نیست. همه چیز ساده و شفافه!
خب، بذار در مورد Turbo Native یه توضیح خودمونی بدم. شاید مثل من موبایل دولوپر نباشی، ولی اینجا چند نکته که از خوندن درباره Turbo Native یاد گرفتم رو برات می نویسم:
Turbo Native یه گزینه خیلی خوبه برای ساخت اپلیکیشن های هیبریدی. یعنی چی؟ یعنی می تونی از HTML رندر شده روی سرور استفاده کنی تا بخش های اصلی اپلیکیشن رو بسازی، و فقط چند تا صفحه بومی (native) هم داشته باشی که به دقت بیشتری نیاز دارن. اینطوری ترکیبی از سرعت توسعه وب و کارایی اپلیکیشن های بومی رو داری.
یکی از مزیت های هیبریدی بودن اینه که هر وقت خواستی اپ رو آپدیت کنی، لازم نیست صبر کنی تا تاییدیه اپ استور رو بگیری. هر چی که با HTML انجام دادی رو می تونی توی اپلیکیشن وب تغییر بدی و بلافاصله به دست کاربرا برسه.
اما یه نکته مهم: Turbo Native یه فریم ورک نیست که بخواد API های بومی رو خلاصه کنه یا کدی ایجاد کنه که بین پلتفرم ها (iOS و Android) به اشتراک گذاشته بشه. در واقع هنوز هم به توسعه دهنده های بومی نیاز داری، ولی کارشون کمتر می شه چون فقط باید روی بخش های بومی کار کنن. اون چیزی که بین پلتفرم ها مشترک هست، همون HTMLیه که از سمت سرور رندر می شه.
تا اینجا با Turbo Drive، Turbo Frames و Turbo Streams آشنا شدیم. حالا وقتشه یه سری نکات ریزتر رو هم بدونیم که موقع ساخت اپلیکیشن با Turbo باید مدنظر داشته باشیم.
یه نکته مهم: درسته که Turbo مختص Rails نیست، اما gem turbo-rails پیاده سازی مرجع Turbo برای Rails محسوب می شه. توی مستندات Turbo هم گفته شده که برای استفاده از Turbo نیاز به یه فریم ورک بک اند نداری. (البته این یکی رو هنوز درست متوجه نشدم، چون به نظر من بک اند باید HTML درست با تگ های <turbo-stream> و <turbo-frame> برگردونه تا همه چیز سر جای خودش باشه!)
خب، حالا که توی Turbo خبری از بارگذاری کامل صفحات نیست، یه سری نکات ریز وجود داره که باید حواسمون بهشون باشه. چون آبجکت های جاوااسکریپت مثل window و document و هر چیزی که توی حافظه گذاشتیم، بین تغییرات صفحه ثابت می مونن. یعنی نمی تونیم به بارگذاری دوباره صفحه برای ریست کردن محیط اپلیکیشن تکیه کنیم. باید اپلیکیشنمون رو جوری طراحی کنیم که با این وضعیت سازگار باشه.
وقتی با Turbo به صفحات مختلف می ریم، اسکریپت هایی که توی تگ <head> هستن مشکلی ندارن؛ Turbo Drive اون ها رو به تگ <head> فعلی اضافه می کنه و مرورگر همونجا لودشون می کنه.
اما اسکریپت هایی که توی <body> باشن دردسر درست می کنن. اگه می خوای موقع تغییر صفحه یه سری عملیات پیچیده انجام بدی یا رفتاری رو به صفحه اضافه کنی، به جای اینکه از تگ اسکریپت استفاده کنی، بهتره از رویداد turbo استفاده کنی.
برای اسکریپت هایی که نمی خوای Turbo بعد از رندر کردن صفحه ارزیابی کنه، باید از ویژگی data-turbo-eval="false" استفاده کنی. مرورگر فقط توی بارگذاری اول اون ها رو اجرا می کنه.
برای لود کردن باندل های جاوااسکریپت اپلیکیشن، همیشه این کار رو توی تگ <head> انجام بده. اگه هم می خوای Turbo یه بارگذاری کامل صفحه رو انجام بده وقتی که باندل جدید جاوااسکریپت منتشر شد، می تونی به اسکریپتت ویژگی data-turbo-track="reload" رو اضافه کنی.
قبل از هر چیز، باید بدونیم منظور از Restoration visits و Application visits چیه.
وقتی Turbo Drive یه کپی از صفحه رو توی کش ذخیره می کنه، از تابع cloneNode(true) استفاده می کنه. این یعنی لیسنرهای رویداد و داده ها پاک می شن (چون cloneNode فقط خود DOM رو کپی می کنه).
اگه لازم باشه قبل از اینکه Turbo صفحه رو کش کنه، کاری انجام بدی (مثل ریست کردن فرم ها یا جمع کردن اجزای UI)، می تونی به رویداد turbo
گوش بدی و تغییرات لازم رو اعمال کنی. مثلاً می تونی این کار رو با document.addEventListener انجام بدی.
وقتی Turbo Drive یه صفحه رو از کش نمایش می ده، به تگ <html> ویژگی data-turbo-preview اضافه می کنه. می تونی از این ویژگی برای فعال یا غیرفعال کردن رفتارهای خاص توی صفحه استفاده کنی.
اگه بخوای کشینگ رو برای یه صفحه خاص غیرفعال کنی، می تونی از تگ <meta> توی <head> صفحه استفاده کنی، مثل این:
<head>
...
<meta name="turbo-cache-control" content="no-cache">
</head>معمولاً اتفاقات مثل window.onload، DOMContentLoaded یا JQuery ready فقط بعد از بارگذاری اولیه صفحه اجرا می شن. اما وقتی با Turbo کار می کنیم و صفحه ها به صورت جزئی لود می شن، نیاز داریم که یه راه حل برای نصب رفتارهای جاوااسکریپت بعد از هر بار لود شدن صفحه پیدا کنیم. دو تا گزینه داریم:
یه رویدادی داریم به اسم turbo:load
که بعد از بارگذاری اولیه صفحه و هر بار که با Turbo Drive صفحه ای رو باز می کنی، اجرا می شه. می تونیم از این رویداد به این شکل استفاده کنیم:
document.addEventListener("turbo:load", function() {
// اینجا کد جاوااسکریپتت رو می نویسی
})نکته مهم اینه که نباید از turbo:load برای اضافه کردن مستقیم لیسنرهای رویداد به عناصر داخل بدنه صفحه (body) استفاده کنی. به جای این کار بهتره از event delegation استفاده کنی، یعنی لیسنرها رو فقط یه بار روی کل سند (document) یا پنجره (window) ثبت کنی.
وقتی داری با Turbo کار می کنی، ممکنه هر لحظه یه عنصر جدید توی صفحه ظاهر بشه؛ چه از طریق ناوبری با فریم ها، چه پیام های استریم، چه رندر سمت کلاینت و یا بارگذاری صفحه با Turbo Drive. اینجاست که Stimulus به درد می خوره. Stimulus با استفاده از callback های چرخه عمرش و روش های ساده ای که داره، می تونه همه این تغییرات رو تو یه جا مدیریت کنه.
Stimulus با استفاده از MutationObserver API، تغییرات توی سند رو بررسی می کنه و کنترلرها و لیسنرهای رویدادش رو به صورت خودکار وصل و قطع می کنه. این باعث می شه که Stimulus بتونه همه نوع به روزرسانی های DOM رو مدیریت کنه.
اینجا منظور از تغییرات بی اثر اینه که وقتی یه تابع یا تغییر رو به HTML اعمال می کنی، مهم نیست چند بار این کار رو تکرار کنی؛ نتیجه باید مثل دفعه اول باقی بمونه. یعنی بعد از اولین بار اعمال تغییر، دیگه چیزی نباید تغییر کنه.
چرا این مهمه؟ به خاطر کشینگ. مثلا فرض کن یه تابع داری که تو رویداد turbo:load اجرا می شه و به یه مجموعه از عناصر تاریخ اضافه می کنه. وقتی به صفحه می ری، این تابع سربرگ های تاریخ رو اضافه می کنه. حالا تصور کن که از صفحه خارج می شی و Turbo Drive یه کپی از این صفحه رو توی کش ذخیره می کنه. وقتی دوباره با دکمه «برگشت» مرورگر به صفحه برمی گردی، Turbo Drive صفحه رو از کش بازمی گردونه و دوباره رویداد turbo:load اجرا می شه. اگه حواست نباشه، این دفعه سربرگ های تاریخ دوباره اضافه می شن و صفحه به هم می ریزه.
راه حل چیه؟ قبل از اینکه تابع رو دوباره اجرا کنی، چک کنی که آیا این تغییرات قبلاً اعمال شدن یا نه. مثلاً می تونی بررسی کنی که آیا یه عنصر تقسیم کننده ی تاریخ قبلاً وجود داره یا نه. (همچنین می تونی یه flag از طریق data اضافه کنی، ولی این روش کمتر مطمئن هست.)
بعضی وقت ها ممکنه نخوایم که یه سری از عناصر توی صفحه، وقتی کاربر بین صفحات جابجا می شه، تغییر کنن. اینجاست که Turbo Drive بهت اجازه می ده اون عناصر رو ثابت (permanent) کنی. مثلا تصور کن که یه آیکون سبد خرید داری که تعداد آیتم ها رو نشون می ده. نمی خوای وقتی کاربر بعد از اضافه کردن آیتم به سبد، با دکمه "بازگشت" مرورگر به صفحه قبل برمی گرده، این شمارنده به عدد پایین تری تغییر کنه.
برای این کار، کافیه که اون عنصر رو به عنوان "ثابت" مشخص کنی:
<div id="cart-counter" data-turbo-permanent>1 item</div>اینجا، id عنصر خیلی مهمه چون Turbo Drive همه عناصر ثابت رو از طریق id شناسایی می کنه. وقتی صفحه جدید لود می شه، Turbo Drive این عناصر رو از صفحه قبلی به صفحه جدید منتقل می کنه و داده ها و لیسنرهای رویدادها رو هم حفظ می کنه.

Hotwire یه مفهوم کلیه که روش های مختلفی مثل Turbo، Stimulus و Strada رو در بر می گیره. Turbo در واقع یکی از تکنولوژی هاییه که توی Hotwire قرار داره و وظیفه اش به روزرسانی سریع صفحه هاست، بدون اینکه نیازی به بارگذاری کامل صفحه باشه.
نه، درسته که Turbo توسط تیم Rails ساخته شده، ولی می تونی ازش توی هر فریم ورک یا زبان بک اند دیگه ای هم استفاده کنی. مثلاً زبان هایی مثل PHP، Python، و Elixir هم تکنولوژی هایی مشابه Turbo دارن که می تونی باهاشون کار کنی.
خوشبختانه نیازی به نوشتن کلی جاوااسکریپت نیست. Turbo برای این طراحی شده که تا حد امکان بدون جاوااسکریپت سمت کلاینت کار کنه. فقط لازمه که از Turbo.js استفاده کنی و بقیه کارها با HTML و سمت سرور انجام می شه.
بله، چون Turbo به جای استفاده از JSON، از HTML استفاده می کنه. محتوای صفحه ها به شکل HTML رندر شده و به مرورگر ارسال می شه، که برای موتورهای جستجو مثل گوگل کاملاً قابل فهمه.
Turbo Drive کلیک ها روی لینک ها و ارسال فرم ها رو مدیریت می کنه و به جای اینکه کل صفحه رو دوباره لود کنه، فقط بخش های ضروری رو آپدیت می کنه. این باعث می شه سرعت سایت بالا بره و تجربه کاربری بهتر بشه.
بله، با استفاده از Turbo Native می تونی اپلیکیشن های هیبریدی بسازی که هم از قدرت HTML رندر شده روی سرور استفاده کنن و هم از صفحه های بومی (native) که توی iOS و Android به صورت اختصاصی اجرا می شن.
Turbo Frames شبیه iframes هستن چون بهت اجازه می دن فقط بخشی از صفحه رو آپدیت کنی، ولی فرقشون اینه که Turbo Frames توی همون DOM قرار دارن، از همون CSS استفاده می کنن و توی همون کانتکست جاوااسکریپت اجرا می شن. پس مشکلات عجیبی که iframes داره اینجا وجود نداره.
Turbo Streams بهت اجازه می ده بخشی از صفحه رو به صورت زنده آپدیت کنی. مثلاً وقتی از WebSocket یا SSE استفاده می کنی، می تونی بدون نیاز به رفرش کل صفحه، داده های جدید رو به صفحه اضافه کنی یا بخشی از صفحه رو تغییر بدی.
Turbo به طور پیش فرض صفحات رو کش می کنه. اما اگه بخوای کشینگ رو برای یه صفحه خاص غیرفعال کنی، می تونی از این تگ استفاده کنی:
<meta name="turbo-cache-control" content="no-cache">نه، برای بعضی از اپلیکیشن های پیچیده که نیاز به رندر سمت کلاینت دارن، مثل ویرایشگرهای متنی پیشرفته، ممکنه استفاده از تکنولوژی های دیگه مثل فریم ورک های جاوااسکریپتی مناسب تر باشه. اما برای اکثر اپلیکیشن های مدرن، استفاده از Hotwire و Turbo یه انتخاب عالی هستن چون پیچیدگی ها رو کاهش می دن و تجربه توسعه رو ساده تر می کنن.
خب، رسیدیم به آخر خط! تا اینجا بیشتر مفاهیم اصلی Turbo و Hotwire رو توضیح دادیم. اصل ماجرا اینه که چطور می تونیم چیزهایی که تو صفحه هست رو سریع و روان آپدیت کنیم، بدون اینکه مجبور بشیم کلی کد جاوااسکریپت سمت کاربر بنویسیم.
Hotwire یا همون HTML-over-the-wire یه مفهومه، نه یه تکنولوژی خاص. ایده اصلی اینه که به جای ارسال جیسون، HTML رندر شده از سمت سرور رو به مرورگر بفرستیم و بیشتر منطق اپلیکیشن هم توی سرور اجرا بشه.
Turbo همون تکنولوژیه که تو دنیای Rails پیاده سازی Hotwire رو انجام می ده. البته سایر فریم ورک ها و زبان های بک اند هم نسخه های خودشون از Turbo رو دارن. Turbo از سه بخش اصلی تشکیل شده: Drive، Frames و Streams.
موقع ساخت اپلیکیشن با Turbo باید حواست باشه که اپلیکیشنت به صورت یه فرایند پایدار و طولانی مدت تو مرورگر اجرا می شه. دیگه نمی تونی به بارگذاری مجدد صفحه برای ریست کردن محیطت تکیه کنی. باید به مسائل مهمی مثل کشینگ، اسکریپت ها و نصب رفتارهای جاوااسکریپتی دقت کنی.
آخر سر، اینم بگم که روش Hotwire و Turbo برای همه نوع اپلیکیشن وب مناسب نیست. بعضی وقت ها، پیچیدگی رندر سمت کلاینت با یه اپلیکیشن تک صفحه ای (SPA) لازمه تا تجربه کاربری کاملی داشته باشیم، مثل ویرایشگر متن Trix از جامعه Rails. ولی برای خیلی از اپلیکیشن های مدرن، استفاده از Hotwire و Turbo می تونه پیچیدگی ها رو به شدت کاهش بده و تجربه ساخت رو ساده تر کنه.
اگه تا اینجا همراه ما بودی، دمت گرم! 💙 امیدوارم چیزهای خوبی یاد گرفته باشی!
اصفهان، خیابان حمزه اصفهانی، بن بست تخت جمشید(18) ، پلاک ۴
دفتر تهران: تهران، خیابان سهروردی شمالی، خیابان هویزه شرقی، پلاک 20، طبقه دوم، واحد 6