Closed xiaohanyu closed 2 months ago
We did a spike today and found that PWA service worker can mitigate this issue. By caching pdf.worker.js
with PWA's cache, the download time for pdf.worker.js
could be reduced from several hundreds ms to several ms.
Evidence:
Code skeleton looks something like this:
// eslint-disable-next-line no-undef
self.addEventListener('install', () => {
console.debug('service worker installed')
})
// eslint-disable-next-line no-undef
self.addEventListener('activate', () => {
console.debug('service worker activated')
})
// eslint-disable-next-line no-undef
self.addEventListener('fetch', function (e) {
const CACHE_NAME = 'cache-v1'
console.log('fetch', e.request.url)
e.respondWith(
(async function () {
// eslint-disable-next-line no-undef
const cachedResponse = await caches.match(e.request)
if (cachedResponse) {
console.log(
'return from cache for response with request.url: ',
e.request.url
)
return cachedResponse
}
const networkResponse = await fetch(e.request)
const hosts = ['https://unpkg.com']
if (hosts.some((host) => e.request.url.startsWith(host))) {
// Cloning the response is necessary because request and response
// streams can only be read once. In order to return the response to the
// browser and put it in the cache we have to clone it. So the original
// gets returned to the browser and the clone gets sent to the cache.
// They are each read once.
//
// This clone() happens before `return networkResponse`
const clonedResponse = networkResponse.clone()
e.waitUntil(
(async function () {
// eslint-disable-next-line no-undef
const cache = await caches.open(CACHE_NAME)
// This will be called after `return networkResponse`
// so make sure you already have the clone!
console.log('set new cache')
await cache.put(e.request, clonedResponse)
})()
)
}
return networkResponse
})()
)
})
Ref implementation:
As mentioned in above, we can mitigate the pain by adopting service worker to cache pdf.worker.min.js
and reduce the latency from several hundreds of ms to less than 10 ms, which could drastically improve the performance.
In the end I didn't use code shown in this comment, however, the problem of the original code is, by default it is pretty dangerous to cache a opaque response since it may lead to corrupted PWA app permanently.
Instead, I adopted serwist for generating a service worker file, and self hosted pdf.js (in order to make the request to pdf.worker.min.js
same origin, ah, non-opaque response to be service worker cache friendly).
So after all the optimization, the latency to download pdf.worker.min.js
is reduced to less than 5 ms, evidence:
For now, this should be enough for us.
Ideally, react-pdf-viewer's <Worker>
should not reload many times when fileUrl changed, I guess this need a fix to react-pdf-viewer, and react's memoize won't work here.
Description
PPResume use react-pdf-viewer for viewing PDF, however, it has a serious bug, when the encoded PDF (by base64) changed, it will re-init its worker and one of its dependency
pdf.worker.min.js
would be re-downloaded.In the whole session of resume composing,
pdf.worker.min.js
would be re-downloaded tens of hundreds of times, which is both bad for performance and bandwidth.Evidence:
[Optional] Possible Solutions
pdf.worker.min.js
in browser cache and avoid re-download because it doesn't changeAcceptance Criteria
pdf.worker.min.js
should be downloaded for only once from remote CDN and later download request should be cached from browser local cacheTodo list
NA