Explorar el Código

perf(frontend): code-split heavy components to improve LCP

Switch the inbounds-page modals, login page's theme switch, and the
Persian date picker to defineAsyncComponent. They're not needed on
first paint, so deferring them shrinks the initial bundle and lets
the LCP element render sooner.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
MHSanaei hace 10 horas
padre
commit
444b05cac9

+ 2 - 10
frontend/src/components/DateTimePicker.vue

@@ -1,17 +1,9 @@
 <script setup>
-import { computed } from 'vue';
+import { computed, defineAsyncComponent } from 'vue';
 import dayjs from 'dayjs';
-import PersianDatePicker from 'vue3-persian-datetime-picker';
 import { useDatepicker } from '@/composables/useDatepicker.js';
 
-// Drop-in replacement for <a-date-picker> that swaps to a real Jalali
-// calendar (vue3-persian-datetime-picker, backed by moment-jalaali)
-// when the panel's "Calendar Type" setting is `jalalian`.
-//
-// The v-model contract matches AD-Vue: the parent works with a dayjs
-// object (or null). For the persian picker we serialize to/from the
-// `YYYY-MM-DD HH:mm:ss` string it expects so callers don't need to
-// know which renderer is active.
+const PersianDatePicker = defineAsyncComponent(() => import('vue3-persian-datetime-picker'));
 
 const props = defineProps({
   value: { type: [Object, null], default: null },

+ 9 - 8
frontend/src/pages/inbounds/InboundsPage.vue

@@ -1,5 +1,5 @@
 <script setup>
-import { computed, onMounted, ref } from 'vue';
+import { computed, defineAsyncComponent, onMounted, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { Modal, message } from 'ant-design-vue';
 import {
@@ -18,16 +18,17 @@ import AppSidebar from '@/components/AppSidebar.vue';
 import CustomStatistic from '@/components/CustomStatistic.vue';
 import { useNodeList } from '@/composables/useNodeList.js';
 import InboundList from './InboundList.vue';
-import InboundFormModal from './InboundFormModal.vue';
-import ClientFormModal from './ClientFormModal.vue';
-import ClientBulkModal from './ClientBulkModal.vue';
-import InboundInfoModal from './InboundInfoModal.vue';
-import QrCodeModal from './QrCodeModal.vue';
-import TextModal from '@/components/TextModal.vue';
-import PromptModal from '@/components/PromptModal.vue';
 import { useInbounds } from './useInbounds.js';
 import { useWebSocket } from '@/composables/useWebSocket.js';
 
+const InboundFormModal = defineAsyncComponent(() => import('./InboundFormModal.vue'));
+const ClientFormModal = defineAsyncComponent(() => import('./ClientFormModal.vue'));
+const ClientBulkModal = defineAsyncComponent(() => import('./ClientBulkModal.vue'));
+const InboundInfoModal = defineAsyncComponent(() => import('./InboundInfoModal.vue'));
+const QrCodeModal = defineAsyncComponent(() => import('./QrCodeModal.vue'));
+const TextModal = defineAsyncComponent(() => import('@/components/TextModal.vue'));
+const PromptModal = defineAsyncComponent(() => import('@/components/PromptModal.vue'));
+
 const { t } = useI18n();
 
 const {

+ 3 - 2
frontend/src/pages/login/LoginPage.vue

@@ -1,5 +1,5 @@
 <script setup>
-import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
+import { computed, defineAsyncComponent, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { UserOutlined, LockOutlined, KeyOutlined, SettingOutlined } from '@ant-design/icons-vue';
 
@@ -9,7 +9,8 @@ import {
   currentTheme,
   theme as themeState,
 } from '@/composables/useTheme.js';
-import ThemeSwitchLogin from '@/components/ThemeSwitchLogin.vue';
+
+const ThemeSwitchLogin = defineAsyncComponent(() => import('@/components/ThemeSwitchLogin.vue'));
 
 const { t } = useI18n();