
সারাংশ
Google I/O 2015 ওয়েব অ্যাপকে দ্রুত এবং অফলাইন-প্রথম করতে আমরা কীভাবে পরিষেবা কর্মী লাইব্রেরি ব্যবহার করেছি তা জানুন।
ওভারভিউ
এই বছরের Google I/O 2015 ওয়েব অ্যাপটি Google-এর ডেভেলপার রিলেশনস টিম দ্বারা লেখা হয়েছে, যা আমাদের Instrument- এ বন্ধুদের ডিজাইনের উপর ভিত্তি করে, যারা নিফটি অডিও/ভিজ্যুয়াল পরীক্ষা লিখেছেন৷ আমাদের দলের লক্ষ্য ছিল নিশ্চিত করা যে I/O ওয়েব অ্যাপ (যাকে আমি এর কোডনাম, IOWA দ্বারা উল্লেখ করব) আধুনিক ওয়েব যা করতে পারে তার সবকিছু প্রদর্শন করে। একটি সম্পূর্ণ অফলাইন-প্রথম অভিজ্ঞতা আমাদের থাকা আবশ্যক বৈশিষ্ট্যগুলির তালিকার শীর্ষে ছিল৷
আপনি যদি সম্প্রতি এই সাইটের অন্য কোনো নিবন্ধ পড়ে থাকেন, তাহলে আপনি নিঃসন্দেহে পরিষেবা কর্মীদের সম্মুখীন হয়েছেন, এবং আপনি শুনে অবাক হবেন না যে IOWA-এর অফলাইন সমর্থন তাদের উপর অনেক বেশি নির্ভরশীল। IOWA-এর বাস্তব-বিশ্বের চাহিদার দ্বারা অনুপ্রাণিত হয়ে, আমরা দুটি ভিন্ন অফলাইন ব্যবহারের ক্ষেত্রে দুটি লাইব্রেরি তৈরি করেছি: স্ট্যাটিক রিসোর্সের প্রিক্যাচিং স্বয়ংক্রিয় করতে sw-precache
, এবং রানটাইম ক্যাশিং এবং ফলব্যাক কৌশলগুলি পরিচালনা করার জন্য sw-toolbox
৷
লাইব্রেরিগুলি একে অপরের সুন্দরভাবে পরিপূরক করে, এবং আমাদেরকে একটি কার্যকরী কৌশল প্রয়োগ করার অনুমতি দেয় যেখানে IOWA-এর স্ট্যাটিক বিষয়বস্তু "শেল" সর্বদা সরাসরি ক্যাশে থেকে পরিবেশন করা হয়, এবং প্রয়োজনের সময় ক্যাশে বা স্ট্যাটিক প্রতিক্রিয়াগুলিতে ফলব্যাক সহ নেটওয়ার্ক থেকে গতিশীল বা দূরবর্তী সংস্থানগুলি পরিবেশন করা হয়।
sw-precache
সঙ্গে precaching
IOWA-এর স্ট্যাটিক রিসোর্স-এর HTML, JavaScript, CSS এবং ছবিগুলি-ওয়েব অ্যাপ্লিকেশনের মূল শেল প্রদান করে। এই সংস্থানগুলি ক্যাশে করার বিষয়ে চিন্তা করার সময় দুটি নির্দিষ্ট প্রয়োজনীয়তা গুরুত্বপূর্ণ ছিল: আমরা নিশ্চিত করতে চেয়েছিলাম যে বেশিরভাগ স্ট্যাটিক সংস্থান ক্যাশে করা হয়েছে এবং সেগুলি আপ টু ডেট রাখা হয়েছে। sw-precache
সেই প্রয়োজনীয়তাগুলিকে মাথায় রেখে তৈরি করা হয়েছিল।
বিল্ড-টাইম ইন্টিগ্রেশন
IOWA-এর gulp
ভিত্তিক বিল্ড প্রক্রিয়ার সাথে sw-precache
, এবং আমরা IOWA ব্যবহার করা সমস্ত স্ট্যাটিক রিসোর্সগুলির একটি সম্পূর্ণ তালিকা তৈরি করা নিশ্চিত করতে গ্লোব প্যাটার্নের একটি সিরিজের উপর নির্ভর করি।
staticFileGlobs: [
rootDir + '/bower_components/**/*.{html,js,css}',
rootDir + '/elements/**',
rootDir + '/fonts/**',
rootDir + '/images/**',
rootDir + '/scripts/**',
rootDir + '/styles/**/*.css',
rootDir + '/data-worker-scripts.js'
]
বিকল্প পন্থা, যেমন একটি অ্যারেতে ফাইলের নামের তালিকাকে কঠিন কোডিং করা, এবং প্রতিবার সেই ফাইলগুলির যেকোনও পরিবর্তনের সময় একটি ক্যাশে সংস্করণ নম্বর বাম্প করার কথা মনে রাখা অনেক বেশি ত্রুটির প্রবণ ছিল, বিশেষ করে আমাদের একাধিক টিম সদস্য কোড চেক করার কারণে। ম্যানুয়ালি রক্ষণাবেক্ষণ করা অ্যারেতে একটি নতুন ফাইল রেখে কেউ অফলাইন সমর্থন ভাঙতে চায় না! বিল্ড-টাইম ইন্টিগ্রেশন মানে আমরা বিদ্যমান ফাইলগুলিতে পরিবর্তন করতে পারি এবং সেই উদ্বেগ ছাড়াই নতুন ফাইল যোগ করতে পারি।
ক্যাশড রিসোর্স আপডেট করা হচ্ছে
sw-precache
একটি বেস সার্ভিস ওয়ার্কার স্ক্রিপ্ট তৈরি করে যাতে প্রতিটি রিসোর্সের জন্য একটি অনন্য MD5 হ্যাশ থাকে যা প্রিক্যাচ করা হয়। প্রতিবার একটি বিদ্যমান সংস্থান পরিবর্তিত হয়, বা একটি নতুন সংস্থান যোগ করা হয়, পরিষেবা কর্মী স্ক্রিপ্টটি পুনরায় তৈরি করা হয়। এটি স্বয়ংক্রিয়ভাবে পরিষেবা কর্মী আপডেট ফ্লোকে ট্রিগার করে, যাতে নতুন সংস্থানগুলি ক্যাশে করা হয় এবং পুরানো সংস্থানগুলি পরিষ্কার করা হয়৷ অভিন্ন MD5 হ্যাশ আছে এমন যেকোন বিদ্যমান সংস্থান যেমন আছে তেমনই রেখে দেওয়া হয়। এর মানে হল যে ব্যবহারকারীরা সাইটটি পরিদর্শন করার আগে শুধুমাত্র পরিবর্তিত সংস্থানগুলির ন্যূনতম সেট ডাউনলোড করে, যার ফলে সমগ্র ক্যাশে একত্রে মেয়াদ শেষ হয়ে যাওয়ার চেয়ে অনেক বেশি দক্ষ অভিজ্ঞতার দিকে পরিচালিত করে৷
প্রতিটি ফাইল যা গ্লোব প্যাটার্নগুলির একটির সাথে মেলে তা ডাউনলোড করা হয় এবং প্রথমবার ব্যবহারকারী যখন IOWA পরিদর্শন করে তখন ক্যাশ করা হয়। আমরা নিশ্চিত করার জন্য একটি প্রচেষ্টা করেছি যে পৃষ্ঠাটি রেন্ডার করার জন্য শুধুমাত্র গুরুত্বপূর্ণ সংস্থানগুলিই প্রিক্যাচ করা হয়েছে৷ মাধ্যমিক বিষয়বস্তু, যেমন অডিও/ভিজ্যুয়াল পরীক্ষায় ব্যবহৃত মিডিয়া, অথবা সেশনের স্পিকারের প্রোফাইল চিত্রগুলি, ইচ্ছাকৃতভাবে প্রিক্যাচ করা হয়নি, এবং আমরা পরিবর্তে সেই সংস্থানগুলির জন্য অফলাইন অনুরোধগুলি পরিচালনা করতে sw-toolbox
লাইব্রেরি ব্যবহার করেছি৷
sw-toolbox
, আমাদের সমস্ত গতিশীল প্রয়োজনের জন্য
উল্লিখিত হিসাবে, একটি সাইটের অফলাইনে কাজ করার জন্য প্রয়োজন এমন প্রতিটি সংস্থান প্রিক্যাচ করা সম্ভব নয়৷ কিছু রিসোর্স অনেক বড় বা এটিকে সার্থক করতে কদাচিৎ ব্যবহার করা হয় এবং অন্যান্য রিসোর্স গতিশীল, যেমন দূরবর্তী API বা পরিষেবা থেকে পাওয়া প্রতিক্রিয়া। কিন্তু শুধুমাত্র একটি অনুরোধ প্রিক্যাচেড না হওয়ার মানে এই নয় যে এটি একটি NetworkError
এ পরিণত হবে। sw-toolbox
আমাদের অনুরোধ হ্যান্ডলার বাস্তবায়নের নমনীয়তা দিয়েছে যা কিছু সংস্থানের জন্য রানটাইম ক্যাশিং এবং অন্যদের জন্য কাস্টম ফলব্যাক পরিচালনা করে। আমরা পুশ বিজ্ঞপ্তির প্রতিক্রিয়া হিসাবে আমাদের পূর্বে ক্যাশে করা সংস্থানগুলি আপডেট করতেও এটি ব্যবহার করেছি৷
এখানে কাস্টম অনুরোধ হ্যান্ডলারের কয়েকটি উদাহরণ রয়েছে যা আমরা sw-toolbox এর উপরে তৈরি করেছি। sw-precache
এর importScripts parameter
মাধ্যমে বেস সার্ভিস ওয়ার্কার স্ক্রিপ্টের সাথে এগুলিকে একীভূত করা সহজ ছিল, যা পরিষেবা কর্মীর সুযোগে স্বতন্ত্র জাভাস্ক্রিপ্ট ফাইলগুলিকে টেনে আনে।
অডিও/ভিজ্যুয়াল পরীক্ষা
অডিও/ভিজ্যুয়াল পরীক্ষার জন্য, আমরা sw-toolbox
এর networkFirst
cache কৌশল ব্যবহার করেছি। পরীক্ষার জন্য URL প্যাটার্নের সাথে মিলে যাওয়া সমস্ত HTTP অনুরোধ প্রথমে নেটওয়ার্কের বিরুদ্ধে করা হবে, এবং যদি একটি সফল প্রতিক্রিয়া ফেরত দেওয়া হয়, সেই প্রতিক্রিয়াটি ক্যাশে স্টোরেজ API ব্যবহার করে লুকিয়ে রাখা হবে। নেটওয়ার্ক অনুপলব্ধ হলে পরবর্তী অনুরোধ করা হলে, পূর্বে ক্যাশ করা প্রতিক্রিয়া ব্যবহার করা হবে।
যেহেতু প্রতিবার একটি সফল নেটওয়ার্ক প্রতিক্রিয়া ফিরে আসার সময় ক্যাশে স্বয়ংক্রিয়ভাবে আপডেট হয়েছিল, তাই আমাদের নির্দিষ্টভাবে সংস্করণ সংস্থান বা মেয়াদ শেষ হওয়ার দরকার ছিল না।
toolbox.router.get('/experiment/(.+)', toolbox.networkFirst);
স্পিকার প্রোফাইল ইমেজ
স্পিকার প্রোফাইল ইমেজগুলির জন্য, আমাদের লক্ষ্য ছিল একটি প্রদত্ত স্পিকারের চিত্রের পূর্বে ক্যাশে করা সংস্করণ প্রদর্শন করা যদি এটি উপলব্ধ থাকে, যদি এটি না থাকে তবে ছবিটি পুনরুদ্ধার করতে নেটওয়ার্কে ফিরে আসা। যদি সেই নেটওয়ার্ক অনুরোধ ব্যর্থ হয়, চূড়ান্ত ফলব্যাক হিসাবে, আমরা একটি জেনেরিক প্লেসহোল্ডার ইমেজ ব্যবহার করেছি যা প্রিক্যাচ করা ছিল (এবং তাই সর্বদা উপলব্ধ থাকবে)। এটি একটি সাধারণ কৌশল যা চিত্রগুলির সাথে কাজ করার সময় ব্যবহার করা যায় যা একটি সাধারণ স্থানধারক দ্বারা প্রতিস্থাপিত হতে পারে এবং এটি sw-toolbox
এর cacheFirst
এবং cacheOnly
হ্যান্ডলারগুলিকে চেইন করে প্রয়োগ করা সহজ ছিল৷
var DEFAULT_PROFILE_IMAGE = 'images/touch/homescreen96.png';
function profileImageRequest(request) {
return toolbox.cacheFirst(request).catch(function() {
return toolbox.cacheOnly(new Request(DEFAULT_PROFILE_IMAGE));
});
}
toolbox.precache([DEFAULT_PROFILE_IMAGE]);
toolbox.router.get('/(.+)/images/speakers/(.*)',
profileImageRequest,
{origin: /.*\.googleapis\.com/});

ব্যবহারকারীদের সময়সূচী আপডেট
IOWA-এর অন্যতম প্রধান বৈশিষ্ট্য হল সাইন-ইন করা ব্যবহারকারীদের সেশনের একটি সময়সূচী তৈরি এবং বজায় রাখার অনুমতি দেওয়া যা তারা যোগ দেওয়ার পরিকল্পনা করেছিল। আপনি যেমনটি আশা করেছিলেন, সেশন আপডেটগুলি HTTP POST
অনুরোধের মাধ্যমে একটি ব্যাকএন্ড সার্ভারে করা হয়েছিল, এবং ব্যবহারকারী অফলাইনে থাকাকালীন সেই রাজ্য-সংশোধনের অনুরোধগুলি পরিচালনা করার জন্য আমরা কিছু সময় ব্যয় করেছি৷ আমরা IndexedDB-তে সারিবদ্ধ ব্যর্থ অনুরোধগুলির একটি সংমিশ্রণ নিয়ে এসেছি, মূল ওয়েব পৃষ্ঠায় যুক্তি সহ যা সারিবদ্ধ অনুরোধগুলির জন্য IndexedDB চেক করেছে এবং এটি যেটি পাওয়া গেছে তা পুনরায় চেষ্টা করেছে।
var DB_NAME = 'shed-offline-session-updates';
function queueFailedSessionUpdateRequest(request) {
simpleDB.open(DB_NAME).then(function(db) {
db.set(request.url, request.method);
});
}
function handleSessionUpdateRequest(request) {
return global.fetch(request).then(function(response) {
if (response.status >= 500) {
return Response.error();
}
return response;
}).catch(function() {
queueFailedSessionUpdateRequest(request);
});
}
toolbox.router.put('/(.+)api/v1/user/schedule/(.+)',
handleSessionUpdateRequest);
toolbox.router.delete('/(.+)api/v1/user/schedule/(.+)',
handleSessionUpdateRequest);
কারণ পুনঃপ্রচারগুলি মূল পৃষ্ঠার প্রসঙ্গ থেকে করা হয়েছিল, আমরা নিশ্চিত হতে পারি যে তারা ব্যবহারকারীর শংসাপত্রের একটি নতুন সেট অন্তর্ভুক্ত করেছে। একবার পুনঃপ্রচেষ্টা সফল হলে, আমরা ব্যবহারকারীকে জানাতে একটি বার্তা প্রদর্শন করেছি যে তাদের পূর্বে সারিবদ্ধ আপডেটগুলি প্রয়োগ করা হয়েছে৷
simpleDB.open(QUEUED_SESSION_UPDATES_DB_NAME).then(function(db) {
var replayPromises = [];
return db.forEach(function(url, method) {
var promise = IOWA.Request.xhrPromise(method, url, true).then(function() {
return db.delete(url).then(function() {
return true;
});
});
replayPromises.push(promise);
}).then(function() {
if (replayPromises.length) {
return Promise.all(replayPromises).then(function() {
IOWA.Elements.Toast.showMessage(
'My Schedule was updated with offline changes.');
});
}
});
}).catch(function() {
IOWA.Elements.Toast.showMessage(
'Offline changes could not be applied to My Schedule.');
});
অফলাইন Google Analytics
অনুরূপ শিরায়, আমরা একটি হ্যান্ডলার প্রয়োগ করেছি যেকোন ব্যর্থ Google Analytics অনুরোধগুলিকে সারিবদ্ধ করার জন্য এবং পরবর্তীতে সেগুলি পুনরায় চালানোর চেষ্টা করার জন্য, যখন নেটওয়ার্কটি আশা করা যায় উপলব্ধ ছিল। এই পদ্ধতির সাথে, অফলাইন থাকার অর্থ এই নয় যে Google অ্যানালিটিক্স অফার করা অন্তর্দৃষ্টিগুলিকে ত্যাগ করা। আমরা প্রতিটি সারিবদ্ধ অনুরোধে qt
প্যারামিটার যোগ করেছি, অনুরোধটি প্রথম চেষ্টা করার পর থেকে যে পরিমাণ সময় অতিবাহিত হয়েছে তার জন্য সেট করা হয়েছে, যাতে একটি সঠিক ইভেন্ট অ্যাট্রিবিউশন সময় এটি Google Analytics ব্যাকএন্ডে তৈরি করে। Google Analytics আনুষ্ঠানিকভাবে মাত্র 4 ঘন্টা পর্যন্ত qt
এর মান সমর্থন করে, তাই আমরা যত তাড়াতাড়ি সম্ভব সেই অনুরোধগুলি পুনরায় প্লে করার সর্বোত্তম প্রচেষ্টা করেছি, প্রতিবার পরিষেবা কর্মী শুরু করার সময়।
var DB_NAME = 'offline-analytics';
var EXPIRATION_TIME_DELTA = 86400000;
var ORIGIN = /https?:\/\/((www|ssl)\.)?google-analytics\.com/;
function replayQueuedAnalyticsRequests() {
simpleDB.open(DB_NAME).then(function(db) {
db.forEach(function(url, originalTimestamp) {
var timeDelta = Date.now() - originalTimestamp;
var replayUrl = url + '&qt=' + timeDelta;
fetch(replayUrl).then(function(response) {
if (response.status >= 500) {
return Response.error();
}
db.delete(url);
}).catch(function(error) {
if (timeDelta > EXPIRATION_TIME_DELTA) {
db.delete(url);
}
});
});
});
}
function queueFailedAnalyticsRequest(request) {
simpleDB.open(DB_NAME).then(function(db) {
db.set(request.url, Date.now());
});
}
function handleAnalyticsCollectionRequest(request) {
return global.fetch(request).then(function(response) {
if (response.status >= 500) {
return Response.error();
}
return response;
}).catch(function() {
queueFailedAnalyticsRequest(request);
});
}
toolbox.router.get('/collect',
handleAnalyticsCollectionRequest,
{origin: ORIGIN});
toolbox.router.get('/analytics.js',
toolbox.networkFirst,
{origin: ORIGIN});
replayQueuedAnalyticsRequests();
পুশ নোটিফিকেশন ল্যান্ডিং পেজ
পরিষেবা কর্মীরা শুধু IOWA-এর অফলাইন কার্যকারিতাই পরিচালনা করেননি—তারা পুশ বিজ্ঞপ্তিগুলিকেও চালিত করে যা আমরা ব্যবহারকারীদের তাদের বুকমার্ক করা সেশনের আপডেট সম্পর্কে অবহিত করতে ব্যবহার করি। সেই বিজ্ঞপ্তিগুলির সাথে যুক্ত ল্যান্ডিং পৃষ্ঠা আপডেট করা সেশনের বিবরণ প্রদর্শন করে৷ সেই ল্যান্ডিং পৃষ্ঠাগুলি ইতিমধ্যেই সামগ্রিক সাইটের অংশ হিসাবে ক্যাশে করা হয়েছে, তাই তারা ইতিমধ্যেই অফলাইনে কাজ করেছে, কিন্তু আমাদের নিশ্চিত করতে হবে যে সেই পৃষ্ঠায় সেশনের বিবরণ আপ টু ডেট ছিল, এমনকি অফলাইনে দেখা হলেও। এটি করার জন্য, আমরা পূর্বে ক্যাশে করা সেশনের মেটাডেটা পরিবর্তন করেছি যে আপডেটগুলি পুশ নোটিফিকেশনকে ট্রিগার করেছিল এবং আমরা ফলাফলটি ক্যাশে সংরক্ষণ করেছি। এই আপ-টু-ডেট তথ্যটি পরের বার সেশনের বিবরণ পৃষ্ঠা খোলার সময় ব্যবহার করা হবে, সেটা অনলাইনে হোক বা অফলাইনে হোক।
caches.open(toolbox.options.cacheName).then(function(cache) {
cache.match('api/v1/schedule').then(function(response) {
if (response) {
parseResponseJSON(response).then(function(schedule) {
sessions.forEach(function(session) {
schedule.sessions[session.id] = session;
});
cache.put('api/v1/schedule',
new Response(JSON.stringify(schedule)));
});
} else {
toolbox.cache('api/v1/schedule');
}
});
});
Gotchas এবং বিবেচনা
অবশ্যই, কেউ IOWA এর স্কেলের একটি প্রকল্পে কয়েকটি গোটচা ছাড়াই কাজ করে না। আমরা যেগুলির মধ্যে ছুটে গিয়েছিলাম এবং কীভাবে আমরা সেগুলিকে ঘিরে কাজ করেছি তা এখানে রয়েছে৷
বাসি বিষয়বস্তু
যখনই আপনি একটি ক্যাশিং কৌশল পরিকল্পনা করছেন, পরিষেবা কর্মীদের মাধ্যমে বা স্ট্যান্ডার্ড ব্রাউজার ক্যাশের মাধ্যমে প্রয়োগ করা হোক না কেন, যত তাড়াতাড়ি সম্ভব সম্পদ সরবরাহ করার বনাম নতুনতম সংস্থান সরবরাহ করার মধ্যে একটি ট্রেডঅফ রয়েছে। sw-precache
এর মাধ্যমে, আমরা আমাদের অ্যাপ্লিকেশনের শেলের জন্য একটি আক্রমণাত্মক ক্যাশে-প্রথম কৌশল প্রয়োগ করেছি, যার অর্থ আমাদের পরিষেবা কর্মী পৃষ্ঠায় HTML, JavaScript এবং CSS ফেরত দেওয়ার আগে আপডেটের জন্য নেটওয়ার্ক পরীক্ষা করবে না।
সৌভাগ্যবশত, পৃষ্ঠাটি ইতিমধ্যে লোড হওয়ার পরে নতুন সামগ্রী কখন উপলব্ধ ছিল তা সনাক্ত করতে আমরা পরিষেবা কর্মী লাইফসাইকেল ইভেন্টগুলির সুবিধা নিতে সক্ষম হয়েছি। যখন একটি আপডেট করা পরিষেবা কর্মী সনাক্ত করা হয়, আমরা ব্যবহারকারীকে একটি টোস্ট বার্তা প্রদর্শন করি যাতে তারা জানায় যে তাদের নতুন সামগ্রী দেখতে তাদের পৃষ্ঠাটি পুনরায় লোড করা উচিত।
if (navigator.serviceWorker && navigator.serviceWorker.controller) {
navigator.serviceWorker.controller.onstatechange = function(e) {
if (e.target.state === 'redundant') {
var tapHandler = function() {
window.location.reload();
};
IOWA.Elements.Toast.showMessage(
'Tap here or refresh the page for the latest content.',
tapHandler);
}
};
}

নিশ্চিত করুন স্ট্যাটিক বিষয়বস্তু স্ট্যাটিক!
sw-precache
স্থানীয় ফাইলের বিষয়বস্তুগুলির একটি MD5 হ্যাশ ব্যবহার করে এবং শুধুমাত্র সেই সংস্থানগুলি নিয়ে আসে যার হ্যাশ পরিবর্তিত হয়েছে। এর মানে হল যে সংস্থানগুলি প্রায় সঙ্গে সঙ্গেই পৃষ্ঠায় পাওয়া যায়, কিন্তু এর মানে এটাও যে একবার কিছু ক্যাশে করা হলে, আপডেট করা পরিষেবা কর্মী স্ক্রিপ্টে একটি নতুন হ্যাশ বরাদ্দ না করা পর্যন্ত এটি ক্যাশেই থাকবে।
কনফারেন্সের প্রতিটি দিনের জন্য আমাদের ব্যাকএন্ডকে গতিশীলভাবে লাইভস্ট্রিম YouTube ভিডিও আইডি আপডেট করার প্রয়োজনের কারণে আমরা I/O চলাকালীন এই আচরণের সাথে একটি সমস্যায় পড়েছিলাম । কারণ অন্তর্নিহিত টেমপ্লেট ফাইলটি স্থির ছিল এবং পরিবর্তিত হয়নি, আমাদের পরিষেবা কর্মী আপডেট ফ্লো ট্রিগার করা হয়নি, এবং YouTube ভিডিও আপডেট করার সাথে সার্ভার থেকে একটি গতিশীল প্রতিক্রিয়া বলতে যা বোঝানো হয়েছিল তা অনেক ব্যবহারকারীর জন্য ক্যাশে করা প্রতিক্রিয়া হিসাবে শেষ হয়েছে৷
আপনার ওয়েব অ্যাপ্লিকেশনটি সুগঠিত হয়েছে তা নিশ্চিত করে আপনি এই ধরণের সমস্যা এড়াতে পারেন যাতে শেলটি সর্বদা স্থির থাকে এবং নিরাপদে প্রিক্যাচ করা যায়, যখন শেলটি পরিবর্তন করে এমন যেকোনো গতিশীল সংস্থান স্বাধীনভাবে লোড হয়।
ক্যাশে-বাস্ট আপনার precaching অনুরোধ
যখন sw-precache
রিসোর্সগুলি precache করার জন্য অনুরোধ করে, তখন এটি সেই প্রতিক্রিয়াগুলিকে অনির্দিষ্টকালের জন্য ব্যবহার করে যতক্ষণ না এটি মনে করে যে ফাইলের জন্য MD5 হ্যাশ পরিবর্তন হয়নি। এর মানে হল যে প্রিক্যাচিং অনুরোধের প্রতিক্রিয়া একটি নতুন এবং ব্রাউজারের HTTP ক্যাশে থেকে ফিরে আসে না তা নিশ্চিত করা বিশেষভাবে গুরুত্বপূর্ণ৷ ( fetch()
, একটি পরিষেবা কর্মী দ্বারা করা অনুরোধগুলি ব্রাউজারের HTTP ক্যাশে থেকে ডেটার সাথে প্রতিক্রিয়া জানাতে পারে৷)
আমরা যে প্রতিক্রিয়াগুলি precache করি তা সরাসরি নেটওয়ার্ক থেকে এবং ব্রাউজারের HTTP ক্যাশে নয় তা নিশ্চিত করার জন্য, sw-precache
স্বয়ংক্রিয়ভাবে প্রতিটি ইউআরএলে একটি ক্যাশে-বাস্টিং ক্যোয়ারী প্যারামিটার যোগ করে যা এটি অনুরোধ করে। আপনি যদি sw-precache
ব্যবহার না করেন এবং আপনি একটি ক্যাশে-প্রথম প্রতিক্রিয়া কৌশল ব্যবহার করছেন, তবে নিশ্চিত করুন যে আপনি নিজের কোডে অনুরূপ কিছু করছেন !
ক্যাশে-বাস্টিংয়ের একটি পরিষ্কার সমাধান হল reload
জন্য প্রিক্যাচিংয়ের জন্য ব্যবহৃত প্রতিটি Request
ক্যাশে মোড সেট করা, যা নিশ্চিত করবে যে প্রতিক্রিয়া নেটওয়ার্ক থেকে আসবে। যাইহোক, এই লেখা পর্যন্ত, ক্যাশে মোড বিকল্পটি Chrome-এ সমর্থিত নয় ।
লগ ইন এবং আউট জন্য সমর্থন
IOWA ব্যবহারকারীদের তাদের Google অ্যাকাউন্ট ব্যবহার করে লগ ইন করার এবং তাদের কাস্টমাইজড ইভেন্টের সময়সূচী আপডেট করার অনুমতি দিয়েছে, কিন্তু এর মানে হল যে ব্যবহারকারীরা পরে লগ আউট করতে পারে। ব্যক্তিগতকৃত প্রতিক্রিয়া ডেটা ক্যাশ করা স্পষ্টতই একটি জটিল বিষয় এবং সর্বদা একটি একক সঠিক পদ্ধতি নেই।
যেহেতু আপনার ব্যক্তিগত সময়সূচী দেখা, এমনকি অফলাইনে থাকাকালীনও, IOWA অভিজ্ঞতার মূল বিষয় ছিল, তাই আমরা সিদ্ধান্ত নিয়েছি যে ক্যাশে করা ডেটা ব্যবহার করা উপযুক্ত। যখন একজন ব্যবহারকারী সাইন আউট করেন, আমরা পূর্বে ক্যাশে করা সেশন ডেটা সাফ করার বিষয়টি নিশ্চিত করেছিলাম।
self.addEventListener('message', function(event) {
if (event.data === 'clear-cached-user-data') {
caches.open(toolbox.options.cacheName).then(function(cache) {
cache.keys().then(function(requests) {
return requests.filter(function(request) {
return request.url.indexOf('api/v1/user/') !== -1;
});
}).then(function(userDataRequests) {
userDataRequests.forEach(function(userDataRequest) {
cache.delete(userDataRequest);
});
});
});
}
});
অতিরিক্ত ক্যোয়ারী পরামিতি জন্য দেখুন!
যখন কোনও পরিষেবা কর্মী একটি ক্যাশে করা প্রতিক্রিয়া পরীক্ষা করে, তখন এটি কী হিসাবে একটি অনুরোধ URL ব্যবহার করে। ডিফল্টরূপে, অনুরোধের URLটি অবশ্যই URL-এর অনুসন্ধান অংশে যেকোন ক্যোয়ারী প্যারামিটার সহ ক্যাশে করা প্রতিক্রিয়া সঞ্চয় করতে ব্যবহৃত URL-এর সাথে হুবহু মিলতে হবে৷
আমাদের ট্র্যাফিক কোথা থেকে আসছে তা ট্র্যাক করার জন্য যখন আমরা URL প্যারামিটার ব্যবহার করা শুরু করি তখন এটি বিকাশের সময় আমাদের জন্য একটি সমস্যা সৃষ্টি করে। উদাহরণ স্বরূপ, আমরা utm_source=notification
প্যারামিটার যুক্ত করেছিলাম URL-এ যা খোলা হয়েছিল আমাদের একটি বিজ্ঞপ্তিতে ক্লিক করার সময়, এবং utm_source=web_app_manifest
ব্যবহার করেছি আমাদের ওয়েব অ্যাপ ম্যানিফেস্টের জন্য start_url
এ। পূর্বে ক্যাশ করা প্রতিক্রিয়াগুলির সাথে মিলে যাওয়া URLগুলি যখন সেই প্যারামিটারগুলি যুক্ত করা হয়েছিল তখন মিস হিসাবে উঠে আসছে৷
এটি আংশিকভাবে ignoreSearch
বিকল্প দ্বারা সম্বোধন করা হয়েছে যা Cache.match()
কল করার সময় ব্যবহার করা যেতে পারে। দুর্ভাগ্যবশত, Chrome এখনও ignoreSearch
সমর্থন করে না , এবং এমনকি যদি এটি করেও, এটি একটি সব-বা-কিছুই নয়। আমাদের যা দরকার ছিল তা হল কিছু ইউআরএল ক্যোয়ারী প্যারামিটার উপেক্ষা করার একটি উপায় যা অর্থপূর্ণ ছিল।
আমরা একটি ক্যাশে ম্যাচের জন্য চেক করার আগে কিছু ক্যোয়ারী প্যারামিটার বের করার জন্য sw-precache
প্রসারিত করেছি এবং ignoreUrlParametersMatching
বিকল্পের মাধ্যমে কোন প্যারামিটারগুলি উপেক্ষা করা হয়েছে তা ডেভেলপারদের কাস্টমাইজ করার অনুমতি দেয়। এখানে অন্তর্নিহিত বাস্তবায়ন আছে:
function stripIgnoredUrlParameters(originalUrl, ignoredRegexes) {
var url = new URL(originalUrl);
url.search = url.search.slice(1)
.split('&')
.map(function(kv) {
return kv.split('=');
})
.filter(function(kv) {
return ignoredRegexes.every(function(ignoredRegex) {
return !ignoredRegex.test(kv[0]);
});
})
.map(function(kv) {
return kv.join('=');
})
.join('&');
return url.toString();
}
হোয়াট দিস মিন্স ফর ইউ
Google I/O ওয়েব অ্যাপে পরিষেবা কর্মী সংহতকরণ সম্ভবত সবচেয়ে জটিল, বাস্তব-বিশ্বের ব্যবহার যা এই সময়ে স্থাপন করা হয়েছে। আমরা sw-precache
এবং sw-toolbox
তৈরি করা টুলগুলি ব্যবহার করে ওয়েব ডেভেলপার সম্প্রদায়ের সাথে সাথে আপনার নিজস্ব ওয়েব অ্যাপ্লিকেশনগুলিকে শক্তি দেওয়ার জন্য আমরা যে কৌশলগুলি বর্ণনা করছি তার জন্য আমরা অপেক্ষা করছি৷ পরিষেবা কর্মীরা একটি প্রগতিশীল বর্ধন যা আপনি আজ ব্যবহার শুরু করতে পারেন, এবং যখন একটি সঠিকভাবে কাঠামোগত ওয়েব অ্যাপের অংশ হিসাবে ব্যবহার করা হয়, তখন গতি এবং অফলাইন সুবিধাগুলি আপনার ব্যবহারকারীদের জন্য উল্লেখযোগ্য।

সারাংশ
Google I/O 2015 ওয়েব অ্যাপকে দ্রুত এবং অফলাইন-প্রথম করতে আমরা কীভাবে পরিষেবা কর্মী লাইব্রেরি ব্যবহার করেছি তা জানুন।
ওভারভিউ
এই বছরের Google I/O 2015 ওয়েব অ্যাপটি Google-এর ডেভেলপার রিলেশনস টিম দ্বারা লেখা হয়েছে, যা আমাদের Instrument- এ বন্ধুদের ডিজাইনের উপর ভিত্তি করে, যারা নিফটি অডিও/ভিজ্যুয়াল পরীক্ষা লিখেছেন৷ আমাদের দলের লক্ষ্য ছিল নিশ্চিত করা যে I/O ওয়েব অ্যাপ (যাকে আমি এর কোডনাম, IOWA দ্বারা উল্লেখ করব) আধুনিক ওয়েব যা করতে পারে তার সবকিছু প্রদর্শন করে। একটি সম্পূর্ণ অফলাইন-প্রথম অভিজ্ঞতা আমাদের থাকা আবশ্যক বৈশিষ্ট্যগুলির তালিকার শীর্ষে ছিল৷
আপনি যদি সম্প্রতি এই সাইটের অন্য কোনো নিবন্ধ পড়ে থাকেন, তাহলে আপনি নিঃসন্দেহে পরিষেবা কর্মীদের সম্মুখীন হয়েছেন, এবং আপনি শুনে অবাক হবেন না যে IOWA-এর অফলাইন সমর্থন তাদের উপর অনেক বেশি নির্ভরশীল। IOWA-এর বাস্তব-বিশ্বের চাহিদার দ্বারা অনুপ্রাণিত হয়ে, আমরা দুটি ভিন্ন অফলাইন ব্যবহারের ক্ষেত্রে দুটি লাইব্রেরি তৈরি করেছি: স্ট্যাটিক রিসোর্সের প্রিক্যাচিং স্বয়ংক্রিয় করতে sw-precache
, এবং রানটাইম ক্যাশিং এবং ফলব্যাক কৌশলগুলি পরিচালনা করার জন্য sw-toolbox
৷
লাইব্রেরিগুলি একে অপরের সুন্দরভাবে পরিপূরক করে, এবং আমাদেরকে একটি কার্যকরী কৌশল প্রয়োগ করার অনুমতি দেয় যেখানে IOWA-এর স্ট্যাটিক বিষয়বস্তু "শেল" সর্বদা সরাসরি ক্যাশে থেকে পরিবেশন করা হয়, এবং প্রয়োজনের সময় ক্যাশে বা স্ট্যাটিক প্রতিক্রিয়াগুলিতে ফলব্যাক সহ নেটওয়ার্ক থেকে গতিশীল বা দূরবর্তী সংস্থানগুলি পরিবেশন করা হয়।
sw-precache
সঙ্গে precaching
IOWA-এর স্ট্যাটিক রিসোর্স-এর HTML, JavaScript, CSS এবং ছবিগুলি-ওয়েব অ্যাপ্লিকেশনের মূল শেল প্রদান করে। এই সংস্থানগুলি ক্যাশে করার বিষয়ে চিন্তা করার সময় দুটি নির্দিষ্ট প্রয়োজনীয়তা গুরুত্বপূর্ণ ছিল: আমরা নিশ্চিত করতে চেয়েছিলাম যে বেশিরভাগ স্ট্যাটিক সংস্থান ক্যাশে করা হয়েছে এবং সেগুলি আপ টু ডেট রাখা হয়েছে। sw-precache
সেই প্রয়োজনীয়তাগুলিকে মাথায় রেখে তৈরি করা হয়েছিল।
বিল্ড-টাইম ইন্টিগ্রেশন
IOWA-এর gulp
ভিত্তিক বিল্ড প্রক্রিয়ার সাথে sw-precache
, এবং আমরা IOWA ব্যবহার করা সমস্ত স্ট্যাটিক রিসোর্সগুলির একটি সম্পূর্ণ তালিকা তৈরি করা নিশ্চিত করতে গ্লোব প্যাটার্নের একটি সিরিজের উপর নির্ভর করি।
staticFileGlobs: [
rootDir + '/bower_components/**/*.{html,js,css}',
rootDir + '/elements/**',
rootDir + '/fonts/**',
rootDir + '/images/**',
rootDir + '/scripts/**',
rootDir + '/styles/**/*.css',
rootDir + '/data-worker-scripts.js'
]
বিকল্প পন্থা, যেমন একটি অ্যারেতে ফাইলের নামের তালিকাকে কঠিন কোডিং করা, এবং প্রতিবার সেই ফাইলগুলির যেকোনও পরিবর্তনের সময় একটি ক্যাশে সংস্করণ নম্বর বাম্প করার কথা মনে রাখা অনেক বেশি ত্রুটির প্রবণ ছিল, বিশেষ করে আমাদের একাধিক টিম সদস্য কোড চেক করার কারণে। ম্যানুয়ালি রক্ষণাবেক্ষণ করা অ্যারেতে একটি নতুন ফাইল রেখে কেউ অফলাইন সমর্থন ভাঙতে চায় না! বিল্ড-টাইম ইন্টিগ্রেশন মানে আমরা বিদ্যমান ফাইলগুলিতে পরিবর্তন করতে পারি এবং সেই উদ্বেগ ছাড়াই নতুন ফাইল যোগ করতে পারি।
ক্যাশড রিসোর্স আপডেট করা হচ্ছে
sw-precache
একটি বেস সার্ভিস ওয়ার্কার স্ক্রিপ্ট তৈরি করে যাতে প্রতিটি রিসোর্সের জন্য একটি অনন্য MD5 হ্যাশ থাকে যা প্রিক্যাচ করা হয়। প্রতিবার একটি বিদ্যমান সংস্থান পরিবর্তিত হয়, বা একটি নতুন সংস্থান যোগ করা হয়, পরিষেবা কর্মী স্ক্রিপ্টটি পুনরায় তৈরি করা হয়। এটি স্বয়ংক্রিয়ভাবে পরিষেবা কর্মী আপডেট ফ্লোকে ট্রিগার করে, যাতে নতুন সংস্থানগুলি ক্যাশে করা হয় এবং পুরানো সংস্থানগুলি পরিষ্কার করা হয়৷ অভিন্ন MD5 হ্যাশ আছে এমন যেকোন বিদ্যমান সংস্থান যেমন আছে তেমনই রেখে দেওয়া হয়। এর মানে হল যে ব্যবহারকারীরা সাইটটি পরিদর্শন করার আগে শুধুমাত্র পরিবর্তিত সংস্থানগুলির ন্যূনতম সেট ডাউনলোড করে, যার ফলে সমগ্র ক্যাশে একত্রে মেয়াদ শেষ হয়ে যাওয়ার চেয়ে অনেক বেশি দক্ষ অভিজ্ঞতার দিকে পরিচালিত করে৷
প্রতিটি ফাইল যা গ্লোব প্যাটার্নগুলির একটির সাথে মেলে তা ডাউনলোড করা হয় এবং প্রথমবার ব্যবহারকারী যখন IOWA পরিদর্শন করে তখন ক্যাশ করা হয়। আমরা নিশ্চিত করার জন্য একটি প্রচেষ্টা করেছি যে পৃষ্ঠাটি রেন্ডার করার জন্য শুধুমাত্র গুরুত্বপূর্ণ সংস্থানগুলিই প্রিক্যাচ করা হয়েছে৷ মাধ্যমিক বিষয়বস্তু, যেমন অডিও/ভিজ্যুয়াল পরীক্ষায় ব্যবহৃত মিডিয়া, অথবা সেশনের স্পিকারের প্রোফাইল চিত্রগুলি, ইচ্ছাকৃতভাবে প্রিক্যাচ করা হয়নি, এবং আমরা পরিবর্তে সেই সংস্থানগুলির জন্য অফলাইন অনুরোধগুলি পরিচালনা করতে sw-toolbox
লাইব্রেরি ব্যবহার করেছি৷
sw-toolbox
, আমাদের সমস্ত গতিশীল প্রয়োজনের জন্য
উল্লিখিত হিসাবে, একটি সাইটের অফলাইনে কাজ করার জন্য প্রয়োজন এমন প্রতিটি সংস্থান প্রিক্যাচ করা সম্ভব নয়৷ কিছু রিসোর্স অনেক বড় বা এটিকে সার্থক করতে কদাচিৎ ব্যবহার করা হয় এবং অন্যান্য রিসোর্স গতিশীল, যেমন দূরবর্তী API বা পরিষেবা থেকে পাওয়া প্রতিক্রিয়া। কিন্তু শুধুমাত্র একটি অনুরোধ প্রিক্যাচেড না হওয়ার মানে এই নয় যে এটি একটি NetworkError
এ পরিণত হবে। sw-toolbox
আমাদের অনুরোধ হ্যান্ডলার বাস্তবায়নের নমনীয়তা দিয়েছে যা কিছু সংস্থানের জন্য রানটাইম ক্যাশিং এবং অন্যদের জন্য কাস্টম ফলব্যাক পরিচালনা করে। আমরা পুশ বিজ্ঞপ্তির প্রতিক্রিয়া হিসাবে আমাদের পূর্বে ক্যাশে করা সংস্থানগুলি আপডেট করতেও এটি ব্যবহার করেছি৷
এখানে কাস্টম অনুরোধ হ্যান্ডলারের কয়েকটি উদাহরণ রয়েছে যা আমরা sw-toolbox এর উপরে তৈরি করেছি। sw-precache
এর importScripts parameter
মাধ্যমে বেস সার্ভিস ওয়ার্কার স্ক্রিপ্টের সাথে এগুলিকে একীভূত করা সহজ ছিল, যা পরিষেবা কর্মীর সুযোগে স্বতন্ত্র জাভাস্ক্রিপ্ট ফাইলগুলিকে টেনে আনে।
অডিও/ভিজ্যুয়াল পরীক্ষা
অডিও/ভিজ্যুয়াল পরীক্ষার জন্য, আমরা sw-toolbox
এর networkFirst
cache কৌশল ব্যবহার করেছি। পরীক্ষার জন্য URL প্যাটার্নের সাথে মিলে যাওয়া সমস্ত HTTP অনুরোধ প্রথমে নেটওয়ার্কের বিরুদ্ধে করা হবে, এবং যদি একটি সফল প্রতিক্রিয়া ফেরত দেওয়া হয়, সেই প্রতিক্রিয়াটি ক্যাশে স্টোরেজ API ব্যবহার করে লুকিয়ে রাখা হবে। নেটওয়ার্ক অনুপলব্ধ হলে পরবর্তী অনুরোধ করা হলে, পূর্বে ক্যাশ করা প্রতিক্রিয়া ব্যবহার করা হবে।
যেহেতু প্রতিবার একটি সফল নেটওয়ার্ক প্রতিক্রিয়া ফিরে আসার সময় ক্যাশে স্বয়ংক্রিয়ভাবে আপডেট হয়েছিল, তাই আমাদের নির্দিষ্টভাবে সংস্করণ সংস্থান বা মেয়াদ শেষ হওয়ার দরকার ছিল না।
toolbox.router.get('/experiment/(.+)', toolbox.networkFirst);
স্পিকার প্রোফাইল ইমেজ
স্পিকার প্রোফাইল ইমেজগুলির জন্য, আমাদের লক্ষ্য ছিল একটি প্রদত্ত স্পিকারের চিত্রের পূর্বে ক্যাশে করা সংস্করণ প্রদর্শন করা যদি এটি উপলব্ধ থাকে, যদি এটি না থাকে তবে ছবিটি পুনরুদ্ধার করতে নেটওয়ার্কে ফিরে আসা। যদি সেই নেটওয়ার্ক অনুরোধ ব্যর্থ হয়, চূড়ান্ত ফলব্যাক হিসাবে, আমরা একটি জেনেরিক প্লেসহোল্ডার ইমেজ ব্যবহার করেছি যা প্রিক্যাচ করা ছিল (এবং তাই সর্বদা উপলব্ধ থাকবে)। এটি একটি সাধারণ কৌশল যা চিত্রগুলির সাথে কাজ করার সময় ব্যবহার করা যায় যা একটি সাধারণ স্থানধারক দ্বারা প্রতিস্থাপিত হতে পারে এবং এটি sw-toolbox
এর cacheFirst
এবং cacheOnly
হ্যান্ডলারগুলিকে চেইন করে প্রয়োগ করা সহজ ছিল৷
var DEFAULT_PROFILE_IMAGE = 'images/touch/homescreen96.png';
function profileImageRequest(request) {
return toolbox.cacheFirst(request).catch(function() {
return toolbox.cacheOnly(new Request(DEFAULT_PROFILE_IMAGE));
});
}
toolbox.precache([DEFAULT_PROFILE_IMAGE]);
toolbox.router.get('/(.+)/images/speakers/(.*)',
profileImageRequest,
{origin: /.*\.googleapis\.com/});

ব্যবহারকারীদের সময়সূচী আপডেট
IOWA-এর অন্যতম প্রধান বৈশিষ্ট্য হল সাইন-ইন করা ব্যবহারকারীদের সেশনের একটি সময়সূচী তৈরি এবং বজায় রাখার অনুমতি দেওয়া যা তারা যোগ দেওয়ার পরিকল্পনা করেছিল। আপনি যেমনটি আশা করেছিলেন, সেশন আপডেটগুলি HTTP POST
অনুরোধের মাধ্যমে একটি ব্যাকএন্ড সার্ভারে করা হয়েছিল, এবং ব্যবহারকারী অফলাইনে থাকাকালীন সেই রাজ্য-সংশোধনের অনুরোধগুলি পরিচালনা করার জন্য আমরা কিছু সময় ব্যয় করেছি৷ আমরা IndexedDB-তে সারিবদ্ধ ব্যর্থ অনুরোধগুলির একটি সংমিশ্রণ নিয়ে এসেছি, মূল ওয়েব পৃষ্ঠায় যুক্তি সহ যা সারিবদ্ধ অনুরোধগুলির জন্য IndexedDB চেক করেছে এবং এটি যেটি পাওয়া গেছে তা পুনরায় চেষ্টা করেছে।
var DB_NAME = 'shed-offline-session-updates';
function queueFailedSessionUpdateRequest(request) {
simpleDB.open(DB_NAME).then(function(db) {
db.set(request.url, request.method);
});
}
function handleSessionUpdateRequest(request) {
return global.fetch(request).then(function(response) {
if (response.status >= 500) {
return Response.error();
}
return response;
}).catch(function() {
queueFailedSessionUpdateRequest(request);
});
}
toolbox.router.put('/(.+)api/v1/user/schedule/(.+)',
handleSessionUpdateRequest);
toolbox.router.delete('/(.+)api/v1/user/schedule/(.+)',
handleSessionUpdateRequest);
কারণ পুনঃপ্রচারগুলি মূল পৃষ্ঠার প্রসঙ্গ থেকে করা হয়েছিল, আমরা নিশ্চিত হতে পারি যে তারা ব্যবহারকারীর শংসাপত্রের একটি নতুন সেট অন্তর্ভুক্ত করেছে। একবার পুনঃপ্রচেষ্টা সফল হলে, আমরা ব্যবহারকারীকে জানাতে একটি বার্তা প্রদর্শন করেছি যে তাদের পূর্বে সারিবদ্ধ আপডেটগুলি প্রয়োগ করা হয়েছে৷
simpleDB.open(QUEUED_SESSION_UPDATES_DB_NAME).then(function(db) {
var replayPromises = [];
return db.forEach(function(url, method) {
var promise = IOWA.Request.xhrPromise(method, url, true).then(function() {
return db.delete(url).then(function() {
return true;
});
});
replayPromises.push(promise);
}).then(function() {
if (replayPromises.length) {
return Promise.all(replayPromises).then(function() {
IOWA.Elements.Toast.showMessage(
'My Schedule was updated with offline changes.');
});
}
});
}).catch(function() {
IOWA.Elements.Toast.showMessage(
'Offline changes could not be applied to My Schedule.');
});
অফলাইন Google Analytics
অনুরূপ শিরায়, আমরা একটি হ্যান্ডলার প্রয়োগ করেছি যেকোন ব্যর্থ Google Analytics অনুরোধগুলিকে সারিবদ্ধ করার জন্য এবং পরবর্তীতে সেগুলি পুনরায় চালানোর চেষ্টা করার জন্য, যখন নেটওয়ার্কটি আশা করা যায় উপলব্ধ ছিল। এই পদ্ধতির সাথে, অফলাইন থাকার অর্থ এই নয় যে Google অ্যানালিটিক্স অফার করা অন্তর্দৃষ্টিগুলিকে ত্যাগ করা। আমরা প্রতিটি সারিবদ্ধ অনুরোধে qt
প্যারামিটার যোগ করেছি, অনুরোধটি প্রথম চেষ্টা করার পর থেকে যে পরিমাণ সময় অতিবাহিত হয়েছে তার জন্য সেট করা হয়েছে, যাতে একটি সঠিক ইভেন্ট অ্যাট্রিবিউশন সময় এটি Google Analytics ব্যাকএন্ডে তৈরি করে। Google Analytics আনুষ্ঠানিকভাবে মাত্র 4 ঘন্টা পর্যন্ত qt
এর মান সমর্থন করে, তাই আমরা যত তাড়াতাড়ি সম্ভব সেই অনুরোধগুলি পুনরায় প্লে করার সর্বোত্তম প্রচেষ্টা করেছি, প্রতিবার পরিষেবা কর্মী শুরু করার সময়।
var DB_NAME = 'offline-analytics';
var EXPIRATION_TIME_DELTA = 86400000;
var ORIGIN = /https?:\/\/((www|ssl)\.)?google-analytics\.com/;
function replayQueuedAnalyticsRequests() {
simpleDB.open(DB_NAME).then(function(db) {
db.forEach(function(url, originalTimestamp) {
var timeDelta = Date.now() - originalTimestamp;
var replayUrl = url + '&qt=' + timeDelta;
fetch(replayUrl).then(function(response) {
if (response.status >= 500) {
return Response.error();
}
db.delete(url);
}).catch(function(error) {
if (timeDelta > EXPIRATION_TIME_DELTA) {
db.delete(url);
}
});
});
});
}
function queueFailedAnalyticsRequest(request) {
simpleDB.open(DB_NAME).then(function(db) {
db.set(request.url, Date.now());
});
}
function handleAnalyticsCollectionRequest(request) {
return global.fetch(request).then(function(response) {
if (response.status >= 500) {
return Response.error();
}
return response;
}).catch(function() {
queueFailedAnalyticsRequest(request);
});
}
toolbox.router.get('/collect',
handleAnalyticsCollectionRequest,
{origin: ORIGIN});
toolbox.router.get('/analytics.js',
toolbox.networkFirst,
{origin: ORIGIN});
replayQueuedAnalyticsRequests();
পুশ নোটিফিকেশন ল্যান্ডিং পেজ
পরিষেবা কর্মীরা শুধু IOWA-এর অফলাইন কার্যকারিতাই পরিচালনা করেননি—তারা পুশ বিজ্ঞপ্তিগুলিকেও চালিত করে যা আমরা ব্যবহারকারীদের তাদের বুকমার্ক করা সেশনের আপডেট সম্পর্কে অবহিত করতে ব্যবহার করি। সেই বিজ্ঞপ্তিগুলির সাথে যুক্ত ল্যান্ডিং পৃষ্ঠা আপডেট করা সেশনের বিবরণ প্রদর্শন করে৷ সেই ল্যান্ডিং পৃষ্ঠাগুলি ইতিমধ্যেই সামগ্রিক সাইটের অংশ হিসাবে ক্যাশে করা হয়েছে, তাই তারা ইতিমধ্যেই অফলাইনে কাজ করেছে, কিন্তু আমাদের নিশ্চিত করতে হবে যে সেই পৃষ্ঠায় সেশনের বিবরণ আপ টু ডেট ছিল, এমনকি অফলাইনে দেখা হলেও। এটি করার জন্য, আমরা পূর্বে ক্যাশে করা সেশনের মেটাডেটা পরিবর্তন করেছি যে আপডেটগুলি পুশ নোটিফিকেশনকে ট্রিগার করেছিল এবং আমরা ফলাফলটি ক্যাশে সংরক্ষণ করেছি। এই আপ-টু-ডেট তথ্যটি পরের বার সেশনের বিবরণ পৃষ্ঠা খোলার সময় ব্যবহার করা হবে, সেটা অনলাইনে হোক বা অফলাইনে হোক।
caches.open(toolbox.options.cacheName).then(function(cache) {
cache.match('api/v1/schedule').then(function(response) {
if (response) {
parseResponseJSON(response).then(function(schedule) {
sessions.forEach(function(session) {
schedule.sessions[session.id] = session;
});
cache.put('api/v1/schedule',
new Response(JSON.stringify(schedule)));
});
} else {
toolbox.cache('api/v1/schedule');
}
});
});
Gotchas এবং বিবেচনা
অবশ্যই, কেউ IOWA এর স্কেলের একটি প্রকল্পে কয়েকটি গোটচা ছাড়াই কাজ করে না। আমরা যেগুলির মধ্যে ছুটে গিয়েছিলাম এবং কীভাবে আমরা সেগুলিকে ঘিরে কাজ করেছি তা এখানে রয়েছে৷
বাসি বিষয়বস্তু
যখনই আপনি একটি ক্যাশিং কৌশল পরিকল্পনা করছেন, পরিষেবা কর্মীদের মাধ্যমে বা স্ট্যান্ডার্ড ব্রাউজার ক্যাশের মাধ্যমে প্রয়োগ করা হোক না কেন, যত তাড়াতাড়ি সম্ভব সম্পদ সরবরাহ করার বনাম নতুনতম সংস্থান সরবরাহ করার মধ্যে একটি ট্রেডঅফ রয়েছে। sw-precache
এর মাধ্যমে, আমরা আমাদের অ্যাপ্লিকেশনের শেলের জন্য একটি আক্রমণাত্মক ক্যাশে-প্রথম কৌশল প্রয়োগ করেছি, যার অর্থ আমাদের পরিষেবা কর্মী পৃষ্ঠায় HTML, JavaScript এবং CSS ফেরত দেওয়ার আগে আপডেটের জন্য নেটওয়ার্ক পরীক্ষা করবে না।
সৌভাগ্যবশত, পৃষ্ঠাটি ইতিমধ্যে লোড হওয়ার পরে নতুন সামগ্রী কখন উপলব্ধ ছিল তা সনাক্ত করতে আমরা পরিষেবা কর্মী লাইফসাইকেল ইভেন্টগুলির সুবিধা নিতে সক্ষম হয়েছি। যখন একটি আপডেট করা পরিষেবা কর্মী সনাক্ত করা হয়, আমরা ব্যবহারকারীকে একটি টোস্ট বার্তা প্রদর্শন করি যাতে তারা জানায় যে তাদের নতুন সামগ্রী দেখতে তাদের পৃষ্ঠাটি পুনরায় লোড করা উচিত।
if (navigator.serviceWorker && navigator.serviceWorker.controller) {
navigator.serviceWorker.controller.onstatechange = function(e) {
if (e.target.state === 'redundant') {
var tapHandler = function() {
window.location.reload();
};
IOWA.Elements.Toast.showMessage(
'Tap here or refresh the page for the latest content.',
tapHandler);
}
};
}

নিশ্চিত করুন স্ট্যাটিক বিষয়বস্তু স্ট্যাটিক!
sw-precache
স্থানীয় ফাইলের বিষয়বস্তুগুলির একটি MD5 হ্যাশ ব্যবহার করে এবং শুধুমাত্র সেই সংস্থানগুলি নিয়ে আসে যার হ্যাশ পরিবর্তিত হয়েছে। এর মানে হল যে সংস্থানগুলি প্রায় সঙ্গে সঙ্গেই পৃষ্ঠায় পাওয়া যায়, কিন্তু এর মানে এটাও যে একবার কিছু ক্যাশে করা হলে, আপডেট করা পরিষেবা কর্মী স্ক্রিপ্টে একটি নতুন হ্যাশ বরাদ্দ না করা পর্যন্ত এটি ক্যাশেই থাকবে।
কনফারেন্সের প্রতিটি দিনের জন্য আমাদের ব্যাকএন্ডকে গতিশীলভাবে লাইভস্ট্রিম YouTube ভিডিও আইডি আপডেট করার প্রয়োজনের কারণে আমরা I/O চলাকালীন এই আচরণের সাথে একটি সমস্যায় পড়েছিলাম । কারণ অন্তর্নিহিত টেমপ্লেট ফাইলটি স্থির ছিল এবং পরিবর্তিত হয়নি, আমাদের পরিষেবা কর্মী আপডেট ফ্লো ট্রিগার করা হয়নি, এবং YouTube ভিডিও আপডেট করার সাথে সার্ভার থেকে একটি গতিশীল প্রতিক্রিয়া বলতে যা বোঝানো হয়েছিল তা অনেক ব্যবহারকারীর জন্য ক্যাশে করা প্রতিক্রিয়া হিসাবে শেষ হয়েছে৷
আপনার ওয়েব অ্যাপ্লিকেশনটি সুগঠিত হয়েছে তা নিশ্চিত করে আপনি এই ধরণের সমস্যা এড়াতে পারেন যাতে শেলটি সর্বদা স্থির থাকে এবং নিরাপদে প্রিক্যাচ করা যায়, যখন শেলটি পরিবর্তন করে এমন যেকোনো গতিশীল সংস্থান স্বাধীনভাবে লোড হয়।
ক্যাশে-বাস্ট আপনার precaching অনুরোধ
যখন sw-precache
রিসোর্সগুলি precache করার জন্য অনুরোধ করে, তখন এটি সেই প্রতিক্রিয়াগুলিকে অনির্দিষ্টকালের জন্য ব্যবহার করে যতক্ষণ না এটি মনে করে যে ফাইলের জন্য MD5 হ্যাশ পরিবর্তন হয়নি। এর মানে হল যে প্রিক্যাচিং অনুরোধের প্রতিক্রিয়া একটি নতুন এবং ব্রাউজারের HTTP ক্যাশে থেকে ফিরে আসে না তা নিশ্চিত করা বিশেষভাবে গুরুত্বপূর্ণ৷ ( fetch()
, একটি পরিষেবা কর্মী দ্বারা করা অনুরোধগুলি ব্রাউজারের HTTP ক্যাশে থেকে ডেটার সাথে প্রতিক্রিয়া জানাতে পারে৷)
আমরা যে প্রতিক্রিয়াগুলি precache করি তা সরাসরি নেটওয়ার্ক থেকে এবং ব্রাউজারের HTTP ক্যাশে নয় তা নিশ্চিত করার জন্য, sw-precache
স্বয়ংক্রিয়ভাবে প্রতিটি ইউআরএলে একটি ক্যাশে-বাস্টিং ক্যোয়ারী প্যারামিটার যোগ করে যা এটি অনুরোধ করে। আপনি যদি sw-precache
ব্যবহার না করেন এবং আপনি একটি ক্যাশে-প্রথম প্রতিক্রিয়া কৌশল ব্যবহার করছেন, তবে নিশ্চিত করুন যে আপনি নিজের কোডে অনুরূপ কিছু করছেন !
ক্যাশে-বাস্টিংয়ের একটি পরিষ্কার সমাধান হল reload
জন্য প্রিক্যাচিংয়ের জন্য ব্যবহৃত প্রতিটি Request
ক্যাশে মোড সেট করা, যা নিশ্চিত করবে যে প্রতিক্রিয়া নেটওয়ার্ক থেকে আসবে। যাইহোক, এই লেখা পর্যন্ত, ক্যাশে মোড বিকল্পটি Chrome-এ সমর্থিত নয় ।
লগ ইন এবং আউট জন্য সমর্থন
IOWA ব্যবহারকারীদের তাদের Google অ্যাকাউন্ট ব্যবহার করে লগ ইন করার এবং তাদের কাস্টমাইজড ইভেন্টের সময়সূচী আপডেট করার অনুমতি দিয়েছে, কিন্তু এর মানে হল যে ব্যবহারকারীরা পরে লগ আউট করতে পারে। ব্যক্তিগতকৃত প্রতিক্রিয়া ডেটা ক্যাশ করা স্পষ্টতই একটি জটিল বিষয় এবং সর্বদা একটি একক সঠিক পদ্ধতি নেই।
যেহেতু আপনার ব্যক্তিগত সময়সূচী দেখা, এমনকি অফলাইনে থাকাকালীনও, IOWA অভিজ্ঞতার মূল বিষয় ছিল, তাই আমরা সিদ্ধান্ত নিয়েছি যে ক্যাশে করা ডেটা ব্যবহার করা উপযুক্ত। যখন একজন ব্যবহারকারী সাইন আউট করেন, আমরা পূর্বে ক্যাশে করা সেশন ডেটা সাফ করার বিষয়টি নিশ্চিত করেছিলাম।
self.addEventListener('message', function(event) {
if (event.data === 'clear-cached-user-data') {
caches.open(toolbox.options.cacheName).then(function(cache) {
cache.keys().then(function(requests) {
return requests.filter(function(request) {
return request.url.indexOf('api/v1/user/') !== -1;
});
}).then(function(userDataRequests) {
userDataRequests.forEach(function(userDataRequest) {
cache.delete(userDataRequest);
});
});
});
}
});
অতিরিক্ত ক্যোয়ারী পরামিতি জন্য দেখুন!
যখন কোনও পরিষেবা কর্মী একটি ক্যাশে করা প্রতিক্রিয়া পরীক্ষা করে, তখন এটি কী হিসাবে একটি অনুরোধ URL ব্যবহার করে। ডিফল্টরূপে, অনুরোধের URLটি অবশ্যই URL-এর অনুসন্ধান অংশে যেকোন ক্যোয়ারী প্যারামিটার সহ ক্যাশে করা প্রতিক্রিয়া সঞ্চয় করতে ব্যবহৃত URL-এর সাথে হুবহু মিলতে হবে৷
আমাদের ট্র্যাফিক কোথা থেকে আসছে তা ট্র্যাক করার জন্য যখন আমরা URL প্যারামিটার ব্যবহার করা শুরু করি তখন এটি বিকাশের সময় আমাদের জন্য একটি সমস্যা সৃষ্টি করে। উদাহরণ স্বরূপ, আমরা utm_source=notification
প্যারামিটার যুক্ত করেছিলাম URL-এ যা খোলা হয়েছিল আমাদের একটি বিজ্ঞপ্তিতে ক্লিক করার সময়, এবং utm_source=web_app_manifest
ব্যবহার করেছি আমাদের ওয়েব অ্যাপ ম্যানিফেস্টের জন্য start_url
এ। পূর্বে ক্যাশ করা প্রতিক্রিয়াগুলির সাথে মিলে যাওয়া URLগুলি যখন সেই প্যারামিটারগুলি যুক্ত করা হয়েছিল তখন মিস হিসাবে উঠে আসছে৷
এটি আংশিকভাবে ignoreSearch
বিকল্প দ্বারা সম্বোধন করা হয়েছে যা Cache.match()
কল করার সময় ব্যবহার করা যেতে পারে। দুর্ভাগ্যবশত, Chrome এখনও ignoreSearch
সমর্থন করে না , এবং এমনকি যদি এটি করেও, এটি একটি সব-বা-কিছুই নয়। আমাদের যা দরকার ছিল তা হল কিছু ইউআরএল ক্যোয়ারী প্যারামিটার উপেক্ষা করার একটি উপায় যা অর্থপূর্ণ ছিল।
আমরা একটি ক্যাশে ম্যাচের জন্য চেক করার আগে কিছু ক্যোয়ারী প্যারামিটার বের করার জন্য sw-precache
প্রসারিত করেছি এবং ignoreUrlParametersMatching
বিকল্পের মাধ্যমে কোন প্যারামিটারগুলি উপেক্ষা করা হয়েছে তা ডেভেলপারদের কাস্টমাইজ করার অনুমতি দেয়। এখানে অন্তর্নিহিত বাস্তবায়ন আছে:
function stripIgnoredUrlParameters(originalUrl, ignoredRegexes) {
var url = new URL(originalUrl);
url.search = url.search.slice(1)
.split('&')
.map(function(kv) {
return kv.split('=');
})
.filter(function(kv) {
return ignoredRegexes.every(function(ignoredRegex) {
return !ignoredRegex.test(kv[0]);
});
})
.map(function(kv) {
return kv.join('=');
})
.join('&');
return url.toString();
}
হোয়াট দিস মিন্স ফর ইউ
Google I/O ওয়েব অ্যাপে পরিষেবা কর্মী সংহতকরণ সম্ভবত সবচেয়ে জটিল, বাস্তব-বিশ্বের ব্যবহার যা এই সময়ে স্থাপন করা হয়েছে। আমরা sw-precache
এবং sw-toolbox
তৈরি করা টুলগুলি ব্যবহার করে ওয়েব ডেভেলপার সম্প্রদায়ের সাথে সাথে আপনার নিজস্ব ওয়েব অ্যাপ্লিকেশনগুলিকে শক্তি দেওয়ার জন্য আমরা যে কৌশলগুলি বর্ণনা করছি তার জন্য আমরা অপেক্ষা করছি৷ পরিষেবা কর্মীরা একটি প্রগতিশীল বর্ধন যা আপনি আজ ব্যবহার শুরু করতে পারেন, এবং যখন একটি সঠিকভাবে কাঠামোগত ওয়েব অ্যাপের অংশ হিসাবে ব্যবহার করা হয়, তখন গতি এবং অফলাইন সুবিধাগুলি আপনার ব্যবহারকারীদের জন্য উল্লেখযোগ্য।

সারাংশ
Google I/O 2015 ওয়েব অ্যাপকে দ্রুত এবং অফলাইন-প্রথম করতে আমরা কীভাবে পরিষেবা কর্মী লাইব্রেরি ব্যবহার করেছি তা জানুন।
ওভারভিউ
এই বছরের Google I/O 2015 ওয়েব অ্যাপটি Google-এর ডেভেলপার রিলেশনস টিম দ্বারা লেখা হয়েছে, যা আমাদের Instrument- এ বন্ধুদের ডিজাইনের উপর ভিত্তি করে, যারা নিফটি অডিও/ভিজ্যুয়াল পরীক্ষা লিখেছেন৷ আমাদের দলের লক্ষ্য ছিল নিশ্চিত করা যে I/O ওয়েব অ্যাপ (যাকে আমি এর কোডনাম, IOWA দ্বারা উল্লেখ করব) আধুনিক ওয়েব যা করতে পারে তার সবকিছু প্রদর্শন করে। একটি সম্পূর্ণ অফলাইন-প্রথম অভিজ্ঞতা আমাদের থাকা আবশ্যক বৈশিষ্ট্যগুলির তালিকার শীর্ষে ছিল৷
আপনি যদি সম্প্রতি এই সাইটের অন্য কোনো নিবন্ধ পড়ে থাকেন, তাহলে আপনি নিঃসন্দেহে পরিষেবা কর্মীদের সম্মুখীন হয়েছেন, এবং আপনি শুনে অবাক হবেন না যে IOWA-এর অফলাইন সমর্থন তাদের উপর অনেক বেশি নির্ভরশীল। IOWA-এর বাস্তব-বিশ্বের চাহিদার দ্বারা অনুপ্রাণিত হয়ে, আমরা দুটি ভিন্ন অফলাইন ব্যবহারের ক্ষেত্রে দুটি লাইব্রেরি তৈরি করেছি: স্ট্যাটিক রিসোর্সের প্রিক্যাচিং স্বয়ংক্রিয় করতে sw-precache
, এবং রানটাইম ক্যাশিং এবং ফলব্যাক কৌশলগুলি পরিচালনা করার জন্য sw-toolbox
৷
লাইব্রেরিগুলি একে অপরের সুন্দরভাবে পরিপূরক করে, এবং আমাদেরকে একটি কার্যকরী কৌশল প্রয়োগ করার অনুমতি দেয় যেখানে IOWA-এর স্ট্যাটিক বিষয়বস্তু "শেল" সর্বদা সরাসরি ক্যাশে থেকে পরিবেশন করা হয়, এবং প্রয়োজনের সময় ক্যাশে বা স্ট্যাটিক প্রতিক্রিয়াগুলিতে ফলব্যাক সহ নেটওয়ার্ক থেকে গতিশীল বা দূরবর্তী সংস্থানগুলি পরিবেশন করা হয়।
sw-precache
সঙ্গে precaching
IOWA-এর স্ট্যাটিক রিসোর্স-এর HTML, JavaScript, CSS এবং ছবিগুলি-ওয়েব অ্যাপ্লিকেশনের মূল শেল প্রদান করে। এই সংস্থানগুলি ক্যাশে করার বিষয়ে চিন্তা করার সময় দুটি নির্দিষ্ট প্রয়োজনীয়তা গুরুত্বপূর্ণ ছিল: আমরা নিশ্চিত করতে চেয়েছিলাম যে বেশিরভাগ স্ট্যাটিক সংস্থান ক্যাশে করা হয়েছে এবং সেগুলি আপ টু ডেট রাখা হয়েছে। sw-precache
সেই প্রয়োজনীয়তাগুলিকে মাথায় রেখে তৈরি করা হয়েছিল।
বিল্ড-টাইম ইন্টিগ্রেশন
IOWA-এর gulp
ভিত্তিক বিল্ড প্রক্রিয়ার সাথে sw-precache
, এবং আমরা IOWA ব্যবহার করা সমস্ত স্ট্যাটিক রিসোর্সগুলির একটি সম্পূর্ণ তালিকা তৈরি করা নিশ্চিত করতে গ্লোব প্যাটার্নের একটি সিরিজের উপর নির্ভর করি।
staticFileGlobs: [
rootDir + '/bower_components/**/*.{html,js,css}',
rootDir + '/elements/**',
rootDir + '/fonts/**',
rootDir + '/images/**',
rootDir + '/scripts/**',
rootDir + '/styles/**/*.css',
rootDir + '/data-worker-scripts.js'
]
বিকল্প পন্থা, যেমন একটি অ্যারেতে ফাইলের নামের তালিকাকে কঠিন কোডিং করা, এবং প্রতিবার সেই ফাইলগুলির যেকোনও পরিবর্তনের সময় একটি ক্যাশে সংস্করণ নম্বর বাম্প করার কথা মনে রাখা অনেক বেশি ত্রুটির প্রবণ ছিল, বিশেষ করে আমাদের একাধিক টিম সদস্য কোড চেক করার কারণে। ম্যানুয়ালি রক্ষণাবেক্ষণ করা অ্যারেতে একটি নতুন ফাইল রেখে কেউ অফলাইন সমর্থন ভাঙতে চায় না! বিল্ড-টাইম ইন্টিগ্রেশন মানে আমরা বিদ্যমান ফাইলগুলিতে পরিবর্তন করতে পারি এবং সেই উদ্বেগ ছাড়াই নতুন ফাইল যোগ করতে পারি।
ক্যাশড রিসোর্স আপডেট করা হচ্ছে
sw-precache
একটি বেস সার্ভিস ওয়ার্কার স্ক্রিপ্ট তৈরি করে যাতে প্রতিটি রিসোর্সের জন্য একটি অনন্য MD5 হ্যাশ থাকে যা প্রিক্যাচ করা হয়। প্রতিবার একটি বিদ্যমান সংস্থান পরিবর্তিত হয়, বা একটি নতুন সংস্থান যোগ করা হয়, পরিষেবা কর্মী স্ক্রিপ্টটি পুনরায় তৈরি করা হয়। এটি স্বয়ংক্রিয়ভাবে পরিষেবা কর্মী আপডেট ফ্লোকে ট্রিগার করে, যাতে নতুন সংস্থানগুলি ক্যাশে করা হয় এবং পুরানো সংস্থানগুলি পরিষ্কার করা হয়৷ অভিন্ন MD5 হ্যাশ আছে এমন যেকোন বিদ্যমান সংস্থান যেমন আছে তেমনই রেখে দেওয়া হয়। এর মানে হল যে ব্যবহারকারীরা সাইটটি পরিদর্শন করার আগে শুধুমাত্র পরিবর্তিত সংস্থানগুলির ন্যূনতম সেট ডাউনলোড করে, যার ফলে সমগ্র ক্যাশে একত্রে মেয়াদ শেষ হয়ে যাওয়ার চেয়ে অনেক বেশি দক্ষ অভিজ্ঞতার দিকে পরিচালিত করে৷
প্রতিটি ফাইল যা গ্লোব প্যাটার্নগুলির একটির সাথে মেলে তা ডাউনলোড করা হয় এবং প্রথমবার ব্যবহারকারী যখন IOWA পরিদর্শন করে তখন ক্যাশ করা হয়। আমরা নিশ্চিত করার জন্য একটি প্রচেষ্টা করেছি যে পৃষ্ঠাটি রেন্ডার করার জন্য শুধুমাত্র গুরুত্বপূর্ণ সংস্থানগুলিই প্রিক্যাচ করা হয়েছে৷ মাধ্যমিক বিষয়বস্তু, যেমন অডিও/ভিজ্যুয়াল পরীক্ষায় ব্যবহৃত মিডিয়া, অথবা সেশনের স্পিকারের প্রোফাইল চিত্রগুলি, ইচ্ছাকৃতভাবে প্রিক্যাচ করা হয়নি, এবং আমরা পরিবর্তে সেই সংস্থানগুলির জন্য অফলাইন অনুরোধগুলি পরিচালনা করতে sw-toolbox
লাইব্রেরি ব্যবহার করেছি৷
sw-toolbox
, আমাদের সমস্ত গতিশীল প্রয়োজনের জন্য
উল্লিখিত হিসাবে, একটি সাইটের অফলাইনে কাজ করার জন্য প্রয়োজন এমন প্রতিটি সংস্থান প্রিক্যাচ করা সম্ভব নয়৷ কিছু রিসোর্স অনেক বড় বা এটিকে সার্থক করতে কদাচিৎ ব্যবহার করা হয় এবং অন্যান্য রিসোর্স গতিশীল, যেমন দূরবর্তী API বা পরিষেবা থেকে পাওয়া প্রতিক্রিয়া। কিন্তু শুধুমাত্র একটি অনুরোধ প্রিক্যাচেড না হওয়ার মানে এই নয় যে এটি একটি NetworkError
এ পরিণত হবে। sw-toolbox
আমাদের অনুরোধ হ্যান্ডলারগুলি বাস্তবায়নের নমনীয়তা দিয়েছে যা কিছু সংস্থান এবং অন্যদের জন্য কাস্টম ফ্যালব্যাকগুলির জন্য রানটাইম ক্যাচিং পরিচালনা করে। পুশ বিজ্ঞপ্তিগুলির প্রতিক্রিয়া হিসাবে আমরা আমাদের পূর্বে ক্যাশেড সংস্থানগুলি আপডেট করতে এটি ব্যবহার করেছি।
আমরা এসডাব্লু-টুলবক্সের শীর্ষে তৈরি কাস্টম অনুরোধ হ্যান্ডলারগুলির কয়েকটি উদাহরণ এখানে দেওয়া হল। sw-precache
importScripts parameter
মাধ্যমে বেস পরিষেবা কর্মী স্ক্রিপ্টের সাথে তাদের সংহত করা সহজ ছিল, যা স্ট্যান্ডেলোন জাভাস্ক্রিপ্ট ফাইলগুলিকে পরিষেবা কর্মীর সুযোগে টান দেয়।
অডিও/ভিজ্যুয়াল পরীক্ষা
অডিও/ভিজ্যুয়াল পরীক্ষার জন্য, আমরা sw-toolbox
networkFirst
ক্যাশে কৌশল ব্যবহার করেছি। পরীক্ষার জন্য ইউআরএল প্যাটার্নের সাথে মেলে সমস্ত এইচটিটিপি অনুরোধগুলি প্রথমে নেটওয়ার্কের বিরুদ্ধে করা হবে এবং যদি একটি সফল প্রতিক্রিয়া ফিরে আসে তবে সেই প্রতিক্রিয়াটি তখন ক্যাশে স্টোরেজ এপিআই ব্যবহার করে দূরে সরিয়ে দেওয়া হবে। যদি নেটওয়ার্কটি অনুপলব্ধ ছিল তখন যদি পরবর্তীকালে কোনও অনুরোধ করা হয় তবে পূর্বে ক্যাশেড প্রতিক্রিয়া ব্যবহার করা হবে।
যেহেতু প্রতিটি সফল নেটওয়ার্ক প্রতিক্রিয়া ফিরে আসার সময় ক্যাশে স্বয়ংক্রিয়ভাবে আপডেট হয়েছিল, তাই আমাদের বিশেষভাবে সংস্থানগুলি সংস্করণ করতে বা এন্ট্রিগুলির মেয়াদ শেষ করতে হবে না।
toolbox.router.get('/experiment/(.+)', toolbox.networkFirst);
স্পিকার প্রোফাইল চিত্র
স্পিকার প্রোফাইল চিত্রগুলির জন্য, আমাদের লক্ষ্যটি ছিল কোনও প্রদত্ত স্পিকারের চিত্রের পূর্বে ক্যাশেড সংস্করণটি যদি এটি উপলব্ধ থাকে তবে চিত্রটি না থাকলে চিত্রটি পুনরুদ্ধার করতে নেটওয়ার্কে ফিরে পড়ে। যদি সেই নেটওয়ার্কের অনুরোধটি ব্যর্থ হয়, চূড়ান্ত ফ্যালব্যাক হিসাবে, আমরা একটি জেনেরিক স্থানধারক চিত্র ব্যবহার করেছি যা পূর্বনির্ধারিত ছিল (এবং তাই সর্বদা উপলব্ধ থাকবে)। জেনেরিক স্থানধারক দিয়ে প্রতিস্থাপন করা যেতে পারে এমন চিত্রগুলির সাথে ডিল করার সময় এটি ব্যবহার করার একটি সাধারণ কৌশল এবং sw-toolbox
cacheFirst
এবং cacheOnly
হ্যান্ডলারগুলি চেইন করে এটি প্রয়োগ করা সহজ ছিল।
var DEFAULT_PROFILE_IMAGE = 'images/touch/homescreen96.png';
function profileImageRequest(request) {
return toolbox.cacheFirst(request).catch(function() {
return toolbox.cacheOnly(new Request(DEFAULT_PROFILE_IMAGE));
});
}
toolbox.precache([DEFAULT_PROFILE_IMAGE]);
toolbox.router.get('/(.+)/images/speakers/(.*)',
profileImageRequest,
{origin: /.*\.googleapis\.com/});

ব্যবহারকারীদের সময়সূচীতে আপডেট
আইওয়া এর অন্যতম মূল বৈশিষ্ট্য স্বাক্ষরিত-ইন ব্যবহারকারীদের অংশ নেওয়ার পরিকল্পনা করা সেশনগুলির একটি সময়সূচী তৈরি এবং বজায় রাখতে অনুমতি দিচ্ছিল। আপনি যেমন আশা করেছিলেন, সেশন আপডেটগুলি ব্যাকএন্ড সার্ভারে এইচটিটিপি POST
অনুরোধগুলির মাধ্যমে করা হয়েছিল এবং ব্যবহারকারী অফলাইনে থাকাকালীন আমরা সেই রাজ্য-সংশোধনকারী অনুরোধগুলি পরিচালনা করার জন্য সেরা উপায়টি কাজ করার জন্য কিছুটা সময় ব্যয় করেছি। আমরা ইনডেক্সডিবিতে সারি করা ব্যর্থ অনুরোধগুলির সংমিশ্রণটি নিয়ে এসেছি, মূল ওয়েব পৃষ্ঠায় যুক্তির সাথে মিলিত হয়েছে যা সারি অনুরোধগুলির জন্য ইনডেক্সডডিবি পরীক্ষা করে এবং এটি যে কোনও খুঁজে পেয়েছে তা পুনরায় চেষ্টা করে।
var DB_NAME = 'shed-offline-session-updates';
function queueFailedSessionUpdateRequest(request) {
simpleDB.open(DB_NAME).then(function(db) {
db.set(request.url, request.method);
});
}
function handleSessionUpdateRequest(request) {
return global.fetch(request).then(function(response) {
if (response.status >= 500) {
return Response.error();
}
return response;
}).catch(function() {
queueFailedSessionUpdateRequest(request);
});
}
toolbox.router.put('/(.+)api/v1/user/schedule/(.+)',
handleSessionUpdateRequest);
toolbox.router.delete('/(.+)api/v1/user/schedule/(.+)',
handleSessionUpdateRequest);
যেহেতু পুনরায় চেষ্টাগুলি মূল পৃষ্ঠার প্রসঙ্গ থেকে তৈরি করা হয়েছিল, আমরা নিশ্চিত হতে পারি যে তারা ব্যবহারকারীর শংসাপত্রগুলির একটি নতুন সেট অন্তর্ভুক্ত করেছে। একবারে পুনরায় চেষ্টাগুলি সফল হয়ে গেলে, আমরা ব্যবহারকারীকে তাদের পূর্বে সারিবদ্ধ আপডেটগুলি প্রয়োগ করা হয়েছে তা জানাতে একটি বার্তা প্রদর্শন করেছি।
simpleDB.open(QUEUED_SESSION_UPDATES_DB_NAME).then(function(db) {
var replayPromises = [];
return db.forEach(function(url, method) {
var promise = IOWA.Request.xhrPromise(method, url, true).then(function() {
return db.delete(url).then(function() {
return true;
});
});
replayPromises.push(promise);
}).then(function() {
if (replayPromises.length) {
return Promise.all(replayPromises).then(function() {
IOWA.Elements.Toast.showMessage(
'My Schedule was updated with offline changes.');
});
}
});
}).catch(function() {
IOWA.Elements.Toast.showMessage(
'Offline changes could not be applied to My Schedule.');
});
অফলাইন গুগল অ্যানালিটিক্স
অনুরূপ শিরাতে, আমরা কোনও ব্যর্থ গুগল অ্যানালিটিক্স অনুরোধগুলি সারি করার জন্য একটি হ্যান্ডলার প্রয়োগ করেছি এবং যখন নেটওয়ার্কটি আশাবাদী উপলব্ধ ছিল তখন পরে সেগুলি পুনরায় খেলার চেষ্টা করেছিলাম। এই পদ্ধতির সাথে, অফলাইনে থাকার অর্থ গুগল অ্যানালিটিক্স অফারগুলি অন্তর্দৃষ্টি ত্যাগ করা নয়। আমরা প্রতিটি সারিবদ্ধ অনুরোধে qt
প্যারামিটার যুক্ত করেছি, অনুরোধটি প্রথম চেষ্টা করার পরে যে পরিমাণ সময় পেরিয়ে গেছে তার পরিমাণ নির্ধারণ করেছিলাম, এটি নিশ্চিত করার জন্য যে একটি উপযুক্ত ইভেন্টের অ্যাট্রিবিউশন সময় এটি গুগল অ্যানালিটিক্স ব্যাকএন্ডে তৈরি করেছে। গুগল অ্যানালিটিক্স আনুষ্ঠানিকভাবে কেবল 4 ঘন্টা অবধি qt
জন্য মানগুলিকে সমর্থন করে, তাই আমরা যত তাড়াতাড়ি সম্ভব এই অনুরোধগুলি পুনরায় খেলতে একটি সেরা-প্রচেষ্টা চেষ্টা করেছি, প্রতিবার পরিষেবা কর্মী শুরু করার সময়।
var DB_NAME = 'offline-analytics';
var EXPIRATION_TIME_DELTA = 86400000;
var ORIGIN = /https?:\/\/((www|ssl)\.)?google-analytics\.com/;
function replayQueuedAnalyticsRequests() {
simpleDB.open(DB_NAME).then(function(db) {
db.forEach(function(url, originalTimestamp) {
var timeDelta = Date.now() - originalTimestamp;
var replayUrl = url + '&qt=' + timeDelta;
fetch(replayUrl).then(function(response) {
if (response.status >= 500) {
return Response.error();
}
db.delete(url);
}).catch(function(error) {
if (timeDelta > EXPIRATION_TIME_DELTA) {
db.delete(url);
}
});
});
});
}
function queueFailedAnalyticsRequest(request) {
simpleDB.open(DB_NAME).then(function(db) {
db.set(request.url, Date.now());
});
}
function handleAnalyticsCollectionRequest(request) {
return global.fetch(request).then(function(response) {
if (response.status >= 500) {
return Response.error();
}
return response;
}).catch(function() {
queueFailedAnalyticsRequest(request);
});
}
toolbox.router.get('/collect',
handleAnalyticsCollectionRequest,
{origin: ORIGIN});
toolbox.router.get('/analytics.js',
toolbox.networkFirst,
{origin: ORIGIN});
replayQueuedAnalyticsRequests();
বিজ্ঞপ্তি অবতরণ পৃষ্ঠাগুলি ধাক্কা দিন
পরিষেবা কর্মীরা কেবল আইওয়ার অফলাইন কার্যকারিতা পরিচালনা করেননি - তারা তাদের বুকমার্কযুক্ত সেশনের আপডেটগুলি সম্পর্কে ব্যবহারকারীদের অবহিত করার জন্য আমরা যে ধাক্কা বিজ্ঞপ্তিগুলি ব্যবহার করেছি তাও চালিত করেছিল। এই বিজ্ঞপ্তিগুলির সাথে যুক্ত অবতরণ পৃষ্ঠাটি আপডেট হওয়া সেশনের বিশদটি প্রদর্শন করেছে। এই অবতরণ পৃষ্ঠাগুলি ইতিমধ্যে সামগ্রিক সাইটের অংশ হিসাবে ক্যাশে করা হচ্ছে, সুতরাং তারা ইতিমধ্যে অফলাইনে কাজ করেছে, তবে আমাদের নিশ্চিত করা দরকার যে সেই পৃষ্ঠায় সেশনের বিশদটি আপ টু ডেট ছিল, এমনকি অফলাইনে দেখা গেলেও। এটি করার জন্য, আমরা পূর্বে ক্যাশেড সেশন মেটাডেটাকে আপডেটগুলি দিয়ে সংশোধন করেছি যা পুশ বিজ্ঞপ্তিটিকে ট্রিগার করেছিল এবং আমরা ফলাফলটি ক্যাশে সংরক্ষণ করেছি। অনলাইনে বা অফলাইনে স্থান নেওয়া হোক না কেন, সেশন বিশদ পৃষ্ঠাটি খোলার পরের বার এই আপ-টু-ডেট তথ্যটি ব্যবহার করা হবে।
caches.open(toolbox.options.cacheName).then(function(cache) {
cache.match('api/v1/schedule').then(function(response) {
if (response) {
parseResponseJSON(response).then(function(schedule) {
sessions.forEach(function(session) {
schedule.sessions[session.id] = session;
});
cache.put('api/v1/schedule',
new Response(JSON.stringify(schedule)));
});
} else {
toolbox.cache('api/v1/schedule');
}
});
});
Gotchas এবং বিবেচনা
অবশ্যই, কয়েকটি গোটচাসে না গিয়ে আইওয়া স্কেলের কোনও প্রকল্পে কেউ কাজ করে না। আমরা যেগুলি দৌড়েছি তার কয়েকটি এখানে রয়েছে এবং আমরা কীভাবে তাদের চারপাশে কাজ করেছি।
বাসি বিষয়বস্তু
যখনই আপনি কোনও ক্যাচিংয়ের কৌশল পরিকল্পনা করছেন, পরিষেবা কর্মীদের মাধ্যমে বা স্ট্যান্ডার্ড ব্রাউজার ক্যাশে দিয়ে প্রয়োগ করা হোক না কেন, সর্বাধিক দ্রুত সংস্থানগুলি সরবরাহের তুলনায় যত তাড়াতাড়ি সম্ভব সংস্থান সরবরাহের মধ্যে একটি বাণিজ্য রয়েছে। sw-precache
মাধ্যমে, আমরা আমাদের অ্যাপ্লিকেশনটির শেলটির জন্য একটি আক্রমণাত্মক ক্যাশে-প্রথম কৌশল বাস্তবায়ন করেছি, যার অর্থ আমাদের পরিষেবা কর্মী পৃষ্ঠায় এইচটিএমএল, জাভাস্ক্রিপ্ট এবং সিএসএস ফিরিয়ে দেওয়ার আগে আপডেটের জন্য নেটওয়ার্কটি পরীক্ষা করবে না।
ভাগ্যক্রমে, আমরা পৃষ্ঠাটি ইতিমধ্যে লোড হওয়ার পরে নতুন সামগ্রী কখন উপলব্ধ ছিল তা সনাক্ত করতে আমরা পরিষেবা কর্মী লাইফসাইকেল ইভেন্টগুলির সুবিধা নিতে সক্ষম হয়েছি। যখন কোনও আপডেট করা পরিষেবা কর্মী সনাক্ত করা হয়, আমরা ব্যবহারকারীকে তাদের জানাতে একটি টোস্ট বার্তা প্রদর্শন করি যে তাদের নতুন সামগ্রীটি দেখতে তাদের পৃষ্ঠাটি পুনরায় লোড করা উচিত।
if (navigator.serviceWorker && navigator.serviceWorker.controller) {
navigator.serviceWorker.controller.onstatechange = function(e) {
if (e.target.state === 'redundant') {
var tapHandler = function() {
window.location.reload();
};
IOWA.Elements.Toast.showMessage(
'Tap here or refresh the page for the latest content.',
tapHandler);
}
};
}

স্থির বিষয়বস্তু স্থির কিনা তা নিশ্চিত করুন!
sw-precache
স্থানীয় ফাইলগুলির সামগ্রীগুলির একটি এমডি 5 হ্যাশ ব্যবহার করে এবং কেবলমাত্র এমন সংস্থানগুলি এনেছে যার হ্যাশ পরিবর্তিত হয়েছে। এর অর্থ হ'ল সংস্থানগুলি প্রায় অবিলম্বে পৃষ্ঠায় উপলভ্য, তবে এর অর্থ এটিও হ'ল একবার কিছু ক্যাশে হয়ে গেলে, এটি কোনও আপডেট হওয়া পরিষেবা কর্মী স্ক্রিপ্টে নতুন হ্যাশ বরাদ্দ না করা পর্যন্ত এটি ক্যাশে থাকতে চলেছে।
সম্মেলনের প্রতিটি দিনের জন্য লাইভস্ট্রিম ইউটিউব ভিডিও আইডিগুলি গতিশীলভাবে আপডেট করার প্রয়োজনের কারণে আমরা আই/ও চলাকালীন এই আচরণের সাথে একটি ইস্যুতে দৌড়েছি । যেহেতু অন্তর্নিহিত টেম্পলেট ফাইলটি স্থির ছিল এবং এটি পরিবর্তন হয়নি, আমাদের পরিষেবা কর্মী আপডেট প্রবাহটি ট্রিগার করা হয়নি এবং ইউটিউব ভিডিও আপডেট করার সাথে সার্ভারের কাছ থেকে গতিশীল প্রতিক্রিয়া হিসাবে বোঝানো হয়েছিল যা বেশ কয়েকটি ব্যবহারকারীর জন্য ক্যাশেড প্রতিক্রিয়া হিসাবে শেষ হয়েছিল।
আপনার ওয়েব অ্যাপ্লিকেশনটিকে কাঠামোগত করা হয়েছে তা নিশ্চিত করে আপনি এই ধরণের সমস্যাটি এড়াতে পারেন যাতে শেলটি সর্বদা স্থির থাকে এবং নিরাপদে পূর্বাভাস দেওয়া যায়, যখন শেলটি সংশোধন করে এমন কোনও গতিশীল সংস্থান স্বাধীনভাবে লোড হয়।
ক্যাশে-বস্ট আপনার পূর্বের অনুরোধগুলি
যখন sw-precache
সংস্থানগুলি প্রাকচাচের জন্য অনুরোধ করে, তখন এটি সেই প্রতিক্রিয়াগুলি অনির্দিষ্টকালের জন্য ব্যবহার করে যতক্ষণ না এটি মনে করে যে ফাইলটির জন্য এমডি 5 হ্যাশ পরিবর্তন হয়নি। এর অর্থ হ'ল এটি নিশ্চিত করা বিশেষভাবে গুরুত্বপূর্ণ যে প্রাক্যাচিং অনুরোধের প্রতিক্রিয়াটি একটি নতুন, এবং ব্রাউজারের এইচটিটিপি ক্যাশে থেকে ফিরে আসেনি। (হ্যাঁ, fetch()
কোনও পরিষেবা কর্মী করা অনুরোধগুলি ব্রাউজারের এইচটিটিপি ক্যাশে থেকে ডেটা দিয়ে প্রতিক্রিয়া জানাতে পারে))
আমরা যে প্রতিক্রিয়াগুলি প্রাকচারগুলি সরাসরি নেটওয়ার্ক থেকে এসেছি তা নিশ্চিত করার জন্য, ব্রাউজারের এইচটিটিপি ক্যাশে নয়, sw-precache
স্বয়ংক্রিয়ভাবে এটি প্রতিটি ইউআরএল অনুরোধ করে একটি ক্যাশে-বস্টিং ক্যোয়ারী প্যারামিটার যুক্ত করে । আপনি যদি sw-precache
ব্যবহার না করে থাকেন এবং আপনি ক্যাশে-প্রথম প্রতিক্রিয়া কৌশলটি ব্যবহার করছেন, তবে নিশ্চিত হয়ে নিন যে আপনি নিজের কোডে অনুরূপ কিছু করেছেন !
ক্যাশে-বস্টিংয়ের একটি ক্লিনার সমাধান হ'ল reload
জন্য ব্যবহৃত প্রতিটি Request
ক্যাশে মোড সেট করা, যা নিশ্চিত করবে যে প্রতিক্রিয়াটি নেটওয়ার্ক থেকে এসেছে। যাইহোক, এই লেখার হিসাবে, ক্যাশে মোড বিকল্পটি ক্রোমে সমর্থিত নয় ।
লগ ইন এবং আউট জন্য সমর্থন
আইওয়া ব্যবহারকারীদের তাদের গুগল অ্যাকাউন্টগুলি ব্যবহার করে লগ ইন করতে এবং তাদের কাস্টমাইজড ইভেন্টের সময়সূচী আপডেট করার অনুমতি দেয় তবে এর অর্থ হ'ল ব্যবহারকারীরা পরে লগ আউট করতে পারেন। ব্যক্তিগতকৃত প্রতিক্রিয়া ডেটা ক্যাশে করা স্পষ্টতই একটি জটিল বিষয়, এবং সর্বদা একটি সঠিক পদ্ধতির থাকে না।
আপনার ব্যক্তিগত সময়সূচীটি দেখার পরে, এমনকি যখন অফলাইনে, আইওয়া অভিজ্ঞতার মূল ছিল, আমরা সিদ্ধান্ত নিয়েছি যে ক্যাশেড ডেটা ব্যবহার করা উপযুক্ত। যখন কোনও ব্যবহারকারী সাইন আউট করে, আমরা পূর্বে ক্যাশেড সেশন ডেটা সাফ করার বিষয়টি নিশ্চিত করেছিলাম।
self.addEventListener('message', function(event) {
if (event.data === 'clear-cached-user-data') {
caches.open(toolbox.options.cacheName).then(function(cache) {
cache.keys().then(function(requests) {
return requests.filter(function(request) {
return request.url.indexOf('api/v1/user/') !== -1;
});
}).then(function(userDataRequests) {
userDataRequests.forEach(function(userDataRequest) {
cache.delete(userDataRequest);
});
});
});
}
});
অতিরিক্ত ক্যোয়ারী প্যারামিটারগুলির জন্য দেখুন!
যখন কোনও পরিষেবা কর্মী ক্যাশেড প্রতিক্রিয়ার জন্য পরীক্ষা করে, এটি কী হিসাবে একটি অনুরোধ ইউআরএল ব্যবহার করে। ডিফল্টরূপে, অনুরোধের ইউআরএলটি অবশ্যই ইউআরএল এর অনুসন্ধান অংশে কোনও ক্যোয়ারী প্যারামিটার সহ ক্যাশেড প্রতিক্রিয়া সঞ্চয় করতে ব্যবহৃত ইউআরএলটির সাথে হুবহু মেলে।
এটি বিকাশের সময় আমাদের জন্য একটি সমস্যা সৃষ্টি করে, যখন আমরা আমাদের ট্র্যাফিক কোথা থেকে আসছিল তা ট্র্যাক রাখতে ইউআরএল প্যারামিটারগুলি ব্যবহার শুরু করি। উদাহরণস্বরূপ, আমরা আমাদের বিজ্ঞপ্তিগুলির একটিতে ক্লিক করার সময় খোলা ইউআরএলগুলিতে utm_source=notification
প্যারামিটার যুক্ত করেছি এবং আমাদের ওয়েব অ্যাপ্লিকেশন ম্যানিফেস্টের start_url
utm_source=web_app_manifest
ব্যবহার করেছি। URLS যা পূর্বে ক্যাশেড প্রতিক্রিয়াগুলির সাথে মেলে তখন মিস হিসাবে আসছিল যখন এই পরামিতিগুলি যুক্ত করা হয়েছিল।
এটি আংশিকভাবে ignoreSearch
বিকল্প দ্বারা সম্বোধন করা হয়েছে যা Cache.match()
কল করার সময় ব্যবহার করা যেতে পারে। দুর্ভাগ্যক্রমে, ক্রোম এখনও ignoreSearch
সমর্থন করে না , এবং এটি যদি তা করে থাকে তবে এটি একটি সর্বশক্তিমান আচরণ নয়। আমাদের যা প্রয়োজন তা হ'ল কিছু ইউআরএল ক্যোয়ারী প্যারামিটারগুলি উপেক্ষা করার একটি উপায় ছিল যখন অন্যদের বিবেচনায় নেওয়া উচিত।
আমরা ক্যাশে ম্যাচটি পরীক্ষা করার আগে কিছু ক্যোয়ারী প্যারামিটারগুলি ছিনিয়ে নেওয়ার জন্য sw-precache
প্রসারিত করে শেষ করেছি এবং বিকাশকারীদের ignoreUrlParametersMatching
করার জন্য কোন প্যারামিটারগুলি উপেক্ষা করা হয় তা কাস্টমাইজ করার অনুমতি দেয়। এখানে অন্তর্নিহিত বাস্তবায়ন:
function stripIgnoredUrlParameters(originalUrl, ignoredRegexes) {
var url = new URL(originalUrl);
url.search = url.search.slice(1)
.split('&')
.map(function(kv) {
return kv.split('=');
})
.filter(function(kv) {
return ignoredRegexes.every(function(ignoredRegex) {
return !ignoredRegex.test(kv[0]);
});
})
.map(function(kv) {
return kv.join('=');
})
.join('&');
return url.toString();
}
হোয়াট দিস মিন্স ফর ইউ
গুগল আই/ও ওয়েব অ্যাপে পরিষেবা কর্মী সংহতকরণ সম্ভবত সবচেয়ে জটিল, বাস্তব-বিশ্বের ব্যবহার যা এই পর্যায়ে মোতায়েন করা হয়েছে। আমরা sw-precache
এবং sw-toolbox
তৈরি করা সরঞ্জামগুলির পাশাপাশি আমরা আপনার নিজস্ব ওয়েব অ্যাপ্লিকেশনগুলিকে শক্তিশালী করার জন্য যে কৌশলগুলি বর্ণনা করছি সেগুলি ব্যবহার করে আমরা ওয়েব বিকাশকারী সম্প্রদায়ের অপেক্ষায় রয়েছি। পরিষেবা কর্মীরা একটি প্রগতিশীল বর্ধন যা আপনি আজ ব্যবহার শুরু করতে পারেন এবং যখন সঠিকভাবে কাঠামোগত ওয়েব অ্যাপের অংশ হিসাবে ব্যবহার করা হয়, তখন আপনার ব্যবহারকারীদের জন্য গতি এবং অফলাইন সুবিধাগুলি উল্লেখযোগ্য।

সারাংশ
গুগল আই/ও 2015 ওয়েব অ্যাপ্লিকেশনটিকে দ্রুত এবং অফলাইন-প্রথম তৈরি করতে আমরা কীভাবে পরিষেবা কর্মী গ্রন্থাগারগুলি ব্যবহার করেছি তা শিখুন।
ওভারভিউ
এই বছরের গুগল আই/ও 2015 ওয়েব অ্যাপটি গুগলের বিকাশকারী সম্পর্ক দল দ্বারা লিখিত ছিল, আমাদের বন্ধুদের দ্বারা ইনস্ট্রুমেন্টের ডিজাইনের উপর ভিত্তি করে, যারা নিফটি অডিও/ভিজ্যুয়াল পরীক্ষাটি লিখেছিলেন। আমাদের দলের মিশনটি নিশ্চিত করা ছিল যে আই/ও ওয়েব অ্যাপ (যা আমি এর কোডনাম, আইওয়া দ্বারা উল্লেখ করব) আধুনিক ওয়েব যা করতে পারে তা প্রদর্শন করেছে। একটি সম্পূর্ণ অফলাইন-প্রথম অভিজ্ঞতা আমাদের অবশ্যই বৈশিষ্ট্যগুলির তালিকার শীর্ষে ছিল।
আপনি যদি সম্প্রতি এই সাইটের অন্য কোনও নিবন্ধ পড়ে থাকেন তবে আপনি নিঃসন্দেহে পরিষেবা কর্মীদের মুখোমুখি হয়েছেন এবং শুনে আপনি অবাক হবেন না যে আইওয়া এর অফলাইন সমর্থন তাদের উপর ভারী নির্ভরশীল। আইওয়া-র বাস্তব-জগতের প্রয়োজনগুলির দ্বারা অনুপ্রাণিত হয়ে আমরা দুটি পৃথক অফলাইন ব্যবহারের ক্ষেত্রে দুটি লাইব্রেরি তৈরি করেছি: স্ট্যাটিক রিসোর্সের প্রাক্যাচিং স্বয়ংক্রিয় করার জন্য sw-precache
, এবং রানটাইম ক্যাচিং এবং ফ্যালব্যাক কৌশলগুলি পরিচালনা করার জন্য sw-toolbox
।
গ্রন্থাগারগুলি একে অপরকে সুন্দরভাবে পরিপূরক করে এবং আমাদের এমন একটি পারফরম্যান্ট কৌশল বাস্তবায়নের অনুমতি দেয় যেখানে আইওয়া এর স্ট্যাটিক সামগ্রী "শেল" সর্বদা সরাসরি ক্যাশে থেকে পরিবেশন করা হত, এবং গতিশীল বা দূরবর্তী সংস্থানগুলি নেটওয়ার্ক থেকে পরিবেশন করা হয়েছিল, যখন প্রয়োজনের সময় ক্যাশেড বা স্থির প্রতিক্রিয়াগুলির ফ্যালব্যাকস সহ।
sw-precache
দিয়ে প্রাক্কিং
আইওয়া এর স্ট্যাটিক রিসোর্সগুলি - এর এইচটিএমএল, জাভাস্ক্রিপ্ট, সিএসএস এবং চিত্রগুলি - ওয়েব অ্যাপ্লিকেশনটির জন্য মূল শেল সরবরাহ করে। এই সংস্থানগুলি ক্যাশে করার বিষয়ে চিন্তাভাবনা করার সময় দুটি নির্দিষ্ট প্রয়োজনীয়তা ছিল যা গুরুত্বপূর্ণ ছিল: আমরা নিশ্চিত করতে চেয়েছিলাম যে বেশিরভাগ স্থিতিশীল সংস্থানগুলি ক্যাশে করা হয়েছিল এবং সেগুলি আপ টু ডেট রাখা হয়েছিল। সেই প্রয়োজনীয়তাগুলি মাথায় রেখে sw-precache
নির্মিত হয়েছিল।
বিল্ড-টাইম ইন্টিগ্রেশন
আইওয়া এর gulp
-ভিত্তিক বিল্ড প্রক্রিয়া সহ sw-precache
এবং আমরা আইওয়া ব্যবহারের সমস্ত স্ট্যাটিক সংস্থানগুলির একটি সম্পূর্ণ তালিকা তৈরি করি তা নিশ্চিত করার জন্য আমরা গ্লোব নিদর্শনগুলির একটি সিরিজের উপর নির্ভর করি।
staticFileGlobs: [
rootDir + '/bower_components/**/*.{html,js,css}',
rootDir + '/elements/**',
rootDir + '/fonts/**',
rootDir + '/images/**',
rootDir + '/scripts/**',
rootDir + '/styles/**/*.css',
rootDir + '/data-worker-scripts.js'
]
বিকল্প পন্থাগুলি যেমন হার্ড কোডিংয়ের মতো একটি অ্যারেতে ফাইলের নামের তালিকা কোডিং করা এবং প্রতিবার যখন এই ফাইলগুলির পরিবর্তনগুলির কোনওটি খুব বেশি ত্রুটিযুক্ত ছিল তখন ক্যাশে সংস্করণ নম্বরটি বাম্প করার কথা মনে রাখা, বিশেষত আমাদের একাধিক দলের সদস্য কোডে চেক করা ছিল। ম্যানুয়ালি রক্ষণাবেক্ষণ করা অ্যারেতে নতুন ফাইল রেখে কেউ অফলাইন সমর্থন ভাঙতে চায় না! বিল্ড-টাইম ইন্টিগ্রেশনের অর্থ আমরা বিদ্যমান ফাইলগুলিতে পরিবর্তন করতে পারি এবং সেই উদ্বেগ ছাড়াই নতুন ফাইল যুক্ত করতে পারি।
ক্যাশেড সংস্থান আপডেট করা
sw-precache
একটি বেস পরিষেবা কর্মী স্ক্রিপ্ট উত্পন্ন করে যা প্রতিটি সংস্থানগুলির জন্য একটি অনন্য এমডি 5 হ্যাশ অন্তর্ভুক্ত করে যা পূর্বে পরিণত হয়। প্রতিবার যখন কোনও বিদ্যমান সংস্থান পরিবর্তন হয়, বা একটি নতুন সংস্থান যুক্ত হয়, পরিষেবা কর্মী স্ক্রিপ্টটি পুনরায় জেনারেট করা হয়। এটি স্বয়ংক্রিয়ভাবে পরিষেবা কর্মী আপডেট প্রবাহকে ট্রিগার করে, যেখানে নতুন সংস্থানগুলি ক্যাশে করা হয় এবং তারিখের পুরানো সংস্থানগুলি শুদ্ধ হয়। অভিন্ন এমডি 5 হ্যাশযুক্ত যে কোনও বিদ্যমান সংস্থানগুলি যেমন রয়েছে তেমন বাকি রয়েছে। এর অর্থ হ'ল এমন ব্যবহারকারীরা যারা কেবল পরিবর্তিত সংস্থানগুলির ন্যূনতম সেটটি ডাউনলোড করার আগে সাইটটি পরিদর্শন করেছেন, যার ফলে পুরো ক্যাশে ম্যাসেজের মেয়াদ শেষ হয়ে গেছে তার চেয়ে অনেক বেশি দক্ষ অভিজ্ঞতা অর্জন করে।
গ্লোব প্যাটার্নগুলির মধ্যে একটির সাথে মেলে এমন প্রতিটি ফাইল ডাউনলোড করা হয় এবং প্রথমবার যখন কোনও ব্যবহারকারী আইওয়া পরিদর্শন করেন তখন ক্যাশে হন। আমরা পৃষ্ঠাটি রেন্ডার করার জন্য কেবলমাত্র সমালোচনামূলক সংস্থানগুলি পূর্বনির্ধারিত হয়েছে তা নিশ্চিত করার জন্য একটি প্রচেষ্টা করেছি। অডিও/ভিজ্যুয়াল পরীক্ষায় ব্যবহৃত মিডিয়া বা সেশনগুলির স্পিকারের প্রোফাইল চিত্রগুলির মতো মাধ্যমিক সামগ্রীগুলি ইচ্ছাকৃতভাবে পূর্বনির্ধারিত ছিল না এবং আমরা পরিবর্তে সেই সংস্থানগুলির জন্য অফলাইন অনুরোধগুলি পরিচালনা করতে sw-toolbox
লাইব্রেরিটি ব্যবহার করেছি।
sw-toolbox
, আমাদের সমস্ত গতিশীল প্রয়োজনের জন্য
যেমনটি উল্লেখ করা হয়েছে, কোনও সাইটকে অফলাইনে কাজ করার প্রয়োজন এমন প্রতিটি সংস্থানকে পূর্বাভাস দেওয়া সম্ভব নয়। কিছু সংস্থানগুলি এটি সার্থক করার জন্য খুব বড় বা খুব কম সময়ে ব্যবহৃত হয় এবং অন্যান্য সংস্থানগুলি দূরবর্তী এপিআই বা পরিষেবার প্রতিক্রিয়াগুলির মতো গতিশীল। তবে কেবল একটি অনুরোধটি পূর্বনির্ধারিত নয় তার অর্থ এই নয় যে এটির কোনও NetworkError
ফলাফল হতে হবে। sw-toolbox
আমাদের অনুরোধ হ্যান্ডলারগুলি বাস্তবায়নের নমনীয়তা দিয়েছে যা কিছু সংস্থান এবং অন্যদের জন্য কাস্টম ফ্যালব্যাকগুলির জন্য রানটাইম ক্যাচিং পরিচালনা করে। পুশ বিজ্ঞপ্তিগুলির প্রতিক্রিয়া হিসাবে আমরা আমাদের পূর্বে ক্যাশেড সংস্থানগুলি আপডেট করতে এটি ব্যবহার করেছি।
আমরা এসডাব্লু-টুলবক্সের শীর্ষে তৈরি কাস্টম অনুরোধ হ্যান্ডলারগুলির কয়েকটি উদাহরণ এখানে দেওয়া হল। sw-precache
importScripts parameter
মাধ্যমে বেস পরিষেবা কর্মী স্ক্রিপ্টের সাথে তাদের সংহত করা সহজ ছিল, যা স্ট্যান্ডেলোন জাভাস্ক্রিপ্ট ফাইলগুলিকে পরিষেবা কর্মীর সুযোগে টান দেয়।
অডিও/ভিজ্যুয়াল পরীক্ষা
অডিও/ভিজ্যুয়াল পরীক্ষার জন্য, আমরা sw-toolbox
networkFirst
ক্যাশে কৌশল ব্যবহার করেছি। পরীক্ষার জন্য ইউআরএল প্যাটার্নের সাথে মেলে সমস্ত এইচটিটিপি অনুরোধগুলি প্রথমে নেটওয়ার্কের বিরুদ্ধে করা হবে এবং যদি একটি সফল প্রতিক্রিয়া ফিরে আসে তবে সেই প্রতিক্রিয়াটি তখন ক্যাশে স্টোরেজ এপিআই ব্যবহার করে দূরে সরিয়ে দেওয়া হবে। যদি নেটওয়ার্কটি অনুপলব্ধ ছিল তখন যদি পরবর্তীকালে কোনও অনুরোধ করা হয় তবে পূর্বে ক্যাশেড প্রতিক্রিয়া ব্যবহার করা হবে।
যেহেতু প্রতিটি সফল নেটওয়ার্ক প্রতিক্রিয়া ফিরে আসার সময় ক্যাশে স্বয়ংক্রিয়ভাবে আপডেট হয়েছিল, তাই আমাদের বিশেষভাবে সংস্থানগুলি সংস্করণ করতে বা এন্ট্রিগুলির মেয়াদ শেষ করতে হবে না।
toolbox.router.get('/experiment/(.+)', toolbox.networkFirst);
স্পিকার প্রোফাইল চিত্র
স্পিকার প্রোফাইল চিত্রগুলির জন্য, আমাদের লক্ষ্যটি ছিল কোনও প্রদত্ত স্পিকারের চিত্রের পূর্বে ক্যাশেড সংস্করণটি যদি এটি উপলব্ধ থাকে তবে চিত্রটি না থাকলে চিত্রটি পুনরুদ্ধার করতে নেটওয়ার্কে ফিরে পড়ে। যদি সেই নেটওয়ার্কের অনুরোধটি ব্যর্থ হয়, চূড়ান্ত ফ্যালব্যাক হিসাবে, আমরা একটি জেনেরিক স্থানধারক চিত্র ব্যবহার করেছি যা পূর্বনির্ধারিত ছিল (এবং তাই সর্বদা উপলব্ধ থাকবে)। জেনেরিক স্থানধারক দিয়ে প্রতিস্থাপন করা যেতে পারে এমন চিত্রগুলির সাথে ডিল করার সময় এটি ব্যবহার করার একটি সাধারণ কৌশল এবং sw-toolbox
cacheFirst
এবং cacheOnly
হ্যান্ডলারগুলি চেইন করে এটি প্রয়োগ করা সহজ ছিল।
var DEFAULT_PROFILE_IMAGE = 'images/touch/homescreen96.png';
function profileImageRequest(request) {
return toolbox.cacheFirst(request).catch(function() {
return toolbox.cacheOnly(new Request(DEFAULT_PROFILE_IMAGE));
});
}
toolbox.precache([DEFAULT_PROFILE_IMAGE]);
toolbox.router.get('/(.+)/images/speakers/(.*)',
profileImageRequest,
{origin: /.*\.googleapis\.com/});

ব্যবহারকারীদের সময়সূচীতে আপডেট
আইওয়া এর অন্যতম মূল বৈশিষ্ট্য স্বাক্ষরিত-ইন ব্যবহারকারীদের অংশ নেওয়ার পরিকল্পনা করা সেশনগুলির একটি সময়সূচী তৈরি এবং বজায় রাখতে অনুমতি দিচ্ছিল। আপনি যেমন আশা করেছিলেন, সেশন আপডেটগুলি ব্যাকএন্ড সার্ভারে এইচটিটিপি POST
অনুরোধগুলির মাধ্যমে করা হয়েছিল এবং ব্যবহারকারী অফলাইনে থাকাকালীন আমরা সেই রাজ্য-সংশোধনকারী অনুরোধগুলি পরিচালনা করার জন্য সেরা উপায়টি কাজ করার জন্য কিছুটা সময় ব্যয় করেছি। আমরা ইনডেক্সডিবিতে সারি করা ব্যর্থ অনুরোধগুলির সংমিশ্রণটি নিয়ে এসেছি, মূল ওয়েব পৃষ্ঠায় যুক্তির সাথে মিলিত হয়েছে যা সারি অনুরোধগুলির জন্য ইনডেক্সডডিবি পরীক্ষা করে এবং এটি যে কোনও খুঁজে পেয়েছে তা পুনরায় চেষ্টা করে।
var DB_NAME = 'shed-offline-session-updates';
function queueFailedSessionUpdateRequest(request) {
simpleDB.open(DB_NAME).then(function(db) {
db.set(request.url, request.method);
});
}
function handleSessionUpdateRequest(request) {
return global.fetch(request).then(function(response) {
if (response.status >= 500) {
return Response.error();
}
return response;
}).catch(function() {
queueFailedSessionUpdateRequest(request);
});
}
toolbox.router.put('/(.+)api/v1/user/schedule/(.+)',
handleSessionUpdateRequest);
toolbox.router.delete('/(.+)api/v1/user/schedule/(.+)',
handleSessionUpdateRequest);
যেহেতু পুনরায় চেষ্টাগুলি মূল পৃষ্ঠার প্রসঙ্গ থেকে তৈরি করা হয়েছিল, আমরা নিশ্চিত হতে পারি যে তারা ব্যবহারকারীর শংসাপত্রগুলির একটি নতুন সেট অন্তর্ভুক্ত করেছে। একবারে পুনরায় চেষ্টাগুলি সফল হয়ে গেলে, আমরা ব্যবহারকারীকে তাদের পূর্বে সারিবদ্ধ আপডেটগুলি প্রয়োগ করা হয়েছে তা জানাতে একটি বার্তা প্রদর্শন করেছি।
simpleDB.open(QUEUED_SESSION_UPDATES_DB_NAME).then(function(db) {
var replayPromises = [];
return db.forEach(function(url, method) {
var promise = IOWA.Request.xhrPromise(method, url, true).then(function() {
return db.delete(url).then(function() {
return true;
});
});
replayPromises.push(promise);
}).then(function() {
if (replayPromises.length) {
return Promise.all(replayPromises).then(function() {
IOWA.Elements.Toast.showMessage(
'My Schedule was updated with offline changes.');
});
}
});
}).catch(function() {
IOWA.Elements.Toast.showMessage(
'Offline changes could not be applied to My Schedule.');
});
অফলাইন গুগল অ্যানালিটিক্স
অনুরূপ শিরাতে, আমরা কোনও ব্যর্থ গুগল অ্যানালিটিক্স অনুরোধগুলি সারি করার জন্য একটি হ্যান্ডলার প্রয়োগ করেছি এবং যখন নেটওয়ার্কটি আশাবাদী উপলব্ধ ছিল তখন পরে সেগুলি পুনরায় খেলার চেষ্টা করেছিলাম। এই পদ্ধতির সাথে, অফলাইনে থাকার অর্থ গুগল অ্যানালিটিক্স অফারগুলি অন্তর্দৃষ্টি ত্যাগ করা নয়। আমরা প্রতিটি সারিবদ্ধ অনুরোধে qt
প্যারামিটার যুক্ত করেছি, অনুরোধটি প্রথম চেষ্টা করার পরে যে পরিমাণ সময় পেরিয়ে গেছে তার পরিমাণ নির্ধারণ করেছিলাম, এটি নিশ্চিত করার জন্য যে একটি উপযুক্ত ইভেন্টের অ্যাট্রিবিউশন সময় এটি গুগল অ্যানালিটিক্স ব্যাকএন্ডে তৈরি করেছে। গুগল অ্যানালিটিক্স আনুষ্ঠানিকভাবে কেবল 4 ঘন্টা অবধি qt
জন্য মানগুলিকে সমর্থন করে, তাই আমরা যত তাড়াতাড়ি সম্ভব এই অনুরোধগুলি পুনরায় খেলতে একটি সেরা-প্রচেষ্টা চেষ্টা করেছি, প্রতিবার পরিষেবা কর্মী শুরু করার সময়।
var DB_NAME = 'offline-analytics';
var EXPIRATION_TIME_DELTA = 86400000;
var ORIGIN = /https?:\/\/((www|ssl)\.)?google-analytics\.com/;
function replayQueuedAnalyticsRequests() {
simpleDB.open(DB_NAME).then(function(db) {
db.forEach(function(url, originalTimestamp) {
var timeDelta = Date.now() - originalTimestamp;
var replayUrl = url + '&qt=' + timeDelta;
fetch(replayUrl).then(function(response) {
if (response.status >= 500) {
return Response.error();
}
db.delete(url);
}).catch(function(error) {
if (timeDelta > EXPIRATION_TIME_DELTA) {
db.delete(url);
}
});
});
});
}
function queueFailedAnalyticsRequest(request) {
simpleDB.open(DB_NAME).then(function(db) {
db.set(request.url, Date.now());
});
}
function handleAnalyticsCollectionRequest(request) {
return global.fetch(request).then(function(response) {
if (response.status >= 500) {
return Response.error();
}
return response;
}).catch(function() {
queueFailedAnalyticsRequest(request);
});
}
toolbox.router.get('/collect',
handleAnalyticsCollectionRequest,
{origin: ORIGIN});
toolbox.router.get('/analytics.js',
toolbox.networkFirst,
{origin: ORIGIN});
replayQueuedAnalyticsRequests();
বিজ্ঞপ্তি অবতরণ পৃষ্ঠাগুলি ধাক্কা দিন
পরিষেবা কর্মীরা কেবল আইওয়ার অফলাইন কার্যকারিতা পরিচালনা করেননি - তারা তাদের বুকমার্কযুক্ত সেশনের আপডেটগুলি সম্পর্কে ব্যবহারকারীদের অবহিত করার জন্য আমরা যে ধাক্কা বিজ্ঞপ্তিগুলি ব্যবহার করেছি তাও চালিত করেছিল। এই বিজ্ঞপ্তিগুলির সাথে যুক্ত অবতরণ পৃষ্ঠাটি আপডেট হওয়া সেশনের বিশদটি প্রদর্শন করেছে। এই অবতরণ পৃষ্ঠাগুলি ইতিমধ্যে সামগ্রিক সাইটের অংশ হিসাবে ক্যাশে করা হচ্ছে, সুতরাং তারা ইতিমধ্যে অফলাইনে কাজ করেছে, তবে আমাদের নিশ্চিত করা দরকার যে সেই পৃষ্ঠায় সেশনের বিশদটি আপ টু ডেট ছিল, এমনকি অফলাইনে দেখা গেলেও। এটি করার জন্য, আমরা পূর্বে ক্যাশেড সেশন মেটাডেটাকে আপডেটগুলি দিয়ে সংশোধন করেছি যা পুশ বিজ্ঞপ্তিটিকে ট্রিগার করেছিল এবং আমরা ফলাফলটি ক্যাশে সংরক্ষণ করেছি। অনলাইনে বা অফলাইনে স্থান নেওয়া হোক না কেন, সেশন বিশদ পৃষ্ঠাটি খোলার পরের বার এই আপ-টু-ডেট তথ্যটি ব্যবহার করা হবে।
caches.open(toolbox.options.cacheName).then(function(cache) {
cache.match('api/v1/schedule').then(function(response) {
if (response) {
parseResponseJSON(response).then(function(schedule) {
sessions.forEach(function(session) {
schedule.sessions[session.id] = session;
});
cache.put('api/v1/schedule',
new Response(JSON.stringify(schedule)));
});
} else {
toolbox.cache('api/v1/schedule');
}
});
});
Gotchas এবং বিবেচনা
অবশ্যই, কয়েকটি গোটচাসে না গিয়ে আইওয়া স্কেলের কোনও প্রকল্পে কেউ কাজ করে না। আমরা যেগুলি দৌড়েছি তার কয়েকটি এখানে রয়েছে এবং আমরা কীভাবে তাদের চারপাশে কাজ করেছি।
বাসি বিষয়বস্তু
যখনই আপনি কোনও ক্যাচিংয়ের কৌশল পরিকল্পনা করছেন, পরিষেবা কর্মীদের মাধ্যমে বা স্ট্যান্ডার্ড ব্রাউজার ক্যাশে দিয়ে প্রয়োগ করা হোক না কেন, সর্বাধিক দ্রুত সংস্থানগুলি সরবরাহের তুলনায় যত তাড়াতাড়ি সম্ভব সংস্থান সরবরাহের মধ্যে একটি বাণিজ্য রয়েছে। sw-precache
মাধ্যমে, আমরা আমাদের অ্যাপ্লিকেশনটির শেলটির জন্য একটি আক্রমণাত্মক ক্যাশে-প্রথম কৌশল বাস্তবায়ন করেছি, যার অর্থ আমাদের পরিষেবা কর্মী পৃষ্ঠায় এইচটিএমএল, জাভাস্ক্রিপ্ট এবং সিএসএস ফিরিয়ে দেওয়ার আগে আপডেটের জন্য নেটওয়ার্কটি পরীক্ষা করবে না।
ভাগ্যক্রমে, আমরা পৃষ্ঠাটি ইতিমধ্যে লোড হওয়ার পরে নতুন সামগ্রী কখন উপলব্ধ ছিল তা সনাক্ত করতে আমরা পরিষেবা কর্মী লাইফসাইকেল ইভেন্টগুলির সুবিধা নিতে সক্ষম হয়েছি। যখন কোনও আপডেট করা পরিষেবা কর্মী সনাক্ত করা হয়, আমরা ব্যবহারকারীকে তাদের জানাতে একটি টোস্ট বার্তা প্রদর্শন করি যে তাদের নতুন সামগ্রীটি দেখতে তাদের পৃষ্ঠাটি পুনরায় লোড করা উচিত।
if (navigator.serviceWorker && navigator.serviceWorker.controller) {
navigator.serviceWorker.controller.onstatechange = function(e) {
if (e.target.state === 'redundant') {
var tapHandler = function() {
window.location.reload();
};
IOWA.Elements.Toast.showMessage(
'Tap here or refresh the page for the latest content.',
tapHandler);
}
};
}

স্থির বিষয়বস্তু স্থির কিনা তা নিশ্চিত করুন!
sw-precache
স্থানীয় ফাইলগুলির সামগ্রীগুলির একটি এমডি 5 হ্যাশ ব্যবহার করে এবং কেবলমাত্র এমন সংস্থানগুলি এনেছে যার হ্যাশ পরিবর্তিত হয়েছে। এর অর্থ হ'ল সংস্থানগুলি প্রায় অবিলম্বে পৃষ্ঠায় উপলভ্য, তবে এর অর্থ এটিও হ'ল একবার কিছু ক্যাশে হয়ে গেলে, এটি কোনও আপডেট হওয়া পরিষেবা কর্মী স্ক্রিপ্টে নতুন হ্যাশ বরাদ্দ না করা পর্যন্ত এটি ক্যাশে থাকতে চলেছে।
সম্মেলনের প্রতিটি দিনের জন্য লাইভস্ট্রিম ইউটিউব ভিডিও আইডিগুলি গতিশীলভাবে আপডেট করার প্রয়োজনের কারণে আমরা আই/ও চলাকালীন এই আচরণের সাথে একটি ইস্যুতে দৌড়েছি । যেহেতু অন্তর্নিহিত টেম্পলেট ফাইলটি স্থির ছিল এবং এটি পরিবর্তন হয়নি, আমাদের পরিষেবা কর্মী আপডেট প্রবাহটি ট্রিগার করা হয়নি এবং ইউটিউব ভিডিও আপডেট করার সাথে সার্ভারের কাছ থেকে গতিশীল প্রতিক্রিয়া হিসাবে বোঝানো হয়েছিল যা বেশ কয়েকটি ব্যবহারকারীর জন্য ক্যাশেড প্রতিক্রিয়া হিসাবে শেষ হয়েছিল।
আপনার ওয়েব অ্যাপ্লিকেশনটিকে কাঠামোগত করা হয়েছে তা নিশ্চিত করে আপনি এই ধরণের সমস্যাটি এড়াতে পারেন যাতে শেলটি সর্বদা স্থির থাকে এবং নিরাপদে পূর্বাভাস দেওয়া যায়, যখন শেলটি সংশোধন করে এমন কোনও গতিশীল সংস্থান স্বাধীনভাবে লোড হয়।
ক্যাশে-বস্ট আপনার পূর্বের অনুরোধগুলি
যখন sw-precache
সংস্থানগুলি প্রাকচাচের জন্য অনুরোধ করে, তখন এটি সেই প্রতিক্রিয়াগুলি অনির্দিষ্টকালের জন্য ব্যবহার করে যতক্ষণ না এটি মনে করে যে ফাইলটির জন্য এমডি 5 হ্যাশ পরিবর্তন হয়নি। এর অর্থ হ'ল এটি নিশ্চিত করা বিশেষভাবে গুরুত্বপূর্ণ যে প্রাক্যাচিং অনুরোধের প্রতিক্রিয়াটি একটি নতুন, এবং ব্রাউজারের এইচটিটিপি ক্যাশে থেকে ফিরে আসেনি। (হ্যাঁ, fetch()
কোনও পরিষেবা কর্মী করা অনুরোধগুলি ব্রাউজারের এইচটিটিপি ক্যাশে থেকে ডেটা দিয়ে প্রতিক্রিয়া জানাতে পারে))
আমরা যে প্রতিক্রিয়াগুলি প্রাকচারগুলি সরাসরি নেটওয়ার্ক থেকে এসেছি তা নিশ্চিত করার জন্য, ব্রাউজারের এইচটিটিপি ক্যাশে নয়, sw-precache
স্বয়ংক্রিয়ভাবে এটি প্রতিটি ইউআরএল অনুরোধ করে একটি ক্যাশে-বস্টিং ক্যোয়ারী প্যারামিটার যুক্ত করে । আপনি যদি sw-precache
ব্যবহার না করে থাকেন এবং আপনি ক্যাশে-প্রথম প্রতিক্রিয়া কৌশলটি ব্যবহার করছেন, তবে নিশ্চিত হয়ে নিন যে আপনি নিজের কোডে অনুরূপ কিছু করেছেন !
ক্যাশে-বস্টিংয়ের একটি ক্লিনার সমাধান হ'ল reload
জন্য ব্যবহৃত প্রতিটি Request
ক্যাশে মোড সেট করা, যা নিশ্চিত করবে যে প্রতিক্রিয়াটি নেটওয়ার্ক থেকে এসেছে। যাইহোক, এই লেখার হিসাবে, ক্যাশে মোড বিকল্পটি ক্রোমে সমর্থিত নয় ।
লগ ইন এবং আউট জন্য সমর্থন
আইওয়া ব্যবহারকারীদের তাদের গুগল অ্যাকাউন্টগুলি ব্যবহার করে লগ ইন করতে এবং তাদের কাস্টমাইজড ইভেন্টের সময়সূচী আপডেট করার অনুমতি দেয় তবে এর অর্থ হ'ল ব্যবহারকারীরা পরে লগ আউট করতে পারেন। ব্যক্তিগতকৃত প্রতিক্রিয়া ডেটা ক্যাশে করা স্পষ্টতই একটি জটিল বিষয়, এবং সর্বদা একটি সঠিক পদ্ধতির থাকে না।
আপনার ব্যক্তিগত সময়সূচীটি দেখার পরে, এমনকি যখন অফলাইনে, আইওয়া অভিজ্ঞতার মূল ছিল, আমরা সিদ্ধান্ত নিয়েছি যে ক্যাশেড ডেটা ব্যবহার করা উপযুক্ত। যখন কোনও ব্যবহারকারী সাইন আউট করে, আমরা পূর্বে ক্যাশেড সেশন ডেটা সাফ করার বিষয়টি নিশ্চিত করেছিলাম।
self.addEventListener('message', function(event) {
if (event.data === 'clear-cached-user-data') {
caches.open(toolbox.options.cacheName).then(function(cache) {
cache.keys().then(function(requests) {
return requests.filter(function(request) {
return request.url.indexOf('api/v1/user/') !== -1;
});
}).then(function(userDataRequests) {
userDataRequests.forEach(function(userDataRequest) {
cache.delete(userDataRequest);
});
});
});
}
});
অতিরিক্ত ক্যোয়ারী প্যারামিটারগুলির জন্য দেখুন!
যখন কোনও পরিষেবা কর্মী ক্যাশেড প্রতিক্রিয়ার জন্য পরীক্ষা করে, এটি কী হিসাবে একটি অনুরোধ ইউআরএল ব্যবহার করে। ডিফল্টরূপে, অনুরোধের ইউআরএলটি অবশ্যই ইউআরএল এর অনুসন্ধান অংশে কোনও ক্যোয়ারী প্যারামিটার সহ ক্যাশেড প্রতিক্রিয়া সঞ্চয় করতে ব্যবহৃত ইউআরএলটির সাথে হুবহু মেলে।
এটি বিকাশের সময় আমাদের জন্য একটি সমস্যা সৃষ্টি করে, যখন আমরা আমাদের ট্র্যাফিক কোথা থেকে আসছিল তা ট্র্যাক রাখতে ইউআরএল প্যারামিটারগুলি ব্যবহার শুরু করি। উদাহরণস্বরূপ, আমরা আমাদের বিজ্ঞপ্তিগুলির একটিতে ক্লিক করার সময় খোলা ইউআরএলগুলিতে utm_source=notification
প্যারামিটার যুক্ত করেছি এবং আমাদের ওয়েব অ্যাপ্লিকেশন ম্যানিফেস্টের start_url
utm_source=web_app_manifest
ব্যবহার করেছি। URLS যা পূর্বে ক্যাশেড প্রতিক্রিয়াগুলির সাথে মেলে তখন মিস হিসাবে আসছিল যখন এই পরামিতিগুলি যুক্ত করা হয়েছিল।
এটি আংশিকভাবে ignoreSearch
বিকল্প দ্বারা সম্বোধন করা হয়েছে যা Cache.match()
কল করার সময় ব্যবহার করা যেতে পারে। দুর্ভাগ্যক্রমে, ক্রোম এখনও ignoreSearch
সমর্থন করে না , এবং এটি যদি তা করে থাকে তবে এটি একটি সর্বশক্তিমান আচরণ নয়। আমাদের যা প্রয়োজন তা হ'ল কিছু ইউআরএল ক্যোয়ারী প্যারামিটারগুলি উপেক্ষা করার একটি উপায় ছিল যখন অন্যদের বিবেচনায় নেওয়া উচিত।
আমরা ক্যাশে ম্যাচটি পরীক্ষা করার আগে কিছু ক্যোয়ারী প্যারামিটারগুলি ছিনিয়ে নেওয়ার জন্য sw-precache
প্রসারিত করে শেষ করেছি এবং বিকাশকারীদের ignoreUrlParametersMatching
করার জন্য কোন প্যারামিটারগুলি উপেক্ষা করা হয় তা কাস্টমাইজ করার অনুমতি দেয়। এখানে অন্তর্নিহিত বাস্তবায়ন:
function stripIgnoredUrlParameters(originalUrl, ignoredRegexes) {
var url = new URL(originalUrl);
url.search = url.search.slice(1)
.split('&')
.map(function(kv) {
return kv.split('=');
})
.filter(function(kv) {
return ignoredRegexes.every(function(ignoredRegex) {
return !ignoredRegex.test(kv[0]);
});
})
.map(function(kv) {
return kv.join('=');
})
.join('&');
return url.toString();
}
হোয়াট দিস মিন্স ফর ইউ
গুগল আই/ও ওয়েব অ্যাপে পরিষেবা কর্মী সংহতকরণ সম্ভবত সবচেয়ে জটিল, বাস্তব-বিশ্বের ব্যবহার যা এই পর্যায়ে মোতায়েন করা হয়েছে। আমরা sw-precache
এবং sw-toolbox
তৈরি করা সরঞ্জামগুলির পাশাপাশি আমরা আপনার নিজস্ব ওয়েব অ্যাপ্লিকেশনগুলিকে শক্তিশালী করার জন্য যে কৌশলগুলি বর্ণনা করছি সেগুলি ব্যবহার করে আমরা ওয়েব বিকাশকারী সম্প্রদায়ের অপেক্ষায় রয়েছি। পরিষেবা কর্মীরা একটি প্রগতিশীল বর্ধন যা আপনি আজ ব্যবহার শুরু করতে পারেন এবং যখন সঠিকভাবে কাঠামোগত ওয়েব অ্যাপের অংশ হিসাবে ব্যবহার করা হয়, তখন আপনার ব্যবহারকারীদের জন্য গতি এবং অফলাইন সুবিধাগুলি উল্লেখযোগ্য।