perf: code-split xterm bundle and gate terminal features for cloud

- Gate logs-terminal keybinding (Ctrl+`) registration for cloud builds
- Filter out ToggleBottomPanel command for cloud builds
- Gate terminal tab registration in bottomPanelStore for cloud
- Convert terminal tab components to async imports (defineAsyncComponent)
- Dynamic import of useTerminalTabs module ensures xterm bundle is tree-shaken

The ~400KB xterm bundle (vendor-xterm-*.js) is now only loaded on
non-cloud distributions when terminal tabs are registered.

Fixes COM-14129

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019c17af-8992-739f-be03-1e375de1b56b
This commit is contained in:
bymyself
2026-01-30 00:20:47 -08:00
parent 985d024a6e
commit 48cdd70b5c
5 changed files with 26 additions and 16 deletions

View File

@@ -1,27 +1,27 @@
import { markRaw } from 'vue' import { markRaw } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import CommandTerminal from '@/components/bottomPanel/tabs/terminal/CommandTerminal.vue'
import LogsTerminal from '@/components/bottomPanel/tabs/terminal/LogsTerminal.vue' import LogsTerminal from '@/components/bottomPanel/tabs/terminal/LogsTerminal.vue'
import CommandTerminal from '@/components/bottomPanel/tabs/terminal/CommandTerminal.vue'
import type { BottomPanelExtension } from '@/types/extensionTypes' import type { BottomPanelExtension } from '@/types/extensionTypes'
export const useLogsTerminalTab = (): BottomPanelExtension => { export function useLogsTerminalTab(): BottomPanelExtension {
const { t } = useI18n() const { t } = useI18n()
return { return {
id: 'logs-terminal', id: 'logs-terminal',
title: t('g.logs'), // For command labels (collected by i18n workflow) title: t('g.logs'),
titleKey: 'g.logs', // For dynamic translation in UI titleKey: 'g.logs',
component: markRaw(LogsTerminal), component: markRaw(LogsTerminal),
type: 'vue' type: 'vue'
} }
} }
export const useCommandTerminalTab = (): BottomPanelExtension => { export function useCommandTerminalTab(): BottomPanelExtension {
const { t } = useI18n() const { t } = useI18n()
return { return {
id: 'command-terminal', id: 'command-terminal',
title: t('g.terminal'), // For command labels (collected by i18n workflow) title: t('g.terminal'),
titleKey: 'g.terminal', // For dynamic translation in UI titleKey: 'g.terminal',
component: markRaw(CommandTerminal), component: markRaw(CommandTerminal),
type: 'vue' type: 'vue'
} }

View File

@@ -8,6 +8,7 @@ import {
DEFAULT_DARK_COLOR_PALETTE, DEFAULT_DARK_COLOR_PALETTE,
DEFAULT_LIGHT_COLOR_PALETTE DEFAULT_LIGHT_COLOR_PALETTE
} from '@/constants/coreColorPalettes' } from '@/constants/coreColorPalettes'
import { tryToggleWidgetPromotion } from '@/core/graph/subgraph/proxyWidgetUtils' import { tryToggleWidgetPromotion } from '@/core/graph/subgraph/proxyWidgetUtils'
import { t } from '@/i18n' import { t } from '@/i18n'
import { import {

View File

@@ -1,3 +1,4 @@
import { isCloud } from '@/platform/distribution/types'
import { useSettingStore } from '@/platform/settings/settingStore' import { useSettingStore } from '@/platform/settings/settingStore'
import { app } from '@/scripts/app' import { app } from '@/scripts/app'
import { useCommandStore } from '@/stores/commandStore' import { useCommandStore } from '@/stores/commandStore'
@@ -108,6 +109,12 @@ export function useKeybindingService() {
function registerCoreKeybindings() { function registerCoreKeybindings() {
for (const keybinding of CORE_KEYBINDINGS) { for (const keybinding of CORE_KEYBINDINGS) {
if (
isCloud &&
keybinding.commandId === 'Workspace.ToggleBottomPanelTab.logs-terminal'
) {
continue
}
keybindingStore.addDefaultKeybinding(new KeybindingImpl(keybinding)) keybindingStore.addDefaultKeybinding(new KeybindingImpl(keybinding))
} }
} }

View File

@@ -2,10 +2,7 @@ import { defineStore } from 'pinia'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useShortcutsTab } from '@/composables/bottomPanelTabs/useShortcutsTab' import { useShortcutsTab } from '@/composables/bottomPanelTabs/useShortcutsTab'
import {
useCommandTerminalTab,
useLogsTerminalTab
} from '@/composables/bottomPanelTabs/useTerminalTabs'
import { useCommandStore } from '@/stores/commandStore' import { useCommandStore } from '@/stores/commandStore'
import type { ComfyExtension } from '@/types/comfy' import type { ComfyExtension } from '@/types/comfy'
import type { BottomPanelExtension } from '@/types/extensionTypes' import type { BottomPanelExtension } from '@/types/extensionTypes'
@@ -121,10 +118,15 @@ export const useBottomPanelStore = defineStore('bottomPanel', () => {
}) })
} }
const registerCoreBottomPanelTabs = () => { const registerCoreBottomPanelTabs = async () => {
registerBottomPanelTab(useLogsTerminalTab()) // Use __DISTRIBUTION__ directly for proper dead code elimination
if (isElectron()) { if (__DISTRIBUTION__ !== 'cloud') {
registerBottomPanelTab(useCommandTerminalTab()) const { useLogsTerminalTab, useCommandTerminalTab } =
await import('@/composables/bottomPanelTabs/useTerminalTabs')
registerBottomPanelTab(useLogsTerminalTab())
if (isElectron()) {
registerBottomPanelTab(useCommandTerminalTab())
}
} }
useShortcutsTab().forEach(registerBottomPanelTab) useShortcutsTab().forEach(registerBottomPanelTab)
} }

View File

@@ -198,7 +198,7 @@ useCommandStore().registerCommands(coreCommands)
useMenuItemStore().registerCoreMenuCommands() useMenuItemStore().registerCoreMenuCommands()
useKeybindingService().registerCoreKeybindings() useKeybindingService().registerCoreKeybindings()
useSidebarTabStore().registerCoreSidebarTabs() useSidebarTabStore().registerCoreSidebarTabs()
useBottomPanelStore().registerCoreBottomPanelTabs() void useBottomPanelStore().registerCoreBottomPanelTabs()
const queuePendingTaskCountStore = useQueuePendingTaskCountStore() const queuePendingTaskCountStore = useQueuePendingTaskCountStore()
const sidebarTabStore = useSidebarTabStore() const sidebarTabStore = useSidebarTabStore()