mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-07 14:09:59 +00:00
refactor: parallelize bootstrap and simplify lifecycle with VueUse (#8307)
## Summary Refactors bootstrap and lifecycle management to parallelize initialization, use Vue best practices, and fix a logout state bug. ## Changes ### Bootstrap Store (`bootstrapStore.ts`) - Extract early bootstrap logic into a dedicated store using `useAsyncState` - Parallelize settings, i18n, and workflow sync loading (previously sequential) - Handle multi-user login scenarios by deferring settings/workflows until authenticated ### GraphCanvas Refactoring - Move non-DOM composables (`useGlobalLitegraph`, `useCopy`, `usePaste`, etc.) to script setup level for earlier initialization - Move `watch` and `whenever` declarations outside `onMounted` (Vue best practice) - Use `until()` from VueUse to await bootstrap store readiness instead of direct async calls ### GraphView Simplification - Replace manual `addEventListener`/`removeEventListener` with `useEventListener` - Replace `setInterval` with `useIntervalFn` for automatic cleanup - Move core command registration to script setup level ### Bug Fix Using `router.push()` for logout caused `isSettingsReady` to persist as `true`, making new users inherit the previous user's cached settings. Reverted to `window.location.reload()` with TODOs for future store reset implementation. ## Testing - Verified login/logout cycle clears settings correctly - Verified bootstrap sequence completes without errors --------- Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -93,7 +93,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useEventListener, whenever } from '@vueuse/core'
|
||||
import { until, useEventListener } from '@vueuse/core'
|
||||
import {
|
||||
computed,
|
||||
nextTick,
|
||||
@@ -129,7 +129,7 @@ import { useCopy } from '@/composables/useCopy'
|
||||
import { useGlobalLitegraph } from '@/composables/useGlobalLitegraph'
|
||||
import { usePaste } from '@/composables/usePaste'
|
||||
import { useVueFeatureFlags } from '@/composables/useVueFeatureFlags'
|
||||
import { mergeCustomNodesI18n, t } from '@/i18n'
|
||||
import { t } from '@/i18n'
|
||||
import { LiteGraph } from '@/lib/litegraph/src/litegraph'
|
||||
import { useLitegraphSettings } from '@/platform/settings/composables/useLitegraphSettings'
|
||||
import { CORE_SETTINGS } from '@/platform/settings/constants/coreSettings'
|
||||
@@ -144,12 +144,15 @@ import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteracti
|
||||
import TransformPane from '@/renderer/core/layout/transform/TransformPane.vue'
|
||||
import MiniMap from '@/renderer/extensions/minimap/MiniMap.vue'
|
||||
import LGraphNode from '@/renderer/extensions/vueNodes/components/LGraphNode.vue'
|
||||
import { UnauthorizedError, api } from '@/scripts/api'
|
||||
import { UnauthorizedError } from '@/scripts/api'
|
||||
import { app as comfyApp } from '@/scripts/app'
|
||||
import { ChangeTracker } from '@/scripts/changeTracker'
|
||||
import { IS_CONTROL_WIDGET, updateControlWidgetLabel } from '@/scripts/widgets'
|
||||
import { useColorPaletteService } from '@/services/colorPaletteService'
|
||||
import { newUserService } from '@/services/newUserService'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
import { useBootstrapStore } from '@/stores/bootstrapStore'
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
import { useExecutionStore } from '@/stores/executionStore'
|
||||
import { useNodeDefStore } from '@/stores/nodeDefStore'
|
||||
@@ -175,11 +178,16 @@ const settingStore = useSettingStore()
|
||||
const nodeDefStore = useNodeDefStore()
|
||||
const workspaceStore = useWorkspaceStore()
|
||||
const canvasStore = useCanvasStore()
|
||||
const workflowStore = useWorkflowStore()
|
||||
const executionStore = useExecutionStore()
|
||||
const toastStore = useToastStore()
|
||||
const colorPaletteStore = useColorPaletteStore()
|
||||
const colorPaletteService = useColorPaletteService()
|
||||
const canvasInteractions = useCanvasInteractions()
|
||||
const bootstrapStore = useBootstrapStore()
|
||||
const { isI18nReady, i18nError } = storeToRefs(bootstrapStore)
|
||||
const { isReady: isSettingsReady, error: settingsError } =
|
||||
storeToRefs(settingStore)
|
||||
|
||||
const betaMenuEnabled = computed(
|
||||
() => settingStore.get('Comfy.UseNewMenu') !== 'Disabled'
|
||||
@@ -386,15 +394,6 @@ useEventListener(
|
||||
{ passive: true }
|
||||
)
|
||||
|
||||
const loadCustomNodesI18n = async () => {
|
||||
try {
|
||||
const i18nData = await api.getCustomNodesI18n()
|
||||
mergeCustomNodesI18n(i18nData)
|
||||
} catch (error) {
|
||||
console.error('Failed to load custom nodes i18n', error)
|
||||
}
|
||||
}
|
||||
|
||||
const comfyAppReady = ref(false)
|
||||
const workflowPersistence = useWorkflowPersistence()
|
||||
const { flags } = useFeatureFlags()
|
||||
@@ -404,35 +403,72 @@ useCanvasDrop(canvasRef)
|
||||
useLitegraphSettings()
|
||||
useNodeBadge()
|
||||
|
||||
useGlobalLitegraph()
|
||||
useContextMenuTranslation()
|
||||
useCopy()
|
||||
usePaste()
|
||||
useWorkflowAutoSave()
|
||||
|
||||
// Start watching for locale change after the initial value is loaded.
|
||||
watch(
|
||||
() => settingStore.get('Comfy.Locale'),
|
||||
async (_newLocale, oldLocale) => {
|
||||
if (!oldLocale) return
|
||||
await Promise.all([
|
||||
until(() => isSettingsReady.value || !!settingsError.value).toBe(true),
|
||||
until(() => isI18nReady.value || !!i18nError.value).toBe(true)
|
||||
])
|
||||
if (settingsError.value || i18nError.value) {
|
||||
console.warn(
|
||||
'Somehow the Locale setting was changed while the settings or i18n had a setup error'
|
||||
)
|
||||
}
|
||||
await useCommandStore().execute('Comfy.RefreshNodeDefinitions')
|
||||
await useWorkflowService().reloadCurrentWorkflow()
|
||||
}
|
||||
)
|
||||
useEventListener(
|
||||
() => canvasStore.canvas?.canvas,
|
||||
'litegraph:set-graph',
|
||||
() => {
|
||||
workflowStore.updateActiveGraph()
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
useGlobalLitegraph()
|
||||
useContextMenuTranslation()
|
||||
useCopy()
|
||||
usePaste()
|
||||
useWorkflowAutoSave()
|
||||
useVueFeatureFlags()
|
||||
|
||||
comfyApp.vueAppReady = true
|
||||
|
||||
workspaceStore.spinner = true
|
||||
// ChangeTracker needs to be initialized before setup, as it will overwrite
|
||||
// some listeners of litegraph canvas.
|
||||
ChangeTracker.init()
|
||||
await loadCustomNodesI18n()
|
||||
try {
|
||||
await settingStore.loadSettingValues()
|
||||
} catch (error) {
|
||||
if (error instanceof UnauthorizedError) {
|
||||
|
||||
await until(() => isSettingsReady.value || !!settingsError.value).toBe(true)
|
||||
|
||||
if (settingsError.value) {
|
||||
if (settingsError.value instanceof UnauthorizedError) {
|
||||
localStorage.removeItem('Comfy.userId')
|
||||
localStorage.removeItem('Comfy.userName')
|
||||
window.location.reload()
|
||||
} else {
|
||||
throw error
|
||||
return
|
||||
}
|
||||
throw settingsError.value
|
||||
}
|
||||
|
||||
// Register core settings immediately after settings are ready
|
||||
CORE_SETTINGS.forEach(settingStore.addSetting)
|
||||
|
||||
await newUserService().initializeIfNewUser(settingStore)
|
||||
// Wait for both i18n and newUserService in parallel
|
||||
// (newUserService only needs settings, not i18n)
|
||||
await Promise.all([
|
||||
until(() => isI18nReady.value || !!i18nError.value).toBe(true),
|
||||
newUserService().initializeIfNewUser(settingStore)
|
||||
])
|
||||
if (i18nError.value) {
|
||||
console.warn(
|
||||
'[GraphCanvas] Failed to load custom nodes i18n:',
|
||||
i18nError.value
|
||||
)
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
await comfyApp.setup(canvasRef.value)
|
||||
@@ -487,25 +523,6 @@ onMounted(async () => {
|
||||
const releaseStore = useReleaseStore()
|
||||
void releaseStore.initialize()
|
||||
|
||||
// Start watching for locale change after the initial value is loaded.
|
||||
watch(
|
||||
() => settingStore.get('Comfy.Locale'),
|
||||
async () => {
|
||||
await useCommandStore().execute('Comfy.RefreshNodeDefinitions')
|
||||
await useWorkflowService().reloadCurrentWorkflow()
|
||||
}
|
||||
)
|
||||
|
||||
whenever(
|
||||
() => useCanvasStore().canvas,
|
||||
(canvas) => {
|
||||
useEventListener(canvas.canvas, 'litegraph:set-graph', () => {
|
||||
useWorkflowStore().updateActiveGraph()
|
||||
})
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
emit('ready')
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user