নেভিগেশন প্রিলোড সহ পরিষেবা কর্মীদের গতি বাড়ান

নেভিগেশন প্রিলোড আপনাকে সমান্তরালভাবে অনুরোধ করার মাধ্যমে পরিষেবা কর্মী স্টার্টআপের সময় কাটিয়ে উঠতে দেয়।

ব্রাউজার সমর্থন

  • ক্রোম: 59।
  • প্রান্ত: 18।
  • ফায়ারফক্স: 99।
  • সাফারি: 15.4.

উৎস

সারাংশ

সমস্যা

যখন আপনি এমন একটি সাইটে নেভিগেট করেন যেটি ইভেন্টগুলি নিয়ে আসার জন্য একটি পরিষেবা কর্মী ব্যবহার করে, ব্রাউজার পরিষেবা কর্মীকে একটি প্রতিক্রিয়ার জন্য জিজ্ঞাসা করে৷ এর মধ্যে পরিষেবা কর্মীকে বুট করা (যদি এটি ইতিমধ্যে চালু না থাকে), এবং ফেচ ইভেন্টটি প্রেরণ করা জড়িত।

বুটআপের সময় ডিভাইস এবং অবস্থার উপর নির্ভর করে। এটি সাধারণত প্রায় 50ms হয়। মোবাইলে এটি 250ms এর মত। চরম ক্ষেত্রে (ধীরগতির ডিভাইস, কষ্টে CPU) এটি 500ms এর বেশি হতে পারে। যাইহোক, যেহেতু পরিষেবা কর্মী ইভেন্টগুলির মধ্যে একটি ব্রাউজার-নির্ধারিত সময়ের জন্য জাগ্রত থাকে, আপনি শুধুমাত্র মাঝে মাঝে এই বিলম্বটি পান, যেমন ব্যবহারকারী যখন একটি নতুন ট্যাব বা অন্য সাইট থেকে আপনার সাইটে নেভিগেট করেন।

আপনি যদি ক্যাশে থেকে সাড়া দিচ্ছেন তাহলে বুট-আপ সময় কোনো সমস্যা নয়, কারণ নেটওয়ার্ক এড়িয়ে যাওয়ার সুবিধা বুট-আপ বিলম্বের চেয়ে বেশি। কিন্তু আপনি যদি নেটওয়ার্ক ব্যবহার করে সাড়া দেন...

SW বুট
নেভিগেশন অনুরোধ

পরিষেবা কর্মী বুট-আপ করার কারণে নেটওয়ার্ক অনুরোধ বিলম্বিত হয়৷

আমরা V8-এ কোড-ক্যাশিং ব্যবহার করে বুট-আপের সময় কমিয়ে চলেছি, কোনো ইভেন্ট নেই এমন পরিষেবা কর্মীদের বাদ দিয়ে , পরিষেবা কর্মীদের অনুমানমূলকভাবে চালু করার মাধ্যমে, এবং অন্যান্য অপ্টিমাইজেশানগুলি। যাইহোক, বুটআপ সময় সর্বদা শূন্যের চেয়ে বেশি হবে।

Facebook এই সমস্যার প্রভাব আমাদের নজরে এনেছে, এবং সমান্তরালভাবে নেভিগেশন অনুরোধগুলি সম্পাদন করার জন্য একটি উপায় জিজ্ঞাসা করেছে:

SW বুট
নেভিগেশন অনুরোধ

রেসকিউতে নেভিগেশন প্রিলোড

ন্যাভিগেশন প্রিলোড এমন একটি বৈশিষ্ট্য যা আপনাকে বলতে দেয়, "যখন ব্যবহারকারী একটি GET নেভিগেশন অনুরোধ করে, তখন পরিষেবা কর্মী বুট আপ করার সময় নেটওয়ার্ক অনুরোধ শুরু করুন"।

স্টার্টআপ বিলম্ব এখনও আছে, কিন্তু এটি নেটওয়ার্ক অনুরোধ ব্লক করে না, তাই ব্যবহারকারী শীঘ্রই সামগ্রী পায়।

এখানে এটির একটি ভিডিও রয়েছে, যেখানে পরিষেবা কর্মীকে একটি সময়-লুপ ব্যবহার করে ইচ্ছাকৃতভাবে 500ms স্টার্টআপ বিলম্ব দেওয়া হয়েছে:

এখানে ডেমো নিজেই . নেভিগেশন প্রিলোডের সুবিধা পেতে, আপনার এটি সমর্থন করে এমন একটি ব্রাউজার প্রয়োজন

নেভিগেশন প্রিলোড সক্রিয় করুন

addEventListener('activate', event => {
  event.waitUntil(async function() {
    // Feature-detect
    if (self.registration.navigationPreload) {
      // Enable navigation preloads!
      await self.registration.navigationPreload.enable();
    }
  }());
});

আপনি যখনই চান navigationPreload.enable() কল করতে পারেন, অথবা navigationPreload.disable() দিয়ে এটি নিষ্ক্রিয় করতে পারেন। যাইহোক, যেহেতু আপনার fetch ইভেন্টটিকে এটি ব্যবহার করতে হবে, তাই আপনার পরিষেবা কর্মীর activate ইভেন্টে এটি সক্ষম এবং অক্ষম করা ভাল৷

প্রিলোড করা প্রতিক্রিয়া ব্যবহার করে

এখন ব্রাউজারটি নেভিগেশনের জন্য প্রিলোডগুলি সম্পাদন করবে, তবে আপনাকে এখনও প্রতিক্রিয়া ব্যবহার করতে হবে:

addEventListener('fetch', event => {
  event.respondWith(async function() {
    // Respond from the cache if we can
    const cachedResponse = await caches.match(event.request);
    if (cachedResponse) return cachedResponse;

    // Else, use the preloaded response, if it's there
    const response = await event.preloadResponse;
    if (response) return response;

    // Else try the network.
    return fetch(event.request);
  }());
});

event.preloadResponse হল একটি প্রতিশ্রুতি যা একটি প্রতিক্রিয়ার সাথে সমাধান করে, যদি:

  • নেভিগেশন প্রিলোড সক্ষম করা হয়েছে৷
  • অনুরোধটি একটি GET অনুরোধ।
  • অনুরোধটি একটি নেভিগেশন অনুরোধ (যা ব্রাউজারগুলি আইফ্রেম সহ পেজ লোড করার সময় তৈরি করে)।

অন্যথায় event.preloadResponse এখনও আছে, কিন্তু এটি undefined এর সাথে সমাধান করে।

আপনার পৃষ্ঠার নেটওয়ার্ক থেকে ডেটার প্রয়োজন হলে, দ্রুততম উপায় হল পরিষেবা কর্মীর কাছে এটির অনুরোধ করা এবং ক্যাশে থেকে অংশগুলি এবং নেটওয়ার্কের অংশগুলি সহ একটি একক স্ট্রিমড প্রতিক্রিয়া তৈরি করা৷

বলুন আমরা একটি নিবন্ধ প্রদর্শন করতে চেয়েছিলাম:

addEventListener('fetch', event => {
  const url = new URL(event.request.url);
  const includeURL = new URL(url);
  includeURL.pathname += 'include';

  if (isArticleURL(url)) {
    event.respondWith(async function() {
      // We're going to build a single request from multiple parts.
      const parts = [
        // The top of the page.
        caches.match('/article-top.include'),
        // The primary content
        fetch(includeURL)
          // A fallback if the network fails.
          .catch(() => caches.match('/article-offline.include')),
        // The bottom of the page
        caches.match('/article-bottom.include')
      ];

      // Merge them all together.
      const {done, response} = await mergeResponses(parts);

      // Wait until the stream is complete.
      event.waitUntil(done);

      // Return the merged response.
      return response;
    }());
  }
});

উপরে, mergeResponses হল একটি ছোট ফাংশন যা প্রতিটি অনুরোধের স্ট্রিমগুলিকে একত্রিত করে। এর মানে নেটওয়ার্ক বিষয়বস্তু স্ট্রিম করার সময় আমরা ক্যাশেড হেডার প্রদর্শন করতে পারি।

এটি "অ্যাপ শেল" মডেলের চেয়ে দ্রুত কারণ নেটওয়ার্ক অনুরোধটি পৃষ্ঠার অনুরোধের সাথে করা হয় এবং বিষয়বস্তু বড় হ্যাক ছাড়াই স্ট্রিম করতে পারে৷

যাইহোক, includeURL এর জন্য অনুরোধ পরিষেবা কর্মীর শুরুর সময় দ্বারা বিলম্বিত হবে। আমরা এটিও ঠিক করতে নেভিগেশন প্রিলোড ব্যবহার করতে পারি, কিন্তু এই ক্ষেত্রে আমরা পুরো পৃষ্ঠাটি প্রিলোড করতে চাই না, আমরা একটি অন্তর্ভুক্ত প্রিলোড করতে চাই।

এটি সমর্থন করার জন্য, প্রতিটি প্রিলোড অনুরোধের সাথে একটি শিরোনাম পাঠানো হয়:

Service-Worker-Navigation-Preload: true

সার্ভার নিয়মিত নেভিগেশন অনুরোধের চেয়ে নেভিগেশন প্রিলোড অনুরোধের জন্য বিভিন্ন সামগ্রী পাঠাতে এটি ব্যবহার করতে পারে। শুধু একটি Vary: Service-Worker-Navigation-Preload শিরোনাম যোগ করতে মনে রাখবেন, যাতে ক্যাশে জানতে পারে যে আপনার প্রতিক্রিয়াগুলি আলাদা।

এখন আমরা প্রিলোড অনুরোধটি ব্যবহার করতে পারি:

// Try to use the preload
const networkContent = Promise.resolve(event.preloadResponse)
  // Else do a normal fetch
  .then(r => r || fetch(includeURL))
  // A fallback if the network fails.
  .catch(() => caches.match('/article-offline.include'));

const parts = [
  caches.match('/article-top.include'),
  networkContent,
  caches.match('/article-bottom')
];

হেডার পরিবর্তন করুন

ডিফল্টরূপে, Service-Worker-Navigation-Preload হেডারের মান true , কিন্তু আপনি যা চান তাতে সেট করতে পারেন:

navigator.serviceWorker.ready.then(registration => {
  return registration.navigationPreload.setHeaderValue(newValue);
}).then(() => {
  console.log('Done!');
});

উদাহরণস্বরূপ, আপনি স্থানীয়ভাবে ক্যাশে করা শেষ পোস্টের আইডিতে এটি সেট করতে পারেন, তাই সার্ভার শুধুমাত্র নতুন ডেটা ফেরত দেয়।

রাষ্ট্র পাচ্ছেন

আপনি getState ব্যবহার করে নেভিগেশন প্রিলোডের অবস্থা দেখতে পারেন:

navigator.serviceWorker.ready.then(registration => {
  return registration.navigationPreload.getState();
}).then(state => {
  console.log(state.enabled); // boolean
  console.log(state.headerValue); // string
});

এই বৈশিষ্ট্যটিতে কাজ করার জন্য ম্যাট ফালকেনহেগেন এবং সুয়োশি হোরোকে অনেক ধন্যবাদ এবং এই নিবন্ধটিতে সহায়তা করুন। এবং প্রমিতকরণ প্রচেষ্টার সাথে জড়িত সবাইকে অনেক ধন্যবাদ