জাভাস্ক্রিপ্ট থেকে কিভাবে বিভিন্ন ধরনের সম্পদ আমদানি এবং বান্ডিল করতে হয় তা জানুন।
ধরুন আপনি একটি ওয়েব অ্যাপে কাজ করছেন। সেক্ষেত্রে, সম্ভবত আপনাকে শুধুমাত্র জাভাস্ক্রিপ্ট মডিউলের সাথেই নয়, অন্যান্য সব ধরনের সম্পদের সাথেও মোকাবিলা করতে হবে—ওয়েব ওয়ার্কার (যা জাভাস্ক্রিপ্ট, কিন্তু নিয়মিত মডিউল গ্রাফের অংশ নয়), ছবি, স্টাইলশীট, ফন্ট, ওয়েব অ্যাসেম্বলি মডিউল এবং অন্যান্য।
এইচটিএমএল-এ সরাসরি এই সংস্থানগুলির কিছু রেফারেন্স অন্তর্ভুক্ত করা সম্ভব, তবে প্রায়শই তারা যৌক্তিকভাবে পুনরায় ব্যবহারযোগ্য উপাদানগুলির সাথে সংযুক্ত থাকে। উদাহরণস্বরূপ, জাভাস্ক্রিপ্ট অংশে বাঁধা একটি কাস্টম ড্রপডাউনের জন্য একটি স্টাইলশীট, একটি টুলবার উপাদানের সাথে বাঁধা আইকন চিত্র, বা WebAssembly মডিউল এটির JavaScript আঠার সাথে বাঁধা। এই ক্ষেত্রে, তাদের JavaScript মডিউলগুলি থেকে সরাসরি সংস্থানগুলি উল্লেখ করা এবং সংশ্লিষ্ট উপাদানটি লোড করা হলে (বা যদি) গতিশীলভাবে লোড করা আরও সুবিধাজনক।
যাইহোক, বেশিরভাগ বড় প্রকল্পে এমন সিস্টেম তৈরি করা হয় যা অতিরিক্ত অপ্টিমাইজেশন এবং বিষয়বস্তুর পুনর্গঠন করে—উদাহরণস্বরূপ, বান্ডলিং এবং মিনিফিকেশন। তারা কোডটি কার্যকর করতে পারে না এবং প্রয়োগের ফলাফল কী হবে তা ভবিষ্যদ্বাণী করতে পারে না, বা তারা জাভাস্ক্রিপ্টের প্রতিটি সম্ভাব্য স্ট্রিং আক্ষরিক অতিক্রম করতে পারে না এবং এটি একটি রিসোর্স URL কিনা সে সম্পর্কে অনুমান করতে পারে না। তাহলে আপনি কিভাবে জাভাস্ক্রিপ্ট উপাদান দ্বারা লোড করা সেই গতিশীল সম্পদগুলিকে "দেখতে" এবং বিল্ডে অন্তর্ভুক্ত করতে পারেন?
বান্ডলারে কাস্টম আমদানি
একটি সাধারণ পদ্ধতি হল স্ট্যাটিক আমদানি সিনট্যাক্স পুনরায় ব্যবহার করা। কিছু বান্ডলারে এটি ফাইল এক্সটেনশনের মাধ্যমে স্বয়ংক্রিয়ভাবে শনাক্ত করতে পারে, অন্যরা প্লাগইনগুলিকে নিম্নলিখিত উদাহরণের মতো একটি কাস্টম URL স্কিম ব্যবহার করার অনুমতি দেয়:
// regular JavaScript import
import { loadImg } from './utils.js';
// special "URL imports" for assets
import imageUrl from 'asset-url:./image.png';
import wasmUrl from 'asset-url:./module.wasm';
import workerUrl from 'js-url:./worker.js';
loadImg(imageUrl);
WebAssembly.instantiateStreaming(fetch(wasmUrl));
new Worker(workerUrl);
যখন একটি বান্ডলার প্লাগইন একটি এক্সটেনশন সনাক্ত করে বা এই জাতীয় একটি স্পষ্ট কাস্টম স্কিম ( asset-url:
এবং js-url:
উপরের উদাহরণে) সহ একটি আমদানি খুঁজে পায়, তখন এটি বিল্ড গ্রাফে রেফারেন্সযুক্ত সম্পদ যোগ করে, এটি চূড়ান্ত গন্তব্যে অনুলিপি করে, ইউআরএল চালানোর সময় চূড়ান্তভাবে ব্যবহার করার সময় সম্পদের প্রকারের জন্য প্রযোজ্য অপ্টিমাইজেশান সঞ্চালন করে এবং ফেরত দেয়।
এই পদ্ধতির সুবিধা: জাভাস্ক্রিপ্ট ইম্পোর্ট সিনট্যাক্স পুনরায় ব্যবহার করা নিশ্চিত করে যে সমস্ত ইউআরএল স্থির এবং বর্তমান ফাইলের সাথে আপেক্ষিক, যা বিল্ড সিস্টেমের জন্য এই ধরনের নির্ভরতা সনাক্ত করা সহজ করে তোলে।
যাইহোক, এটির একটি উল্লেখযোগ্য ত্রুটি রয়েছে: এই ধরনের কোড ব্রাউজারে সরাসরি কাজ করতে পারে না, কারণ ব্রাউজার সেই কাস্টম আমদানি স্কিম বা এক্সটেনশনগুলি কীভাবে পরিচালনা করতে হয় তা জানে না। আপনি যদি সমস্ত কোড নিয়ন্ত্রণ করেন এবং যাইহোক বিকাশের জন্য একটি বান্ডলারের উপর নির্ভর করেন তবে এটি ঠিক হতে পারে, তবে ঘর্ষণ কমাতে কমপক্ষে বিকাশের সময় সরাসরি ব্রাউজারে জাভাস্ক্রিপ্ট মডিউল ব্যবহার করা ক্রমবর্ধমান সাধারণ। একটি ছোট ডেমোতে কাজ করা কেউ এমনকি উত্পাদনের ক্ষেত্রেও একটি বান্ডলারের প্রয়োজন নাও হতে পারে।
ব্রাউজার এবং বান্ডলারের জন্য ইউনিভার্সাল প্যাটার্ন
আপনি যদি একটি পুনঃব্যবহারযোগ্য কম্পোনেন্ট নিয়ে কাজ করেন, তাহলে আপনি এটিকে যেকোনো পরিবেশে কাজ করতে চান, তা ব্রাউজারে সরাসরি ব্যবহার করা হোক বা একটি বড় অ্যাপের অংশ হিসেবে পূর্ব-নির্মিত হোক। বেশিরভাগ আধুনিক বান্ডলার জাভাস্ক্রিপ্ট মডিউলগুলিতে নিম্নলিখিত প্যাটার্ন গ্রহণ করে এটির জন্য অনুমতি দেয়:
new URL('./relative-path', import.meta.url)
এই প্যাটার্নটি সরঞ্জামের মাধ্যমে স্থিরভাবে সনাক্ত করা যেতে পারে, প্রায় যেন এটি একটি বিশেষ সিনট্যাক্স, তবুও এটি একটি বৈধ জাভাস্ক্রিপ্ট অভিব্যক্তি যা সরাসরি ব্রাউজারেও কাজ করে।
এই প্যাটার্নটি ব্যবহার করার সময়, উপরের উদাহরণটি এইভাবে পুনরায় লেখা যেতে পারে:
// regular JavaScript import
import { loadImg } from './utils.js';
loadImg(new URL('./image.png', import.meta.url));
WebAssembly.instantiateStreaming(
fetch(new URL('./module.wasm', import.meta.url)),
{ /* … */ }
);
new Worker(new URL('./worker.js', import.meta.url));
এটা কিভাবে কাজ করে? এর এটা ভেঙ্গে দেওয়া যাক. new URL(...)
কনস্ট্রাক্টর একটি আপেক্ষিক ইউআরএলকে প্রথম আর্গুমেন্ট হিসেবে নেয় এবং দ্বিতীয় আর্গুমেন্ট হিসেবে দেওয়া একটি পরম ইউআরএলের বিপরীতে এটি সমাধান করে। আমাদের ক্ষেত্রে, দ্বিতীয় আর্গুমেন্টটি হল import.meta.url
যা বর্তমান জাভাস্ক্রিপ্ট মডিউলের URL দেয়, তাই প্রথম আর্গুমেন্টটি এর সাপেক্ষে যেকোনো পাথ হতে পারে।
এটির গতিশীল আমদানির অনুরূপ ট্রেডঅফ রয়েছে। import(someUrl)
মত নির্বিচারে অভিব্যক্তি সহ import(...)
ব্যবহার করা সম্ভব হলেও, বান্ডলাররা কম্পাইল-টাইমে পরিচিত একটি নির্ভরতা প্রিপ্রসেস করার উপায় হিসাবে স্ট্যাটিক ইউআরএল import('./some-static-url.js')
সহ একটি প্যাটার্নকে বিশেষ চিকিত্সা দেয়, তবুও এটিকে তার নিজস্ব অংশে বিভক্ত করে যা লোডডনাম।
একইভাবে, আপনি new URL(...)
ব্যবহার করতে পারেন নির্বিচারে অভিব্যক্তি যেমন new URL(relativeUrl, customAbsoluteBase)
, তথাপি new URL('...', import.meta.url)
প্যাটার্নটি বান্ডলারদের জন্য প্রিপ্রসেস করার জন্য একটি স্পষ্ট সংকেত এবং প্রধান জাভাস্ক্রিপ্টের পাশাপাশি একটি নির্ভরতা অন্তর্ভুক্ত করে।
অস্পষ্ট আপেক্ষিক ইউআরএল
আপনি হয়ত ভাবছেন, কেন বান্ডলাররা অন্যান্য সাধারণ প্যাটার্ন শনাক্ত করতে পারে না—উদাহরণস্বরূপ, new URL
র্যাপার ছাড়া fetch('./module.wasm')
?
কারণ হল, আমদানি বিবৃতির বিপরীতে, যেকোনো গতিশীল অনুরোধ নথিতে তুলনামূলকভাবে সমাধান করা হয়, বর্তমান জাভাস্ক্রিপ্ট ফাইলে নয়। ধরা যাক আপনার নিম্নলিখিত কাঠামো আছে:
-
index.html
:
html <script src="src/main.js" type="module"></script>
-
src/
-
main.js
-
module.wasm
-
আপনি main.js
থেকে module.wasm
লোড করতে চাইলে, এটি fetch('./module.wasm')
মতো একটি আপেক্ষিক পথ ব্যবহার করতে প্রলুব্ধ হতে পারে।
যাইহোক, fetch
জাভাস্ক্রিপ্ট ফাইলের URL জানেন না যেটিতে এটি কার্যকর করা হয়েছে, পরিবর্তে, এটি নথির সাথে তুলনামূলকভাবে URLগুলি সমাধান করে। ফলস্বরূপ, fetch('./module.wasm')
উদ্দিষ্ট http://example.com/src/module.wasm
এর পরিবর্তে http://example.com/module.wasm
লোড করার চেষ্টা করবে এবং ব্যর্থ হবে (অথবা, আরও খারাপ, নীরবে আপনার উদ্দেশ্যের চেয়ে আলাদা একটি সংস্থান লোড করবে)।
আপেক্ষিক URLটিকে new URL('...', import.meta.url)
এ মোড়ানোর মাধ্যমে আপনি এই সমস্যাটি এড়াতে পারেন এবং গ্যারান্টি দিতে পারেন যে কোনো প্রদত্ত URL বর্তমান জাভাস্ক্রিপ্ট মডিউলের ( import.meta.url
) কোনো লোডারের কাছে পাঠানোর আগে এটির সাথে সাপেক্ষে সমাধান করা হয়েছে৷
fetch('./module.wasm')
fetch(new URL('./module.wasm', import.meta.url))
দিয়ে প্রতিস্থাপন করুন এবং এটি সফলভাবে প্রত্যাশিত WebAssembly মডিউল লোড করবে, সেইসাথে বান্ডলারদের সেই আপেক্ষিক পাথগুলি নির্মাণের সময়ও খুঁজে বের করার উপায় দেবে।
টুলিং সমর্থন
বান্ডলার
নিম্নলিখিত বান্ডলারগুলি ইতিমধ্যেই new URL
স্কিম সমর্থন করে:
- ওয়েবপ্যাক v5
- রোলআপ (প্লাগইনগুলির মাধ্যমে অর্জিত— জেনেরিক সম্পদের জন্য @web/rollup-plugin-import-meta-assets এবং @surma/rollup-plugin-off-main-thread শ্রমিকদের জন্য বিশেষভাবে।)
- পার্সেল v2 (বিটা)
- ভিটে
ওয়েব অ্যাসেম্বলি
WebAssembly এর সাথে কাজ করার সময়, আপনি সাধারণত হাত দিয়ে Wasm মডিউল লোড করবেন না, বরং টুলচেন দ্বারা নির্গত জাভাস্ক্রিপ্ট আঠালো আমদানি করবেন। নিম্নলিখিত টুলচেনগুলি আপনার জন্য হুডের নীচে বর্ণিত new URL(...)
প্যাটার্ন নির্গত করতে পারে৷
Emscripten এর মাধ্যমে C/C++
Emscripten ব্যবহার করার সময়, আপনি নিম্নলিখিত বিকল্পগুলির মধ্যে একটির মাধ্যমে নিয়মিত স্ক্রিপ্টের পরিবর্তে একটি ES6 মডিউল হিসাবে জাভাস্ক্রিপ্ট আঠালো নির্গত করতে বলতে পারেন:
$ emcc input.cpp -o output.mjs
## or, if you don't want to use .mjs extension
$ emcc input.cpp -o output.js -s EXPORT_ES6
এই বিকল্পটি ব্যবহার করার সময়, আউটপুট হুডের নীচে new URL(..., import.meta.url)
প্যাটার্ন ব্যবহার করবে, যাতে বান্ডলাররা স্বয়ংক্রিয়ভাবে সংশ্লিষ্ট Wasm ফাইলটি খুঁজে পেতে পারে।
আপনি একটি -pthread
পতাকা যোগ করে WebAssembly থ্রেডগুলির সাথে এই বিকল্পটি ব্যবহার করতে পারেন:
$ emcc input.cpp -o output.mjs -pthread
## or, if you don't want to use .mjs extension
$ emcc input.cpp -o output.js -s EXPORT_ES6 -pthread
এই ক্ষেত্রে, জেনারেট করা ওয়েব ওয়ার্কার একই ফ্যাশনে অন্তর্ভুক্ত করা হবে এবং একইভাবে বান্ডলার এবং ব্রাউজার দ্বারাও আবিষ্কার করা যাবে।
wasm-pack / wasm-bindgen এর মাধ্যমে মরিচা
wasm-pack — WebAssembly-এর জন্য প্রাথমিক মরিচা টুলচেন—এছাড়াও বেশ কিছু আউটপুট মোড রয়েছে।
ডিফল্টরূপে, এটি একটি জাভাস্ক্রিপ্ট মডিউল নির্গত করবে যা WebAssembly ESM ইন্টিগ্রেশন প্রস্তাবের উপর নির্ভর করে। লেখার মুহুর্তে, এই প্রস্তাবটি এখনও পরীক্ষামূলক, এবং আউটপুট শুধুমাত্র Webpack এর সাথে বান্ডিল করলেই কাজ করবে।
পরিবর্তে, আপনি --target web
মাধ্যমে একটি ব্রাউজার-সামঞ্জস্যপূর্ণ ES6 মডিউল নির্গত করতে wasm-pack বলতে পারেন:
$ wasm-pack build --target web
আউটপুট বর্ণিত new URL(..., import.meta.url)
প্যাটার্ন ব্যবহার করবে এবং Wasm ফাইলটি বান্ডলারদের দ্বারা স্বয়ংক্রিয়ভাবে আবিষ্কৃত হবে।
আপনি যদি মরিচা দিয়ে WebAssembly থ্রেড ব্যবহার করতে চান তবে গল্পটি একটু বেশি জটিল। আরও জানতে গাইডের সংশ্লিষ্ট বিভাগটি দেখুন।
সংক্ষিপ্ত সংস্করণ হল যে আপনি নির্বিচারে থ্রেড API ব্যবহার করতে পারবেন না, তবে আপনি যদি Rayon ব্যবহার করেন, আপনি এটিকে wasm-bindgen-rayon অ্যাডাপ্টারের সাথে একত্রিত করতে পারেন যাতে এটি ওয়েবে শ্রমিকদের জন্ম দিতে পারে। wasm-bindgen-rayon দ্বারা ব্যবহৃত জাভাস্ক্রিপ্ট আঠালোতেও হুডের নিচে new URL(...)
প্যাটার্ন অন্তর্ভুক্ত রয়েছে , এবং তাই শ্রমিকরা আবিষ্কারযোগ্য হবে এবং বান্ডলারদের দ্বারাও অন্তর্ভুক্ত হবে।
ভবিষ্যতের বৈশিষ্ট্য
import.meta.resolve
একটি ডেডিকেটেড import.meta.resolve(...)
কল একটি সম্ভাব্য ভবিষ্যতের উন্নতি। এটি বর্তমান মডিউলের সাথে তুলনামূলকভাবে স্পেসিফায়ারগুলিকে আরও সহজবোধ্যভাবে সমাধান করার অনুমতি দেবে, অতিরিক্ত প্যারাম ছাড়াই:
new URL('...', import.meta.url)
await import.meta.resolve('...')
এটি আমদানি মানচিত্র এবং কাস্টম সমাধানকারীদের সাথে আরও ভালভাবে সংহত করবে কারণ এটি import
মতো একই মডিউল রেজোলিউশন সিস্টেমের মধ্য দিয়ে যাবে৷ এটি বান্ডলারদের জন্যও একটি শক্তিশালী সংকেত হবে কারণ এটি একটি স্ট্যাটিক সিনট্যাক্স যা URL
মতো রানটাইম API-এর উপর নির্ভর করে না।
import.meta.resolve
ইতিমধ্যেই Node.js-এ একটি পরীক্ষা হিসাবে প্রয়োগ করা হয়েছে কিন্তু ওয়েবে এটি কীভাবে কাজ করবে সে সম্পর্কে এখনও কিছু অমীমাংসিত প্রশ্ন রয়েছে।
দাবী আমদানি করুন
আমদানি দাবী হল একটি নতুন বৈশিষ্ট্য যা ECMAScript মডিউল ব্যতীত অন্য প্রকারগুলি আমদানি করতে দেয়৷ আপাতত তারা JSON-এ সীমাবদ্ধ:
foo.json:
{ "answer": 42 }
main.mjs:
import json from './foo.json' assert { type: 'json' };
console.log(json.answer); // 42
এগুলি বান্ডলারদের দ্বারাও ব্যবহার করা হতে পারে এবং বর্তমানে new URL
প্যাটার্ন দ্বারা আচ্ছাদিত ব্যবহারের ক্ষেত্রে প্রতিস্থাপন করা হতে পারে, তবে প্রতি-কেস ভিত্তিতে আমদানি দাবীতে প্রকারগুলি যোগ করা হয়। আপাতত তারা শুধুমাত্র JSON-কে কভার করে, CSS মডিউলগুলি শীঘ্রই আসবে, কিন্তু অন্যান্য ধরনের সম্পদের জন্য আরও সাধারণ সমাধানের প্রয়োজন হবে।
এই বৈশিষ্ট্য সম্পর্কে আরও জানতে v8.dev বৈশিষ্ট্য ব্যাখ্যাকারী দেখুন।
উপসংহার
আপনি দেখতে পাচ্ছেন, ওয়েবে নন-জাভাস্ক্রিপ্ট সংস্থানগুলি অন্তর্ভুক্ত করার বিভিন্ন উপায় রয়েছে, তবে তাদের বিভিন্ন ত্রুটি রয়েছে এবং বিভিন্ন টুলচেইন জুড়ে কাজ করে না। ভবিষ্যত প্রস্তাবগুলি আমাদেরকে বিশেষ সিনট্যাক্স সহ এই জাতীয় সম্পদ আমদানি করতে দিতে পারে, কিন্তু আমরা এখনও সেখানে নেই।
ততক্ষণ পর্যন্ত, new URL(..., import.meta.url)
প্যাটার্ন হল সবচেয়ে প্রতিশ্রুতিশীল সমাধান যা ইতিমধ্যেই ব্রাউজার, বিভিন্ন বান্ডলার এবং WebAssembly টুলচেইনে কাজ করে।