使用 ServiceWorker 拦截和重定向请求
Using ServiceWorker to intercept and redirect requests
我被要求创建一个服务工作者,它能够拦截请求并将它们重定向到存储的模拟数据。我以前从未做过这样的事情,所以我有点挣扎。当 testMode=true 添加到 URL 时,服务工作者被激活。我有 2 个文件要处理。这是我目前所拥有的:
TestMode.ts
class TestMode {
constructor() {
if (!this.isEnabled()) {
return;
}
if (!('serviceWorker' in navigator)) {
console.log('Browser does not support service workers');
return;
}
this.init();
}
private init(): void {
navigator.serviceWorker
.register('planner-worker/js/worker.min.js')
.then(this.handleRegistration)
.catch((error) => { throw new Error('Service Worker registration failed: ' + error.message); });
navigator.serviceWorker.addEventListener('message', event => {
// event is a MessageEvent object
console.log(`The service worker sent me a message: ${event.data}`);
});
navigator.serviceWorker.ready.then( registration => {
if (!registration.active) {
console.log('failed to communicate')
return;
}
registration.active.postMessage("Hi service worker");
});
}
private handleRegistration(registration: ServiceWorkerRegistration): void {
registration.update();
console.log('Registration successful, scope is:', registration.scope);
}
private isEnabled(): boolean {
return locationService.hasParam('testMode');
}
}
export default new TestMode();
serviceWorker.ts
const CACHE_NAME = 'mockData-cache';
const MOCK_DATA: Record<string, string> = {
'/units/all?availability=Active&roomTypeHandle=kitchens': 'mock-data/unitData.json',
'/frontal-ranges/kitchens?' : 'mock-data/kitchensData.json',
'/carcase-ranges/?availability=Active&roomTypeHandle=kitchens' : 'mock-data/carcaseRangesData.json'
};
self.addEventListener('install', event => {
console.log('Attempting to install service worker and cache static assets');
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
return cache.addAll(Object.values(MOCK_DATA));
})
);
});
self.addEventListener('activate', function(event) {
console.log('Claiming control');
return self.clients.claim();
});
self.addEventListener( "fetch", event => {
console.log('WORKER: Fetching', event.request);
});
我目前所做的工作,服务工作者已注册,模拟数据 json 文件存储在缓存中。
我不确定该怎么做是当发出某个请求时,service worker 将使用存储在缓存中的模拟数据。
例如,我怎样才能得到它,以便在为 /units/all?availability=Active&roomTypeHandle=kitchens 发出请求时,服务人员将重定向到 mock-data/unitData.json而不是在缓存中?
我希望我说得有道理,任何帮助将不胜感激,这对我来说是全新的。
处理传入请求和生成响应(来自缓存、网络或两者的某种组合)的逻辑需要在您的 fetch
event handler 中实现。
根据您的缓存内容和用例,我将如何构造您的 fetch
处理程序:
self.addEventListener('fetch', (event) => {
// Using a URL object will make routing easier.
const url = new URL(event.request.url);
const pathAndQuery = url.pathname + url.search;
if (pathAndQuery in MOCK_DATA) {
const cacheKey = MOCK_DATA[pathAndQuery];
event.respondWith(
caches.match(cacheKey, {
cacheName: CACHE_NAME,
})
);
}
// If pathAndQuery isn't in MOCK_DATA, then respondWith()
// won't be called, and the default network behavior will
// be used for this request.
});
您可以使用像 https://mswjs.io/ 这样的库来代替手写,但如果您决定自己动手,那是一般的想法。
我被要求创建一个服务工作者,它能够拦截请求并将它们重定向到存储的模拟数据。我以前从未做过这样的事情,所以我有点挣扎。当 testMode=true 添加到 URL 时,服务工作者被激活。我有 2 个文件要处理。这是我目前所拥有的:
TestMode.ts
class TestMode {
constructor() {
if (!this.isEnabled()) {
return;
}
if (!('serviceWorker' in navigator)) {
console.log('Browser does not support service workers');
return;
}
this.init();
}
private init(): void {
navigator.serviceWorker
.register('planner-worker/js/worker.min.js')
.then(this.handleRegistration)
.catch((error) => { throw new Error('Service Worker registration failed: ' + error.message); });
navigator.serviceWorker.addEventListener('message', event => {
// event is a MessageEvent object
console.log(`The service worker sent me a message: ${event.data}`);
});
navigator.serviceWorker.ready.then( registration => {
if (!registration.active) {
console.log('failed to communicate')
return;
}
registration.active.postMessage("Hi service worker");
});
}
private handleRegistration(registration: ServiceWorkerRegistration): void {
registration.update();
console.log('Registration successful, scope is:', registration.scope);
}
private isEnabled(): boolean {
return locationService.hasParam('testMode');
}
}
export default new TestMode();
serviceWorker.ts
const CACHE_NAME = 'mockData-cache';
const MOCK_DATA: Record<string, string> = {
'/units/all?availability=Active&roomTypeHandle=kitchens': 'mock-data/unitData.json',
'/frontal-ranges/kitchens?' : 'mock-data/kitchensData.json',
'/carcase-ranges/?availability=Active&roomTypeHandle=kitchens' : 'mock-data/carcaseRangesData.json'
};
self.addEventListener('install', event => {
console.log('Attempting to install service worker and cache static assets');
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
return cache.addAll(Object.values(MOCK_DATA));
})
);
});
self.addEventListener('activate', function(event) {
console.log('Claiming control');
return self.clients.claim();
});
self.addEventListener( "fetch", event => {
console.log('WORKER: Fetching', event.request);
});
我目前所做的工作,服务工作者已注册,模拟数据 json 文件存储在缓存中。
我不确定该怎么做是当发出某个请求时,service worker 将使用存储在缓存中的模拟数据。
例如,我怎样才能得到它,以便在为 /units/all?availability=Active&roomTypeHandle=kitchens 发出请求时,服务人员将重定向到 mock-data/unitData.json而不是在缓存中?
我希望我说得有道理,任何帮助将不胜感激,这对我来说是全新的。
处理传入请求和生成响应(来自缓存、网络或两者的某种组合)的逻辑需要在您的 fetch
event handler 中实现。
根据您的缓存内容和用例,我将如何构造您的 fetch
处理程序:
self.addEventListener('fetch', (event) => {
// Using a URL object will make routing easier.
const url = new URL(event.request.url);
const pathAndQuery = url.pathname + url.search;
if (pathAndQuery in MOCK_DATA) {
const cacheKey = MOCK_DATA[pathAndQuery];
event.respondWith(
caches.match(cacheKey, {
cacheName: CACHE_NAME,
})
);
}
// If pathAndQuery isn't in MOCK_DATA, then respondWith()
// won't be called, and the default network behavior will
// be used for this request.
});
您可以使用像 https://mswjs.io/ 这样的库来代替手写,但如果您决定自己动手,那是一般的想法。