Skip to content
Snippets Groups Projects
sw_plugin.js 3.28 KiB
Newer Older
tusooa's avatar
tusooa committed
import { fileURLToPath } from 'node:url'
import { dirname } from 'node:path'
import { readFile } from 'node:fs/promises'
import { build } from 'vite'
import { generateServiceWorkerMessages } from './service_worker_messages.js'

const projectRoot = dirname(dirname(fileURLToPath(import.meta.url)))

export const devSwPlugin = ({
  swSrc,
  swDest,
}) => {
  return {
    name: 'dev-sw-plugin',
    apply: 'serve',
    resolveId (id) {
      const name = id.startsWith('/') ? id.slice(1) : id
      if (name === swDest) {
        return swSrc
      }
      return null
    },
    async load (id) {
      if (id === swSrc) {
        return readFile(swSrc, 'utf-8')
      }
      return null
    },
    /**
     * vite does not bundle the service worker
     * during dev, and firefox does not support ESM as service worker
     * https://bugzilla.mozilla.org/show_bug.cgi?id=1360870
     */
    // async transform (code, id) {
    //   if (id === swSrc) {
    //     console.log('load virtual')
    //     const res = await build({
    //       entryPoints: [swSrc],
    //       bundle: true,
    //       write: false,
    //       outfile: 'sw-pleroma.js',
    //       alias: {
    //         'src': projectRoot + '/src',
    //       },
    //       define: {
    //         'import.meta.glob': 'require'
    //       }
    //     })
    //     console.log('res', res)
    //     const text = res.outputFiles[0].text
    //     console.log('text', text)
    //     return text
    //   }
    // }
  }
}

// Idea taken from
// https://github.com/vite-pwa/vite-plugin-pwa/blob/main/src/plugins/build.ts
// rollup does not support compiling to iife if we want to code-split;
// however, we must compile the service worker to iife because of browser support.
// Run another vite build just for the service worker targeting iife at
// the end of the build.
export const buildSwPlugin = ({
  swSrc,
  swDest,
}) => {
  let config
  return {
    name: 'build-sw-plugin',
    enforce: 'post',
    apply: 'build',
    configResolved (resolvedConfig) {
      config = {
        define: resolvedConfig.define,
        resolve: resolvedConfig.resolve,
        plugins: [swMessagesPlugin()],
        publicDir: false,
        build: {
          ...resolvedConfig.build,
          lib: {
            entry: swSrc,
            formats: ['iife'],
            name: 'sw_pleroma'
          },
          emptyOutDir: false,
          rollupOptions: {
            output: {
              entryFileNames: swDest
            }
          }
        },
        configFile: false
      }
    },
    closeBundle: {
      order: 'post',
      sequential: true,
      async handler () {
        console.log('Building service worker for production')
        await build(config)
      }
    }
  }
}

const swMessagesName = 'virtual:pleroma-fe/service_worker_messages'
const swMessagesNameResolved = '\0' + swMessagesName

export const swMessagesPlugin = () => {
  return {
    name: 'sw-messages-plugin',
    resolveId (id) {
      if (id === swMessagesName) {
        return swMessagesNameResolved
      } else {
        return null
      }
    },
    async load (id) {
      if (id === swMessagesNameResolved) {
        const messages = await generateServiceWorkerMessages()
        return `export default ${JSON.stringify(messages, undefined, 2)}`
      }
      return null
    }
  }
}