vue.js - Laravel 10/Vue 3/Vite 4/Vuetify 3 项目中不必要的组件加载

标签 vue.js vuetify.js vite inertiajs

我正在使用 Laravel、Vue、Vite 和 Inertia。对于 UI,我使用 Vuetify,由于某种原因,当我加载页面时,我可以看到网络选项卡中有 500 多个请求,其中大多数正在加载一些我根本不需要的 Vuetify 组件。我怎样才能使它只加载应用程序中使用的组件?

这是我的 main.js 文件:

/* eslint-disable import/order */
import layoutsPlugin from '@/plugins/layouts'
import vuetify from '@/plugins/vuetify'
import VueToast from 'vue-toast-notification'
import 'vue-toast-notification/dist/theme-default.css'
import { createInertiaApp, Link } from '@inertiajs/vue3'
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers'
import { loadFonts } from '@/plugins/webfontloader'
import './../styles/@core/template/index.scss'
import '@styles/styles.scss'
import { createPinia } from 'pinia'
import { createApp } from 'vue'
import { ZiggyVue } from '../../vendor/tightenco/ziggy/dist/vue.m'
import 'sweetalert2/dist/sweetalert2.min.css'

loadFonts()
createInertiaApp({
    title: title => `${title}`,
    resolve: name => resolvePageComponent(`./pages/${name}.vue`, import.meta.glob('./pages/**/*.vue')),
    setup({ el, App, props, plugin }) {
        // eslint-disable-next-line vue/component-api-style
        const vueApp = createApp({ render: () => h(App, props) })

        vueApp.use(plugin)
            .use(ZiggyVue, Ziggy)
            .use(VueToast, {
                position: 'top',
                pauseOnHover: true,
            }).provide('toast', vueApp.config.globalProperties.$toast)
            .use(vuetify)
            .use(createPinia())
            .use(layoutsPlugin)
            .use(Link)
            .mount(el)
        
        return vueApp
    },
    progress: {
        color: '#4B5563',
    },
})

还有 vite.config.js:

import { fileURLToPath } from 'url'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import DefineOptions from 'unplugin-vue-define-options/vite'
import { defineConfig } from 'vite'
import Pages from 'vite-plugin-pages'
import Layouts from 'vite-plugin-vue-layouts'
import vuetify from 'vite-plugin-vuetify'
import laravel from 'laravel-vite-plugin'

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/js/main.js'],
            refresh: true,
        }),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
        }),
        vueJsx(),

        // https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin
        vuetify({
            styles: {
                configFile: 'resources/styles/variables/_vuetify.scss',
            },
        }),
        Pages({
            dirs: ['./resources/js/pages'],
        }),
        Layouts({
            layoutsDirs: './resources/js/layouts/',
        }),
        Components({
            dirs: ['resources/js/@core/components', 'resources/js/views/demos'],
            dts: true,
        }),
        AutoImport({
            eslintrc: {
                enabled: true,
                filepath: './.eslintrc-auto-import.json',
            },
            imports: ['vue', 'vue-router', '@vueuse/core', '@vueuse/math', 'pinia'],
            vueTemplate: true,
        }),
        DefineOptions(),
    ],
    define: { 'process.env': {} },
    resolve: {
        alias: {
            '@core-scss': fileURLToPath(new URL('./resources/styles/@core', import.meta.url)),
            '@': fileURLToPath(new URL('./resources/js', import.meta.url)),
            '@themeConfig': fileURLToPath(new URL('./themeConfig.js', import.meta.url)),
            '@core': fileURLToPath(new URL('./resources/js/@core', import.meta.url)),
            '@layouts': fileURLToPath(new URL('./resources/js/@layouts', import.meta.url)),
            '@images': fileURLToPath(new URL('./resources/images/', import.meta.url)),
            '@styles': fileURLToPath(new URL('./resources/styles/', import.meta.url)),
            '@configured-variables': fileURLToPath(new URL('./resources/styles/variables/_template.scss', import.meta.url)),
            '@axios': fileURLToPath(new URL('./resources/js/plugins/axios', import.meta.url)),
            '@validators': fileURLToPath(new URL('./resources/js/@core/utils/validators', import.meta.url)),
            'apexcharts': fileURLToPath(new URL('node_modules/apexcharts-clevision', import.meta.url)),
        },
    },
    build: {
        chunkSizeWarningLimit: 5000,
    },
    optimizeDeps: {
        exclude: ['vuetify'],
        entries: [
            './resources/js/**/*.vue',
        ],
    },
})

网络选项卡: enter image description here enter image description here

资源/js/plugins/vuetify/index.js:

import { createVuetify } from 'vuetify'
import { VBtn } from 'vuetify/components'
import defaults from './defaults'
import { icons } from './icons'
import theme from './theme'

// Styles
// eslint-disable-next-line import/no-unresolved
import '@core-scss/template/libs/vuetify/index.scss'
import 'vuetify/styles'

export default createVuetify({
    aliases: {
        IconBtn: VBtn,
    },
    defaults,
    icons,
    theme,
})

defaults.js:

export default {
    IconBtn: {
        icon: true,
        size: 'small',
        color: 'default',
        variant: 'text',
        VIcon: {
            size: 24,
        },
    },
    VAlert: {
        density: 'comfortable',
        VBtn: {
            color: undefined,
        },
    },
    VAvatar: {
    // ℹ️ Remove after next release
        variant: 'flat',
    },
    VBadge: {
    // set v-badge default color to primary
        color: 'primary',
    },
    VBtn: {
    // set v-btn default color to primary
        color: 'primary',
    },
    VChip: {
        elevation: 0,
    },
    VPagination: {
        activeColor: 'primary',
        density: 'comfortable',
        size: '32',
    },
    VTabs: {
    // set v-tabs default color to primary
        color: 'primary',
        VSlideGroup: {
            showArrows: true,
        },
    },
    VTooltip: {
    // set v-tooltip default location to top
        location: 'top',
    },
    VList: {
        VListItem: {
            activeColor: 'primary',
        },
    },
    VCheckbox: {
    // set v-checkbox default color to primary
        color: 'primary',
        density: 'comfortable',
        hideDetails: 'auto',
    },
    VRadioGroup: {
        color: 'primary',
        hideDetails: 'auto',
    },
    VRadio: {
        hideDetails: 'auto',
    },
    VSelect: {
        variant: 'outlined',
        color: 'primary',
        hideDetails: 'auto',
    },
    VRangeSlider: {
    // set v-range-slider default color to primary
        color: 'primary',
        density: 'comfortable',
        thumbLabel: true,
        hideDetails: 'auto',
    },
    VRating: {
    // set v-rating default color to primary
        density: 'compact',
        activeColor: 'warning',
    },
    VProgressCircular: {
    // set v-progress-circular default color to primary
        color: 'primary',
    },
    VSlider: {
    // set v-slider default color to primary
        color: 'primary',
        hideDetails: 'auto',
    },
    VTextField: {
        variant: 'outlined',
        color: 'primary',
        hideDetails: 'auto',
    },
    VAutocomplete: {
        variant: 'outlined',
        density: 'comfortable',
        color: 'primary',
        hideDetails: 'auto',
    },
    VCombobox: {
        variant: 'outlined',
        color: 'primary',
        hideDetails: 'auto',
    },
    VFileInput: {
        variant: 'outlined',
        color: 'primary',
        hideDetails: 'auto',
    },
    VTextarea: {
        variant: 'outlined',
        density: 'comfortable',
        color: 'primary',
        hideDetails: 'auto',
    },
    VSwitch: {
    // set v-switch default color to primary
        color: 'primary',
        hideDetails: 'auto',
    },
}

最佳答案

resources/js/plugins/vuetify/index.js 中,通过 vuetify/components 导入 VBtn:

import { VBtn } from 'vuetify/components'

这会加载node_modules/vuetify/lib/components/index.mjs,它会导出所有 Vuetify 组件。在为生产构建时,未使用的组件将通过摇树删除,但在运行开发服务器时不会。

当您直接从vuetify/components/VBtn加载VBtn时,其他文件将不再加载:

import { VBtn } from 'vuetify/components/VBtn'

documentation 中也对此进行了描述:

Although treeshaking is automatically applied during production builds, it is advantageous to import components by specifying their full path in development mode. For instance, using vuetify/components/VBtn instead of vuetify/components ensures that the compiler loads fewer components, thus optimizing performance.

关于vue.js - Laravel 10/Vue 3/Vite 4/Vuetify 3 项目中不必要的组件加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76765266/

相关文章:

vue.js - v-model 和子组件?

javascript - 如何在vue.js中显示富文本内容?

javascript - 如何在创建组件之前更改 VueJS 的 <slot> 内容

svelte - 如何在 svelte 中指定导出构建的 js 和 css 文件名

javascript - 在 Vue JS 中渲染 Markdown

typescript - 如何在 Vue 中异步加载 vuetify 下拉(v-select)项目

vue.js - 设置加载覆盖层的不透明度

reactjs - 为什么网站图标仅显示在根页面中?

vuejs3 - 调用本地API时vite自签名证书报错

javascript - 如何获取 Vuetify v-img 的 naturalSize?