Laravel 9 + Vite 生产构建耗时过长问题求助
解决Laravel 9 + Vue 3 + Vuetify 3项目npm run build耗时过长问题
问题描述
我有一个基于Laravel 9、Vue 3和Vuetify 3的初期项目,npm run dev启动仅需几秒,但npm run build却耗时约30分钟。构建过程中会在单个步骤卡顿10-30秒,比如卡在transforming (856) node_modules/function-bind/implementation.js这一步。不想重新创建项目,希望将构建时间缩短至合理范围。
相关配置文件
vite.config.js
import { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; import vue from '@vitejs/plugin-vue'; export default defineConfig({ plugins: [ laravel({ input: 'resources/js/app.js', refresh: true, }), vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false, }, }, }), ], });
app.js
import './bootstrap'; import '../css/app.css'; // Default Scaffolding import {createApp, h} from 'vue'; import {createInertiaApp} from '@inertiajs/inertia-vue3'; import {InertiaProgress} from '@inertiajs/progress'; import {resolvePageComponent} from 'laravel-vite-plugin/inertia-helpers'; import {ZiggyVue} from '../../vendor/tightenco/ziggy/dist/vue.m'; // Vuetify import 'vuetify/styles' import {createVuetify} from 'vuetify' import * as components from 'vuetify/components' import * as directives from 'vuetify/directives' import {aliases, fa} from 'vuetify/iconsets/fa-svg' // Font Awesome import {library} from '@fortawesome/fontawesome-svg-core' import {faEnvelope, faKey, faBars, faMoneyBillTrendUp} from '@fortawesome/free-solid-svg-icons' import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome' import '@fortawesome/fontawesome-free/js/all' library.add(faEnvelope, faKey, faBars, faMoneyBillTrendUp) //Layouts import AuthLayout from './Layouts/AuthLayout.vue' const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel'; ////////////////////////////////////////////////////////////// DATEPICKER import Datepicker from '@vuepic/vue-datepicker'; import '@vuepic/vue-datepicker/dist/main.css' import colors from 'vuetify/lib/util/colors' const vuetify = createVuetify({ components, directives, theme: { themes: { light: { dark: false, colors: { primary: '#43A047', // #E53935 danger: colors.red.base } }, }, }, icons: { defaultSet: 'fa', aliases, sets: { fa, }, }, }) import Vue3EasyDataTable from 'vue3-easy-data-table'; import 'vue3-easy-data-table/dist/style.css'; // // const app = createApp(App); createInertiaApp({ title: (title) => `${title} - ${appName}`, // resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')), resolve: name => { const page = resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')) page.then((module) => { module.default.layout = module.default.layout || AuthLayout; }); return page; }, setup({el, app, props, plugin}) { return createApp({render: () => h(app, props)}) .use(plugin) .use(vuetify) .use(ZiggyVue, Ziggy) .component('font-awesome-icon', FontAwesomeIcon) .component('Datepicker', Datepicker) .component('EasyDataTable', Vue3EasyDataTable) .mount(el); }, }); InertiaProgress.init({color: '#4B5563'});
优化方案
1. 按需引入Vuetify组件和指令
当前代码全量导入Vuetify所有组件和指令,会大幅增加打包体积与构建时间。改为仅导入项目实际使用的组件:
// 替换原Vuetify导入部分 import { createVuetify } from 'vuetify' // 只导入用到的组件,示例: import { VBtn, VCard, VTextField, VLayout } from 'vuetify/components' // 只导入用到的指令,示例: import { VTooltip } from 'vuetify/directives' import 'vuetify/styles' const vuetify = createVuetify({ components: { VBtn, VCard, VTextField, VLayout }, directives: { VTooltip }, // 保留原有主题、图标配置 })
2. 清理Font Awesome冗余导入
同时导入@fortawesome/fontawesome-free/js/all和单个图标会导致重复加载,删除全量导入语句:
// 删除此行 // import '@fortawesome/fontawesome-free/js/all'
3. 启用Vite构建缓存
在vite.config.js中添加缓存配置,复用之前的构建结果:
export default defineConfig({ plugins: [/* 原有插件 */], cacheDir: './node_modules/.vite', build: { cache: true, // 可选:尝试使用terser压缩(需先安装:npm i terser -D) minify: 'terser' } })
4. 分析打包体积定位问题
使用rollup-plugin-visualizer分析打包后的依赖体积,找出大体积或冗余依赖:
# 安装分析插件 npm install rollup-plugin-visualizer -D
修改vite.config.js添加插件:
import { visualizer } from 'rollup-plugin-visualizer'; export default defineConfig({ plugins: [ laravel({/* 原有配置 */}), vue({/* 原有配置 */}), visualizer({ open: true }) // 构建后自动打开分析页面 ], })
运行npm run build后,会打开体积分析页面,针对性优化大体积依赖。
5. 优化Inertia页面解析逻辑
确保import.meta.glob仅匹配必要的页面文件,可添加eager: false明确延迟加载:
resolve: name => { const page = resolvePageComponent( `./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue', { eager: false }) ) page.then((module) => { module.default.layout = module.default.layout || AuthLayout; }); return page; },
内容的提问来源于stack exchange,提问作者Michael Erdmann
相关产品推荐
相关产品推荐

