Skip to content

Instantly share code, notes, and snippets.

@Jxck
Created May 19, 2020 01:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jxck/7b9ff7dc782d98803f3aa266d0a7ddc3 to your computer and use it in GitHub Desktop.
Save Jxck/7b9ff7dc782d98803f3aa266d0a7ddc3 to your computer and use it in GitHub Desktop.

some pain point for building podcast over pwa.

1. DOMParser from SW

sw can't access to DOM API it includes DOMParser API too. so it neccessary for import extra xml feed parser in sw. it reasonable for me that sw can't access to window dom tree but if DOMParser is indepened from tree, I wish I can use them.

in my case, I serve feed xml by myself, so I export json version of feed.

2. ArrayBuffer from

I wanna display some ID3 tag data in mp3. in that case i wanna get ArraBuffer from tag which load mp3 data. I mean something like

// <audio src=episode.mp3>
$('audio').addEventListener('load', (e) => {
  new ID3Parser(e.target.buffer)
})

but there are no such api so I need to do fetch by myself

const res = await fetch('episode.mp3')
const buffer = await res.arrayBuffer

new ID3Parser(buffer)

$('audio').src = createObjectURL(buffer)

but I basically wanna make <audio> to natively fetch with partial request with own header each browser intended to send.

so I pending this.

4. background fetch audio with page html

IIUC, background fetch need to call with total result byte size. if fetching new Audio mp3 with Shownote HTML,

const option = {
  title: 'new episode',
  downloadTotal: html.size + mp3.size
  icons: [{src: 'logo.png', sizes: '256x256', type: 'image/webp'}]
}
const registration = await navigator.serviceWorker.ready
const task = await registration.backgroundFetch.fetch(id, [html, mp3], option)

basically podcast feed includes mp3 size, but there are no html size.

in my case, I deligate html caching to sw like below.

// window
const controller = navigator.serviceWorker.controller
controller.postMessage({type: 'save', url: this.dataset.page})

// sw
self.addEventListener('message', async (e) => {
  const { type, url } = e.data;
  if (type === 'save') {
    const cache = await caches.open(SHOWNOTE)
    cache.add(url)
  }
})

I wonder if there are convenient way to do this.

I'll update if I remember.

@jeffposnick
Copy link

Re: #4, you can use the same Cache Storage API via window.caches as you do inside of a service worker. So I don't think you need to postMessage() to the service worker asking it to cache something. You can do it directly from your web app's window context.

https://googlechrome.github.io/samples/service-worker/window-caches/

@Jxck
Copy link
Author

Jxck commented May 20, 2020

@jeffposnick Ah thanks for pointing out. Yes It's correct, but in my code, SW only knows which Cache Name (means value for caches.open(Name)) is fit for save. so I pass it to sw.
so I should say in other words like, bgfetch with unknown length content will fit to this case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment