টার্বোলিংকস - এটি সম্ভবত রেল মহাবিশ্বের সবচেয়ে ঘৃণ্য শব্দগুলির মধ্যে একটি৷
হয়ত আপনি এটি চেষ্টা করে দেখেছেন। আপনি নতুন প্রোজেক্ট বা বিদ্যমান অ্যাপে টারবোলিংক অন্তর্ভুক্ত করেছেন। এবং শীঘ্রই অ্যাপটি অদ্ভুত এবং বিস্ময়কর উপায়ে ব্যর্থ হতে শুরু করে। ভাল জিনিস ঠিক করা ঠিক ততটাই সহজ ছিল - টার্বোলিংক বন্ধ করুন৷
৷...কিন্তু কিছু কোম্পানি এটি কাজ করে। এখানে হানিব্যাজারে, আমরা এটিকে কাজ করে দিয়েছি - এবং আমরা কোন প্রতিভা নই।
উত্তরটি এত সহজ যে আমি এটি আনতে প্রায় দ্বিধাবোধ করছি। কিন্তু Ruby Nation এবং Madison+Ruby-এ এই বিষয়ে বক্তৃতা দেওয়ার পরে, মনে হচ্ছে লোকেরা এই বিষয়টিকে সহায়ক বলে মনে করে। তো চলুন খনন করি।
Turbolinks এবং PJAX কিভাবে কাজ করে
Turbolinks এবং PJAX মূলত একই ভাবে কাজ করে। তারা তাই অনুরূপ, আমি এখন থেকে শুধু PJAX বলতে যাচ্ছি. :)
আপনি PJAX দুটি পৃষ্ঠার অনুরোধের পরিপ্রেক্ষিতে বুঝতে পারেন। প্রথমবার যখন কোনো ব্যবহারকারী কোনো পৃষ্ঠার অনুরোধ করেন, এটি অন্য যেকোনও "প্রথাগত" রেল পৃষ্ঠার মতোই পরিবেশিত হয়। কিন্তু যখন ব্যবহারকারী একটি PJAX-সক্ষম লিঙ্কে ক্লিক করেন, তখন বিশেষ কিছু ঘটে। পৃষ্ঠাটি সম্পূর্ণরূপে পুনরায় লোড করার পরিবর্তে, পৃষ্ঠার শুধুমাত্র একটি অংশ আপডেট করা হয়। এটি AJAX এর মাধ্যমে সম্পন্ন হয়েছে৷
৷এটি আমাদের একটি একক পৃষ্ঠার অ্যাপের অনেক সুবিধা দেয়, যখন কিছু অসুবিধাকে এড়িয়ে যায়:
- পিজেএএক্স অ্যাপগুলিকে প্রায়ই একক পৃষ্ঠার অ্যাপের মতোই চটকদার বলে মনে হয়, যেহেতু প্রতিটি অনুরোধে পৃষ্ঠাটিকে আর সম্পূর্ণরূপে পুনরায় লোড করতে হবে না।
- আপনি ফ্রন্ট-এন্ড এবং ব্যাক এন্ড ডেভেলপমেন্টের জন্য একই স্ট্যাক ব্যবহার করতে পারেন
- ব্যবহারকারী যখন JS অক্ষম করে তখন PJAX অ্যাপগুলি ডিফল্টরূপে সুন্দরভাবে হ্রাস পায়
- PJAX অ্যাপগুলি আরও সহজে অ্যাক্সেসযোগ্য এবং SEO বন্ধুত্বপূর্ণ
টার্বোলিংক বাস্তবায়ন করা
প্রচুর লাইব্রেরি আছে যা আপনার জন্য PJAX এর ভারী উত্তোলন করবে। Turbolinks সম্ভবত সবচেয়ে সুপরিচিত. এটি সেট আপ করা আপনার জেমফাইলে টার্বোলিংক রত্ন অন্তর্ভুক্ত করার একটি বিষয়:
gem 'turbolinks'
...এবং app/assets/javascripts/application.js
-এ JS সহ//= require turbolinks
এখন আপনি যখন আপনার অ্যাপটি পুনরায় লোড করবেন, প্রতিটি অভ্যন্তরীণ লিঙ্ক একটি টার্বোলিংক হবে। আপনি যখন সেগুলিতে ক্লিক করেন, তখন AJAX এর মাধ্যমে নতুন পৃষ্ঠার অনুরোধ করা হবে এবং বর্তমান নথিতে ঢোকানো হবে৷
jquery-pjax বাস্তবায়ন করা
এখানে Honeybadger-এ, আমরা একটি PJAX লাইব্রেরি ব্যবহার করি যা মূলত Github দ্বারা তৈরি করা হয়েছিল। এটির জন্য Turbolinks-এর তুলনায় একটু বেশি কনফিগারেশন প্রয়োজন, তবে এটি আরও কিছুটা নমনীয়।
অনুমান করার পরিবর্তে যে সমস্ত লিঙ্কগুলি PJAX, এটি আপনাকে এটি নিয়ন্ত্রণ করতে দেয়। এটি আপনাকে পৃষ্ঠায় কোথায় PJAX সামগ্রী ঢোকানো হবে তা নিয়ন্ত্রণ করতে দেয়৷
প্রথম জিনিসটি আমাকে আমার HTML এ একটি ধারক যোগ করতে হবে
<div class="container" id="pjax-container">
Go to <a href="/page/2">next page</a>.
</div>
এখন আমাকে PJAX লিঙ্ক সেট আপ করতে হবে:
$(document).pjax('a', '#pjax-container')
অবশেষে, আমি রেলকে বলব PJAX অনুরোধে লেআউট রেন্ডার না করতে। আপনাকে এরকম কিছু করতে হবে, নতুবা আপনি ডুপ্লিকেট হেডার এবং ফুটার দিয়ে শেষ করবেন। অর্থাৎ আপনার ওয়েবসাইট ইনসেপশনের মত দেখাবে।
def index
if request.headers['X-PJAX']
render :layout => false
end
end
এটা এত সহজ নয়!
ঠিক আছে, আমি যা বলেছি তার চেয়ে এটি একটু বেশি জটিল। বেশিরভাগই একটি দৈত্যাকার সমস্যার কারণে যা খুব কম লোকই কথা বলে।
যখন আপনার DOM প্রতিটি পৃষ্ঠা লোডের সময় সাফ হয় না, তখন এর মানে হল যে JS যেটি আপনার ঐতিহ্যবাহী Rails অ্যাপে কাজ করেছে তা এখন খুব অদ্ভুত উপায়ে ভেঙে যায়।
এর কারণ হল যে আমরা অনেকেই এমনভাবে JS লিখতে শিখেছি যা দুর্ঘটনাজনিত নামকরণের দ্বন্দ্বকে উত্সাহিত করে। সবচেয়ে প্রতারক অপরাধীদের মধ্যে একটি হল সাধারণ jquery নির্বাচক৷
৷// I may look innocent, but I'm not!
$(".something")
যে পৃষ্ঠাগুলি পুনরায় লোড হয় না তাদের জন্য JS লেখা
আপনি যখন পুনরায় লোড হয় না এমন পৃষ্ঠাগুলির জন্য JS লেখেন তখন দ্বন্দ্বগুলি হল এক নম্বর সমস্যা। কিছু অদ্ভুত, ডিবাগ করা কঠিন সমস্যা দেখা দেয় যখন জেএস এইচটিএমএল ম্যানিপুলেট করে যা স্পর্শ করার জন্য কখনই ছিল না। উদাহরণস্বরূপ, আসুন একটি সাধারণ jQuery ইভেন্ট হ্যান্ডলার দেখুন:
$(document).on("click", ".hide-form", function() {
$(".the-form").hide();
});
এটি পুরোপুরি যুক্তিসঙ্গত, যদি এটি শুধুমাত্র একটি পৃষ্ঠায় চলে। কিন্তু যদি DOM কখনই পুনরায় লোড না হয়, তবে কেউ এসে .hide-form-এর সাথে আরেকটি উপাদান যোগ করার আগে এটি কেবল সময়ের ব্যাপার। এখন আপনার একটি দ্বন্দ্ব আছে।
আপনার কাছে প্রচুর বৈশ্বিক রেফারেন্স থাকলে এই ধরনের দ্বন্দ্ব ঘটে। এবং কিভাবে আপনি গ্লোবাল রেফারেন্স সংখ্যা কমাতে? আপনি নামস্থান ব্যবহার করুন৷
নেমস্পেসিং নির্বাচক
নীচের রুবি ক্লাসে, আমরা একটি বিশ্বব্যাপী নাম ব্যবহার করছি - ক্লাসের নাম - প্রচুর পদ্ধতির নাম লুকানোর জন্য৷
# One global name hides two method names
class MyClass
def method1
end
def method2
end
end
যদিও নামস্থান DOM উপাদানগুলির জন্য কোনও অন্তর্নির্মিত সমর্থন নেই (অন্তত ES6 ওয়েব কম্পোনেন্ট না আসা পর্যন্ত নয়) কোডিং কনভেনশনগুলির সাথে নেমস্পেসগুলি অনুকরণ করা সম্ভব৷
উদাহরণস্বরূপ, কল্পনা করুন যে আপনি একটি ট্যাগ সম্পাদনা উইজেট বাস্তবায়ন করতে চান। নামস্থান ছাড়া, এটা এই মত কিছু দেখতে পারে. উল্লেখ্য যে তিনটি বিশ্বব্যাপী রেফারেন্স আছে।
// <input class="tags" type="text" />
// <button class="tag-submit">Save</button>
// <span class="tag-status"></span>
$(".tag-submit").click(function(){
save($(".tags").val());
$(".tag-status").html("Tags were saved");
});
যাইহোক, একটি "নেমস্পেস" তৈরি করে এবং এর সাথে সম্পর্কিত সমস্ত উপাদান লুকআপ তৈরি করে, আমরা একটিতে বিশ্বব্যাপী রেফারেন্সের সংখ্যা কমাতে পারি। আমরা বেশ কয়েকটি ক্লাস সম্পূর্ণরূপে পরিত্রাণ পেয়েছি।
// <div class="tags-component">
// <input type="text" />
// <button>Save</button>
// <span></span>
// </div>
$container = $("#tags-component")
$container.on("click", "button" function(){
save($container.find("input").val());
$container.find("span").html("Tags were saved");
});
আমি তোমাকে বলেছিলাম এটা সহজ।
উপরের উদাহরণে, আমি আমার DOM এলিমেন্টগুলিকে "ট্যাগ-কম্পোনেন্ট"-এর ক্লাস সহ একটি কন্টেইনারের ভিতরে রেখে নামস্থানে রেখেছি। সেই বিশেষ নামের বিশেষ কিছু নেই। কিন্তু আমি যদি এমন একটি নামকরণের রীতি গ্রহণ করি যেখানে প্রতিটি নেমস্পেস কন্টেইনারের একটি ক্লাস শেষ হয় "-কম্পোনেন্ট" এ কিছু খুব আকর্ষণীয় জিনিস ঘটে।
আপনি এক নজরে ভুল বিশ্ব নির্বাচকদের চিনতে পারেন৷
আপনি যদি একমাত্র গ্লোবাল সিলেক্টরদের অনুমতি দেন কম্পোনেন্টে, এবং সমস্ত কম্পোনেন্টের একটি ক্লাস শেষ হয় "-কম্পোনেন্ট" তাহলে আপনি এক নজরে দেখতে পারেন যদি আপনার কোন খারাপ গ্লোবাল সিলেক্টর থাকে।
// Bad
$(".foo").blah()
// Ok
$(".foo-component".blah()
এইচটিএমএল নিয়ন্ত্রণ করে এমন JS খুঁজে পাওয়া সহজ হয়ে যায়
আসুন আমাদের ইন্টারেক্টিভ ট্যাগ ফর্মটি আবার দেখুন। আপনি ফর্মের জন্য HTML লিখেছেন। এখন আপনাকে কিছু JS এবং CSS যোগ করতে হবে। কিন্তু আপনি সেই ফাইলগুলো কোথায় রাখবেন? সৌভাগ্যবশত, যখন আপনার কাছে নেমস্পেসের জন্য একটি নামকরণ স্কিম থাকে, তখন এটি সহজেই JS এবং CSS ফাইলগুলির জন্য একটি নামকরণ স্কিমে অনুবাদ করে। ডিরেক্টরি ট্রি দেখতে কেমন হতে পারে তা এখানে।
.
├── javascripts
| ├── application.coffee
│ └── components
│ └── tags.coffee
└── stylesheets
├── application.scss
└── components
└── tags.scss
স্বয়ংক্রিয় শুরু
একটি ঐতিহ্যগত ওয়েব অ্যাপে, পৃষ্ঠা লোডের সময় আপনার সমস্ত JS শুরু করা স্বাভাবিক। কিন্তু PJAX এবং Turbolinks-এর সাথে, আপনার DOM থেকে সব সময় উপাদান যোগ করা এবং সরানো হচ্ছে। এই কারণে, এটি সত্যিই উপকারী যদি আপনার কোডটি স্বয়ংক্রিয়ভাবে সনাক্ত করতে পারে যখন নতুন উপাদানগুলি ডোমে প্রবেশ করে এবং ফ্লাইতে তাদের জন্য যা কিছু প্রয়োজন JS শুরু করে৷
একটি সামঞ্জস্যপূর্ণ নামকরণ স্কিম, এটি সত্যিই সহজ করে তোলে। স্বয়ংক্রিয়ভাবে শুরু করার জন্য আপনি নিতে পারেন এমন অসংখ্য পন্থা রয়েছে। এখানে একটি:
Initializers = {
tags: function(el){
$(el).on("click", "button", function(){
// setup component
});
}
// Other initializers can go here
}
// Handler called on every normal and pjax page load
$(document).on("load, pjax:load", function(){
for(var key in Initializers){
$("." + key + "-component").each(Initializers[key]);
}
}
এটি আপনার সিএসএসকে আরও ভালো করে তোলে!
জাভাস্ক্রিপ্ট একটি ওয়েব পৃষ্ঠায় দ্বন্দ্বের একমাত্র উৎস নয়। সিএসএস আরও খারাপ হতে পারে! সৌভাগ্যবশত, আমাদের নিফটি নেমস্পেসিং সিস্টেমটি বিরোধ ছাড়াই CSS লেখাকে আরও সহজ করে তোলে। এটি SCSS-এ আরও সুন্দর:
.tags-component {
input { ... }
button { ... }
span { ... }
}