sw_plugin.js (4421B)
- import { fileURLToPath } from 'node:url'
- import { dirname, resolve } from 'node:path'
- import { readFile } from 'node:fs/promises'
- import { build } from 'vite'
- import * as esbuild from 'esbuild'
- import { generateServiceWorkerMessages, i18nFiles } from './service_worker_messages.js'
- const getSWMessagesAsText = async () => {
- const messages = await generateServiceWorkerMessages()
- return `export default ${JSON.stringify(messages, undefined, 2)}`
- }
- const projectRoot = dirname(dirname(fileURLToPath(import.meta.url)))
- export const devSwPlugin = ({
- swSrc,
- swDest,
- transformSW,
- alias
- }) => {
- const swFullSrc = resolve(projectRoot, swSrc)
- const esbuildAlias = {}
- Object.entries(alias).forEach(([source, dest]) => {
- esbuildAlias[source] = dest.startsWith('/') ? projectRoot + dest : dest
- })
- return {
- name: 'dev-sw-plugin',
- apply: 'serve',
- configResolved (conf) {
- },
- resolveId (id) {
- const name = id.startsWith('/') ? id.slice(1) : id
- if (name === swDest) {
- return swFullSrc
- }
- return null
- },
- async load (id) {
- if (id === swFullSrc) {
- return readFile(swFullSrc, '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 === swFullSrc && transformSW) {
- const res = await esbuild.build({
- entryPoints: [swSrc],
- bundle: true,
- write: false,
- outfile: 'sw-pleroma.js',
- alias: esbuildAlias,
- plugins: [{
- name: 'vite-like-root-resolve',
- setup (b) {
- b.onResolve(
- { filter: new RegExp(/^\//) },
- args => ({
- path: resolve(projectRoot, args.path.slice(1))
- })
- )
- }
- }, {
- name: 'sw-messages',
- setup (b) {
- b.onResolve(
- { filter: new RegExp('^' + swMessagesName + '$') },
- args => ({
- path: args.path,
- namespace: 'sw-messages'
- }))
- b.onLoad(
- { filter: /.*/, namespace: 'sw-messages' },
- async () => ({
- contents: await getSWMessagesAsText()
- }))
- }
- }]
- })
- const text = res.outputFiles[0].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) {
- Object.values(i18nFiles).forEach(f => {
- this.addWatchFile(f)
- })
- return swMessagesNameResolved
- } else {
- return null
- }
- },
- async load (id) {
- if (id === swMessagesNameResolved) {
- return await getSWMessagesAsText()
- }
- return null
- }
- }
- }