ওয়েব ওয়ার্কারের জাভাস্ক্রিপ্ট মডিউলের সাহায্যে ব্যাকগ্রাউন্ড থ্রেডে ভারী লিফ্টিং সরানো এখন আরও সহজ।
JavaScript হল সিঙ্গল-থ্রেডেড, যার অর্থ হল এটি একবারে শুধুমাত্র একটি অপারেশন করতে পারে। এটি সহজবোধ্য এবং ওয়েবে অনেক ক্ষেত্রে ভাল কাজ করে, তবে ডেটা প্রসেসিং, পার্সিং, কম্পিউটেশন বা বিশ্লেষণের মতো ভারী কাজ করার প্রয়োজন হলে সমস্যা হতে পারে। ওয়েবে আরও বেশি জটিল অ্যাপ্লিকেশন ডেলিভার করা হচ্ছে, তাই মাল্টি-থ্রেডেড প্রসেসিংয়ের প্রয়োজনীয়তাও বাড়ছে।
ওয়েব প্ল্যাটফর্মে, থ্রেডিং ও প্যারালেলিজমের জন্য প্রধান প্রিমিটিভ হল Web Workers API। ওয়ার্কার হল অপারেটিং সিস্টেম থ্রেড-এর উপরে একটি লাইটওয়েট অ্যাবস্ট্রাকশন যা ইন্টার-থ্রেড কমিউনিকেশনের জন্য একটি মেসেজ পাসিং API প্রকাশ করে। এটি অত্যন্ত উপযোগী হতে পারে যখন আপনি ব্যয়বহুল কম্পিউটেশন বা বৃহৎ ডেটাসেট নিয়ে কাজ করছেন, যা মূল থ্রেডকে মসৃণভাবে চলতে দেয় যখন এক বা একাধিক ব্যাকগ্রাউন্ড থ্রেডে ব্যয়বহুল অপারেশনগুলি সম্পন্ন হয়।
এখানে ওয়ার্কার ব্যবহারের একটি সাধারণ উদাহরণ দেওয়া হল, যেখানে একটি ওয়ার্কার স্ক্রিপ্ট মূল থ্রেড থেকে মেসেজ শোনে এবং নিজস্ব মেসেজ ফেরত পাঠিয়ে উত্তর দেয়:
page.js:
const worker = new Worker('worker.js');
worker.addEventListener('message', e => {
console.log(e.data);
});
worker.postMessage('hello');
worker.js:
addEventListener('message', e => {
if (e.data === 'hello') {
postMessage('world');
}
});
Web Worker API দশ বছরেরও বেশি সময় ধরে বেশিরভাগ ব্রাউজারে উপলভ্য আছে। এর অর্থ হল, কর্মীরা ব্রাউজার থেকে দুর্দান্ত সহায়তা পান এবং সেগুলি ভালভাবে অপ্টিমাইজ করা থাকে। এর পাশাপাশি, জাভাস্ক্রিপ্ট মডিউলের অনেক আগে থেকেই এগুলি ব্যবহার করা হচ্ছে। যেহেতু ওয়ার্কার ডিজাইন করার সময় কোনও মডিউল সিস্টেম ছিল না, তাই ওয়ার্কারে কোড লোড করা এবং স্ক্রিপ্ট কম্পোজ করার জন্য API ২০০৯ সালে প্রচলিত সিঙ্ক্রোনাস স্ক্রিপ্ট লোডিং পদ্ধতির মতোই রয়ে গেছে।
ইতিহাস: ক্লাসিক কর্মী
Worker কনস্ট্রাক্টর একটি ক্লাসিক
স্ক্রিপ্ট URL নেয়, যা
ডকুমেন্ট URL-এর সাথে সম্পর্কিত। এটি অবিলম্বে নতুন ওয়ার্কার ইনস্ট্যান্সের রেফারেন্স রিটার্ন করে,
যা একটি মেসেজিং ইন্টারফেসের পাশাপাশি একটি terminate() পদ্ধতি প্রকাশ করে যা অবিলম্বে ওয়ার্কারকে থামায় এবং
ধ্বংস করে।
const worker = new Worker('worker.js');
অতিরিক্ত কোড লোড করার জন্য ওয়েব ওয়ার্কারের মধ্যে একটি importScripts() ফাংশন উপলভ্য, কিন্তু এটি
প্রতিটি স্ক্রিপ্ট ফেচ ও মূল্যায়ন করার জন্য ওয়ার্কারের এক্সিকিউশন পজ করে। এটি ক্লাসিক <script> ট্যাগের মতো গ্লোবাল স্কোপে স্ক্রিপ্টও এক্সিকিউট করে, যার অর্থ হল একটি স্ক্রিপ্টের ভেরিয়েবল অন্য স্ক্রিপ্টের ভেরিয়েবল দ্বারা ওভাররাইট করা যেতে পারে।
worker.js:
importScripts('greet.js');
// ^ could block for seconds
addEventListener('message', e => {
postMessage(sayHello());
});
greet.js:
// global to the whole worker
function sayHello() {
return 'world';
}
এই কারণে, ওয়েব ওয়ার্কাররা ঐতিহাসিকভাবে কোনও অ্যাপ্লিকেশনের আর্কিটেকচারের উপর একটি বড় প্রভাব আরোপ করেছে। আধুনিক ডেভেলপমেন্ট প্র্যাক্টিস না ছেড়ে ওয়েব ওয়ার্কার ব্যবহার করার জন্য ডেভেলপারদের
চতুর টুলিং ও ওয়ার্কঅ্যারাউন্ড তৈরি করতে হয়েছে। উদাহরণস্বরূপ, webpack-এর মতো বান্ডলার
জেনারেট করা কোডে একটি ছোট মডিউল লোডার ইমপ্লিমেন্টেশন এম্বেড করে যা কোড লোড করার জন্য importScripts()
ব্যবহার করে, কিন্তু ভেরিয়েবেল সংঘর্ষ এড়াতে এবং ডিপেন্ডেন্সি ইমপোর্ট ও এক্সপোর্ট সিমুলেট করতে ফাংশনে মডিউল র্যাপ করে।
মডিউল কর্মীদের নাম লিখুন
Chrome 80-এ ওয়েব ওয়ার্কারদের জন্য একটি নতুন মোড শিপিং করা হচ্ছে, যাকে মডিউল ওয়ার্কার বলা হয়। এটি JavaScript
মডিউল-এর কর্মদক্ষতা এবং পারফর্ম্যান্সের সুবিধা প্রদান করে। Worker
কনস্ট্রাক্টর এখন একটি নতুন {type:"module"} বিকল্প গ্রহণ করে, যা স্ক্রিপ্ট লোডিং এবং
এক্সিকিউশন পরিবর্তন করে <script type="module">-এর সাথে মেলে।
const worker = new Worker('worker.js', {
type: 'module'
});
মডিউল ওয়ার্কার স্ট্যান্ডার্ড জাভাস্ক্রিপ্ট মডিউল হওয়ার কারণে, সেগুলি ইমপোর্ট ও এক্সপোর্ট স্টেটমেন্ট ব্যবহার করতে পারে। সব JavaScript মডিউলের মতো, ডিপেন্ডেন্সি শুধুমাত্র একবারই নির্দিষ্ট কন্টেক্সটে (প্রধান থ্রেড, ওয়ার্কার ইত্যাদি) এক্সিকিউট করা হয় এবং ভবিষ্যতের সব ইমপোর্ট আগে থেকে এক্সিকিউট করা মডিউল ইনস্ট্যান্সকে রেফার করে। জাভাস্ক্রিপ্ট মডিউল লোড ও এক্সিকিউট করার প্রসেসও ব্রাউজার অপ্টিমাইজ করে। মডিউল এক্সিকিউট করার আগে মডিউলের ডিপেন্ডেন্সি লোড করা যেতে পারে, যা সম্পূর্ণ মডিউল ট্রিকে সমান্তরালভাবে লোড করার অনুমতি দেয়। মডিউল লোড করার সময় পার্স করা কোডও ক্যাশে করা হয়, যার অর্থ হল, মূল থ্রেড এবং ওয়ার্কারে ব্যবহার করা মডিউলগুলি শুধুমাত্র একবার পার্স করলেই হয়।
জাভাস্ক্রিপ্ট মডিউলে পরিবর্তন করার ফলে, ওয়ার্কারের এক্সিকিউশন ব্লক না করেই ধীরে ধীরে লোড করা কোডের জন্য ডায়নামিক
ইমপোর্ট ব্যবহার করাও সম্ভব হয়। ডিপেন্ডেন্সি লোড করার জন্য importScripts() ব্যবহার করার চেয়ে ডায়নামিক ইমপোর্ট অনেক বেশি স্পষ্ট,
কারণ গ্লোবাল ভেরিয়েবেলের উপর নির্ভর করার পরিবর্তে ইমপোর্ট করা মডিউলের এক্সপোর্ট রিটার্ন করা হয়।
worker.js:
import { sayHello } from './greet.js';
addEventListener('message', e => {
postMessage(sayHello());
});
greet.js:
import greetings from './data.js';
export function sayHello() {
return greetings.hello;
}
দুর্দান্ত পারফর্ম্যান্স নিশ্চিত করতে, মডিউল ওয়ার্কারের মধ্যে পুরনো importScripts() পদ্ধতি উপলভ্য নেই। JavaScript মডিউল ব্যবহার করার জন্য ওয়ার্কার পরিবর্তন করার অর্থ হল সব কোড স্ট্রিক্ট
মোডে লোড করা হয়েছে। আরেকটি
উল্লেখযোগ্য পরিবর্তন হল, JavaScript মডিউলের টপ-লেভেল স্কোপে this-এর ভ্যালু হল
undefined, যেখানে ক্লাসিক ওয়ার্কারের ক্ষেত্রে ভ্যালু হল ওয়ার্কারের গ্লোবাল স্কোপ। সৌভাগ্যবশত, গ্লোবাল স্কোপের রেফারেন্স প্রদান করার জন্য
সবসময় একটি self গ্লোবাল থাকে। এটি
সার্ভিস ওয়ার্কার সহ সব ধরনের ওয়ার্কার এবং DOM-এ উপলভ্য।
modulepreload-এর মাধ্যমে প্রিলোড ওয়ার্কার
মডিউল ওয়ার্কারের সাথে যে উল্লেখযোগ্য পারফর্ম্যান্সের উন্নতি হয় তা হল ওয়ার্কার ও তাদের ডিপেন্ডেন্সি প্রিলোড করার ক্ষমতা। মডিউল ওয়ার্কারের মাধ্যমে, স্ক্রিপ্ট স্ট্যান্ডার্ড জাভাস্ক্রিপ্ট মডিউল হিসেবে লোড ও এক্সিকিউট করা হয়, যার অর্থ হল, modulepreload ব্যবহার করে এগুলি প্রিলোড ও এমনকি প্রি-পার্স করা যেতে পারে:
<!-- preloads worker.js and its dependencies: -->
<link rel="modulepreload" href="worker.js">
<script>
addEventListener('load', () => {
// our worker code is likely already parsed and ready to execute!
const worker = new Worker('worker.js', { type: 'module' });
});
</script>
এছাড়াও, প্রিলোড করা মডিউল মূল থ্রেড ও মডিউল ওয়ার্কার, দু'জনেই ব্যবহার করতে পারে। এটি সেইসব মডিউলের ক্ষেত্রে উপযোগী যেগুলি দুটি ক্ষেত্রেই ইমপোর্ট করা হয় অথবা যেখানে আগে থেকে জানা সম্ভব নয় যে কোনও মডিউল মূল থ্রেডে নাকি ওয়ার্কারে ব্যবহার করা হবে।
আগে, ওয়েব ওয়ার্কার স্ক্রিপ্ট প্রিলোড করার জন্য উপলভ্য বিকল্পগুলি সীমিত ছিল এবং
সেগুলি নির্ভরযোগ্য ছিল না। প্রিলোড করার জন্য ক্লাসিক ওয়ার্কারদের নিজস্ব "ওয়ার্কার" রিসোর্স টাইপ ছিল, কিন্তু কোনও
ব্রাউজার <link rel="preload" as="worker"> প্রয়োগ করেনি। এর ফলে, ওয়েব ওয়ার্কার প্রিলোড করার জন্য
উপলভ্য প্রাথমিক টেকনিক হল <link rel="prefetch"> ব্যবহার করা, যা সম্পূর্ণভাবে
HTTP ক্যাশের উপর নির্ভর করে। সঠিক ক্যাশিং হেডারের সাথে ব্যবহার করা হলে, এটি ওয়ার্কার স্ক্রিপ্ট ডাউনলোড করার জন্য অপেক্ষা না করেই
ওয়ার্কার ইনস্ট্যান্টিয়েশন এড়ানো সম্ভব করে তোলে। তবে,
modulepreload-এর মতো এই টেকনিক ডিপেন্ডেন্সি প্রিলোড করা বা প্রি-পার্সিং করার সুবিধা দেয় না।
শেয়ার করা কর্মীদের ক্ষেত্রে কী হবে?
Chrome 83 থেকে জাভাস্ক্রিপ্ট মডিউলের জন্য সহায়তা সহ শেয়ার করা ওয়ার্কার
আপডেট করা হয়েছে। ডেডিকেটেড ওয়ার্কারের মতো,
{type:"module"} বিকল্পের মাধ্যমে শেয়ার করা ওয়ার্কার তৈরি করলে, এখন ওয়ার্কার স্ক্রিপ্ট ক্লাসিক স্ক্রিপ্টের পরিবর্তে
মডিউল হিসেবে লোড হয়:
const worker = new SharedWorker('/worker.js', {
type: 'module'
});
JavaScript মডিউলের জন্য সহায়তা পাওয়ার আগে, SharedWorker() কনস্ট্রাক্টর শুধুমাত্র একটি URL এবং একটি ঐচ্ছিক name আর্গুমেন্ট আশা করেছিল। এটি ক্লাসিক শেয়ার করা ওয়ার্কার ব্যবহারের জন্য কাজ করা চালিয়ে যাবে; তবে
মডিউল শেয়ার করা ওয়ার্কার তৈরি করতে নতুন options আর্গুমেন্ট ব্যবহার করতে হবে। উপলভ্য
বিকল্পগুলি
ডেডিকেটেড ওয়ার্কারের মতোই, যার মধ্যে name বিকল্পটি অন্তর্ভুক্ত যা
আগের name আর্গুমেন্টের স্থান অধিকার করে।
সার্ভিস ওয়ার্কার সম্পর্কে কী বলা যায়?
সার্ভিস ওয়ার্কার স্পেসিফিকেশন ইতিমধ্যেই
আপডেট করা হয়েছে যাতে এন্ট্রি পয়েন্ট হিসেবে জাভাস্ক্রিপ্ট মডিউল গ্রহণ করা যায়, মডিউল ওয়ার্কারের মতো একই {type:"module"} বিকল্প ব্যবহার করে,
তবে এই পরিবর্তন এখনও ব্রাউজারে প্রয়োগ করা হয়নি। এটি হয়ে গেলে, নিম্নলিখিত কোড ব্যবহার করে
জাভাস্ক্রিপ্ট মডিউলের মাধ্যমে সার্ভিস ওয়ার্কার ইনস্ট্যান্টিয়েট করা সম্ভব হবে:
navigator.serviceWorker.register('/sw.js', {
type: 'module'
});
এখন স্পেসিফিকেশন আপডেট করা হয়েছে, ব্রাউজার নতুন আচরণ প্রয়োগ করা শুরু করছে। এতে সময় লাগে কারণ সার্ভিস ওয়ার্কারে জাভাস্ক্রিপ্ট মডিউল নিয়ে আসার সাথে কিছু অতিরিক্ত জটিলতা যুক্ত থাকে। আপডেট ট্রিগার করা হবে কিনা তা নির্ধারণ করার সময়, সার্ভিস ওয়ার্কার রেজিস্ট্রেশনকে ইম্পোর্ট করা স্ক্রিপ্টকে তার আগের ক্যাশে করা ভার্সনের সাথে তুলনা করতে হবে এবং সার্ভিস ওয়ার্কারের জন্য ব্যবহার করা হলে, JavaScript মডিউলের জন্য এটি প্রয়োগ করতে হবে। এছাড়াও, আপডেট চেক করার সময় নির্দিষ্ট কিছু ক্ষেত্রে স্ক্রিপ্টের জন্য সার্ভিস ওয়ার্কারদের ক্যাশে বাইপাস করতে পারতে হবে।
অতিরিক্ত রিসোর্স ও আরও তথ্য
- ফিচার স্ট্যাটাস, ব্রাউজার কনসেনসাস ও স্ট্যান্ডার্ডাইজেশন
- আসল মডিউল ওয়ার্কার স্পেক যোগ করা
- শেয়ার করা ওয়ার্কারের জন্য জাভাস্ক্রিপ্ট মডিউল
- সার্ভিস ওয়ার্কারের জন্য জাভাস্ক্রিপ্ট মডিউল: Chrome-এ প্রয়োগ করার স্ট্যাটাস