- From: Arthur Stolyar <notifications@github.com>
- Date: Fri, 19 Aug 2016 15:41:38 -0700
- To: slightlyoff/ServiceWorker <ServiceWorker@noreply.github.com>
- Message-ID: <slightlyoff/ServiceWorker/issues/920/241153009@github.com>
_(My kind-of a proposal for this case, a bit rethinked/reworked)_ ## The `requests` This API is supposed to solve this issue and the race issue for `link=preload` https://github.com/slightlyoff/ServiceWorker/issues/959 ### Preflight First, here are some scetches of the _"pre-flight opt-in"_ which are based on what was writting here and decided on F2F meeting: ##### Registration, preflight is opt-in Each preflight request will have `Service-Worker-Preflight: something` header. ```js navigator.serviceWorker.register('/sw.js', { preflight: { // Preflight interval. Is it really needed? // There was some mentions that HTTP cached would solve this. // Will `Vary: Service-Worker-Preflight` on response work fine here? CDN? ttl: 1000 * 60 } }); ``` ##### Pre-flight data ```js // Naming not final of course self.registration.setPreflightProperties([ headers: { 'X-Status': 'Y' } ]).then(() => { console.log('Done'); }); ``` This is what is related to preflight, following API is for general use cases which may solve Facebook/Google Docs issue with ServiceWorker. ### API (_in TypeScript format, not spec format_) ```ts interface RequestsStorage { match(Request | string): Promise<Response>; putUntil(Request | string, Promise<Response>): void; } interface ServiceWorkerGlobalScope { readonly requests: RequestsStorage; } ``` * `RequestsStorage#putUntil`: Puts a request to the storage until `Promise<Response>` settled. _For the case of preflight, UA need to hold the request in the store until `fetch` event ends_ * `RequestsStorage#match`: Macthes passed request agains stored ones. Requests should be differentiated by `Service-Worker-Preflight` header too. ### Example The website. It wants to preflight requests and wants to handle them differently based on the requested page. It also sends `Link` preload headers for some pages. ```js self.addEventListener('fetch', event => { const request = event.request; const url = new URL(request.url); // Detect if it's a preflight request if (request.mode === 'navigate' && request.header.get('Service-Worker-Preflight')) { let result; // Note that self.request.match() should take into account // existence of Service-Worker-Preflight header // Case A: Construct the page on the fly (FB case) if (url.pathname === '/newsfeed') { result = self.requests.match(request).then(res => { // `res` returns dynamic data, the shell is cached. // Streaming rendering could be used here too return constructThePage(res); }); } // Case B: Simple race with response for simple page else if (url.pathname === '/about') { const fetching = fetchRequest(request); const result = Promise.race([ fetching, self.requests.match(request).catch(() => fetching) ]); } // Case C: Canceling huge **response** else if (url.pathname.endsWith('.mp4')) { self.requests.match(request).then(res => { res.body.cancel(); }); } event.respondWith(result); return; } // Handle normal and preload requests. They are going here too // and if page requests same preload assets which are now _ingligh_ // then the same request is reused. const result = self.requests.match(request).then(inflight => { return inflight || self.caches.match(request); }).then(res => { if (res) return res; return fetch(request).then(res => { if (res && res.ok) { putCache(request, res); } return res; }); }); event.respondWith(result); }); function fetchRequest(request) { return caches.match(request, { cacheName: 'cache' }).then(res => { if (res) return res; return fetch(request).then(res => { if (res && res.ok) { putCache(request, res); } return res; }); }); } function putCache(req, res) { return caches.open('cache').then(cache => { return cache.put(req, res); }); } ``` _____________________________ This is how I think it may work. I hope it isn't very stupud :-) -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/slightlyoff/ServiceWorker/issues/920#issuecomment-241153009
Received on Friday, 19 August 2016 22:42:07 UTC