Merge branch 'optimize' into shigusegubu-themes3

This commit is contained in:
Henry Jameson 2026-06-02 23:53:30 +03:00
commit 23b6366d53
7 changed files with 182 additions and 36 deletions

View file

@ -1,9 +1,7 @@
import { readFile } from 'node:fs/promises' import { readFile } from 'node:fs/promises'
import { dirname, resolve } from 'node:path' import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url' import { fileURLToPath } from 'node:url'
import * as esbuild from 'esbuild'
import { build } from 'vite' import { build } from 'vite'
import { exactRegex } from '@rolldown/pluginutils'
import { import {
generateServiceWorkerMessages, generateServiceWorkerMessages,
@ -16,15 +14,18 @@ const getSWMessagesAsText = async () => {
} }
const projectRoot = dirname(dirname(fileURLToPath(import.meta.url))) const projectRoot = dirname(dirname(fileURLToPath(import.meta.url)))
const swEnvName = 'virtual:pleroma-fe/service_worker_env'
const swEnvNameResolved = '\0' + swEnvName
const getDevSwEnv = () => `self.serviceWorkerOption = { assets: [] };` const getDevSwEnv = () => `self.serviceWorkerOption = { assets: [] };`
const getProdSwEnv = ({ assets }) => const getProdSwEnv = ({ assets }) =>
`self.serviceWorkerOption = { assets: ${JSON.stringify(assets)} };` `self.serviceWorkerOption = { assets: ${JSON.stringify(assets)} };`
export const devSwPlugin = ({ swSrc, swDest }) => { export const devSwPlugin = ({ swSrc, swDest, transformSW, alias }) => {
const swFullSrc = resolve(projectRoot, swSrc) const swFullSrc = resolve(projectRoot, swSrc)
return { return {
name: 'dev-sw-plugin', apply: 'serve', name: 'dev-sw-plugin',
apply: 'serve',
configResolved() { configResolved() {
/* no-op */ /* no-op */
}, },
@ -32,35 +33,173 @@ export const devSwPlugin = ({ swSrc, swDest }) => {
const name = id.startsWith('/') ? id.slice(1) : id const name = id.startsWith('/') ? id.slice(1) : id
if (name === swDest) { if (name === swDest) {
return swFullSrc return swFullSrc
} else if (name === swEnvName) {
return swEnvNameResolved
} }
return null return null
}, },
async load(id) { async load(id) {
if (id === swFullSrc) { if (id === swFullSrc) {
return readFile(swFullSrc, 'utf-8') return readFile(swFullSrc, 'utf-8')
} else if (id === swEnvNameResolved) {
return getDevSwEnv()
}
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 build({
entryPoints: [swSrc],
bundle: true,
write: false,
outfile: 'sw-pleroma.js',
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(),
}),
)
},
},
{
name: 'sw-env',
setup(b) {
b.onResolve(
{ filter: new RegExp('^' + swEnvName + '$') },
(args) => ({
path: args.path,
namespace: 'sw-env',
}),
)
b.onLoad({ filter: /.*/, namespace: 'sw-env' }, () => ({
contents: getDevSwEnv(),
}))
},
},
],
})
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: true,
rolldownOptions: {
output: {
entryFileNames: swDest,
},
},
},
configFile: false,
}
},
generateBundle: {
order: 'post',
sequential: true,
async handler(_, bundle) {
const assets = Object.keys(bundle)
.filter((name) => !/\.map$/.test(name))
.map((name) => '/' + name)
config.plugins.push({
name: 'build-sw-env-plugin',
resolveId(id) {
if (id === swEnvName) {
return swEnvNameResolved
}
return null
},
load(id) {
if (id === swEnvNameResolved) {
return getProdSwEnv({ assets })
}
return null
},
})
},
},
closeBundle: {
order: 'post',
sequential: true,
async handler() {
console.info('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 return null
}, },
} }
} }
export const swMessagesPlugin = () => {
const swMessagesName = 'virtual:pleroma-fe/service_worker_messages'
const swMessagesNameResolved = '\0' + swMessagesName
return {
name: 'sw-messages-plugin',
resolveId: {
filter: { id: exactRegex(swMessagesName) },
handler() {
return swMessagesNameResolved
}
},
load: {
filter: { id: exactRegex(swMessagesNameResolved) },
async handler () {
return await getSWMessagesAsText()
}
},
}
}

View file

@ -66,6 +66,7 @@ const MobileNav = {
countExtraNotifications( countExtraNotifications(
this.$store, this.$store,
useMergedConfigStore().mergedConfig, useMergedConfigStore().mergedConfig,
useAnnouncementsStore().unreadAnnouncementCount,
) )
) )
}, },

View file

@ -115,6 +115,7 @@ const Notifications = {
return countExtraNotifications( return countExtraNotifications(
this.$store, this.$store,
useMergedConfigStore().mergedConfig, useMergedConfigStore().mergedConfig,
useAnnouncementsStore().unreadAnnouncementCount,
) )
}, },
unseenCountTitle() { unseenCountTitle() {

View file

@ -9,6 +9,7 @@ import {
maybeShowNotification, maybeShowNotification,
} from '../services/notification_utils/notification_utils.js' } from '../services/notification_utils/notification_utils.js'
import { useI18nStore } from 'src/stores/i18n.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useReportsStore } from 'src/stores/reports.js' import { useReportsStore } from 'src/stores/reports.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
@ -123,6 +124,7 @@ export const notifications = {
useMergedConfigStore().mergedConfig.notificationVisibility, useMergedConfigStore().mergedConfig.notificationVisibility,
Object.values(useSyncConfigStore().prefsStorage.simple.muteFilters), Object.values(useSyncConfigStore().prefsStorage.simple.muteFilters),
notification, notification,
useI18nStore().i18n,
) )
} else if (notification.seen) { } else if (notification.seen) {
state.idStore[notification.id].seen = true state.idStore[notification.id].seen = true

View file

@ -2,7 +2,6 @@ import { showDesktopNotification } from '../desktop_notification_utils/desktop_n
import { muteFilterHits } from '../status_parser/status_parser.js' import { muteFilterHits } from '../status_parser/status_parser.js'
import { useAnnouncementsStore } from 'src/stores/announcements.js' import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useI18nStore } from 'src/stores/i18n.js'
import FaviconService from 'src/services/favicon_service/favicon_service.js' import FaviconService from 'src/services/favicon_service/favicon_service.js'
@ -76,6 +75,7 @@ export const maybeShowNotification = (
notificationVisibility, notificationVisibility,
muteFilters, muteFilters,
notification, notification,
i18n,
) => { ) => {
const rootState = store.rootState || store.state const rootState = store.rootState || store.state
@ -89,7 +89,7 @@ export const maybeShowNotification = (
const notificationObject = prepareNotificationObject( const notificationObject = prepareNotificationObject(
notification, notification,
useI18nStore().i18n, i18n,
) )
showDesktopNotification(rootState, notificationObject) showDesktopNotification(rootState, notificationObject)
} }
@ -193,7 +193,7 @@ export const prepareNotificationObject = (notification, i18n) => {
return notifObj return notifObj
} }
export const countExtraNotifications = (store, mergedConfig) => { export const countExtraNotifications = (store, mergedConfig, unreadAnnouncementCount) => {
const rootGetters = store.rootGetters || store.getters const rootGetters = store.rootGetters || store.getters
if (!mergedConfig.showExtraNotifications) { if (!mergedConfig.showExtraNotifications) {
@ -205,7 +205,7 @@ export const countExtraNotifications = (store, mergedConfig) => {
? rootGetters.unreadChatCount ? rootGetters.unreadChatCount
: 0, : 0,
mergedConfig.showAnnouncementsInExtraNotifications mergedConfig.showAnnouncementsInExtraNotifications
? useAnnouncementsStore().unreadAnnouncementCount ? unreadAnnouncementCount
: 0, : 0,
mergedConfig.showFollowRequestsInExtraNotifications mergedConfig.showFollowRequestsInExtraNotifications
? rootGetters.followRequestCount ? rootGetters.followRequestCount

View file

@ -1,8 +1,9 @@
/* eslint-env serviceworker */ /* eslint-env serviceworker */
import 'virtual:pleroma-fe/service_worker_env'
import { createI18n } from 'vue-i18n' import { createI18n } from 'vue-i18n'
import { storage } from 'src/lib/storage.js'
import { INSTANCE_DEFAULT_CONFIG } from 'src/modules/default_config_state.js' import { INSTANCE_DEFAULT_CONFIG } from 'src/modules/default_config_state.js'
import { parseNotification } from 'src/services/entity_normalizer/entity_normalizer.service.js' import { parseNotification } from 'src/services/entity_normalizer/entity_normalizer.service.js'
import { prepareNotificationObject } from 'src/services/notification_utils/notification_utils.js' import { prepareNotificationObject } from 'src/services/notification_utils/notification_utils.js'
@ -33,7 +34,7 @@ function getWindowClients() {
} }
const setSettings = async () => { const setSettings = async () => {
const piniaState = await storage.getItem('pinia-local-sync_config') const piniaState = {}
const locale = piniaState.prefsStorage.simple.interfaceLanguage || 'en' const locale = piniaState.prefsStorage.simple.interfaceLanguage || 'en'
i18n.locale = locale i18n.locale = locale
const notificationsNativeArray = Object.entries( const notificationsNativeArray = Object.entries(

View file

@ -11,12 +11,12 @@ import { configDefaults } from 'vitest/config'
import { getCommitHash } from './build/commit_hash.js' import { getCommitHash } from './build/commit_hash.js'
import copyPlugin from './build/copy_plugin.js' import copyPlugin from './build/copy_plugin.js'
import emojisPlugin from './build/emojis_plugin.js' import emojisPlugin from './build/emojis_plugin.js'
import mswPlugin from './build/msw_plugin.js'
import { import {
buildSwPlugin,
devSwPlugin, devSwPlugin,
swMessagesPlugin, swMessagesPlugin,
} from './build/sw_plugin.js' } from './build/sw_plugin.js'
import { VitePWA } from 'vite-plugin-pwa'
const localConfigPath = '<projectRoot>/config/local.json' const localConfigPath = '<projectRoot>/config/local.json'
const normalizeTarget = (target) => { const normalizeTarget = (target) => {
@ -142,6 +142,9 @@ export default defineConfig(async ({ mode, command }) => {
// outDir: 'custom-dir', // optional, defaults to Vite's build.outDir // outDir: 'custom-dir', // optional, defaults to Vite's build.outDir
}, },
}), }),
devSwPlugin({ swSrc, swDest, transformSW, alias }),
buildSwPlugin({ swSrc, swDest }),
swMessagesPlugin(),
emojisPlugin(), emojisPlugin(),
copyPlugin({ copyPlugin({
inUrl: '/static/ruffle', inUrl: '/static/ruffle',
@ -160,8 +163,7 @@ export default defineConfig(async ({ mode, command }) => {
'node_modules/.cache/stylelintcache', 'node_modules/.cache/stylelintcache',
), ),
}), }),
swMessagesPlugin(), ...(mode === 'test' ? [mswPlugin()] : []),
devSwPlugin({ swSrc, swDest }),
], ],
optimizeDeps: { optimizeDeps: {
// For unknown reasons, during vitest, vite will re-optimize the following // For unknown reasons, during vitest, vite will re-optimize the following
@ -206,9 +208,9 @@ export default defineConfig(async ({ mode, command }) => {
devtools: {}, // enable devtools mode devtools: {}, // enable devtools mode
input: { input: {
main: 'index.html', main: 'index.html',
sw: 'src/sw.js',
}, },
output: { output: {
inlineDynamicImports: false,
entryFileNames(chunkInfo) { entryFileNames(chunkInfo) {
const id = chunkInfo.facadeModuleId const id = chunkInfo.facadeModuleId
if (id.endsWith(swSrc)) { if (id.endsWith(swSrc)) {