From d2ef57bcfa362f4be18fa187bbf4949386618103 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Sat, 14 Jan 2023 10:55:09 +0100 Subject: [PATCH] perf: cache userSettings, improve #1013 --- composables/users.ts | 42 ++++++++++++++++++++--------- error.vue | 3 +++ plugins/setup-head-script.server.ts | 8 +++--- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/composables/users.ts b/composables/users.ts index c68d90d2..2966979e 100644 --- a/composables/users.ts +++ b/composables/users.ts @@ -1,6 +1,6 @@ import { createClient, fetchV1Instance } from 'masto' import type { mastodon } from 'masto' -import type { Ref } from 'vue' +import type { EffectScope, Ref } from 'vue' import type { MaybeComputedRef, RemovableRef } from '@vueuse/core' import type { ElkMasto, UserLogin } from '~/types' import { @@ -266,18 +266,34 @@ export function checkLogin() { return true } +interface UseUserLocalStorageCache { + scope: EffectScope + value: Ref> +} + /** * Create reactive storage for the current user */ export function useUserLocalStorage(key: string, initial: () => T) { - const all = useLocalStorage>(key, {}, { deep: true }) - return computed(() => { - const id = currentUser.value?.account.id - ? currentUser.value.account.acct - : '[anonymous]' - all.value[id] = Object.assign(initial(), all.value[id] || {}) - return all.value[id] - }) + // @ts-expect-error bind value to the function + const map: Map = useUserLocalStorage._ = useUserLocalStorage._ || new Map() + + if (!map.has(key)) { + const scope = effectScope(true) + const value = scope.run(() => { + const all = useLocalStorage>(key, {}, { deep: true }) + return computed(() => { + const id = currentUser.value?.account.id + ? currentUser.value.account.acct + : '[anonymous]' + all.value[id] = Object.assign(initial(), all.value[id] || {}) + return all.value[id] + }) + }) + map.set(key, { scope, value: value! }) + } + + return map.get(key)!.value } /** @@ -290,10 +306,12 @@ export function clearUserLocalStorage(account?: mastodon.v1.Account) { return const id = `${account.acct}@${currentInstance.value?.uri || currentServer.value}` + // @ts-expect-error bind value to the function - ;(useUserLocalStorage._ as Map>> | undefined)?.forEach((storage) => { - if (storage.value[id]) - delete storage.value[id] + const cacheMap = useUserLocalStorage._ as Map | undefined + cacheMap?.forEach(({ value }) => { + if (value.value[id]) + delete value.value[id] }) } diff --git a/error.vue b/error.vue index 1e5aa429..84dc9ff1 100644 --- a/error.vue +++ b/error.vue @@ -11,6 +11,9 @@ const errorCodes: Record = { 404: 'Page not found', } +if (process.dev) + console.error(error) + const defaultMessage = 'Something went wrong' const message = error.message ?? errorCodes[error.statusCode!] ?? defaultMessage diff --git a/plugins/setup-head-script.server.ts b/plugins/setup-head-script.server.ts index 36cccad1..27962c07 100644 --- a/plugins/setup-head-script.server.ts +++ b/plugins/setup-head-script.server.ts @@ -11,15 +11,13 @@ export default defineNuxtPlugin(() => { innerHTML: ` ;(function() { const handle = localStorage.getItem('${STORAGE_KEY_CURRENT_USER_HANDLE}') - if (!handle) - return + if (!handle) { return } const allSettings = JSON.parse(localStorage.getItem('${STORAGE_KEY_SETTINGS}') || '{}') const settings = allSettings[handle] - if (!settings) - return + if (!settings) { return } const html = document.querySelector('html') - ${process.dev ? 'console.log(\'settings\', settings)' : ''} + ${process.dev ? 'console.log({ settings })' : ''} const { fontSize, language } = settings || {}