如何拆分Laravel+InertiaJS(VueJS)大文件,按需加载提升SPA性能?
实现InertiaJS(Vue)页面与组件的按需加载
1. 启用Inertia页面级代码分割
InertiaJS原生支持页面组件的按需加载,核心是把静态导入改成动态import,让打包工具自动拆分chunk:
原来的静态导入写法:
// app.js或routes.js import Dashboard from './Pages/Dashboard.vue'; import Users from './Pages/Users/Index.vue'; createInertiaApp({ resolve: (name) => { return require(`./Pages/${name}`).default; }, // ...其他配置 });
改成动态import方式:
createInertiaApp({ resolve: async (name) => { // 动态导入页面,自动生成独立chunk const page = await import(`./Pages/${name}.vue`); return page.default; }, // ...其他配置 });
这样每个页面会被打包成单独的chunk文件(如Dashboard.xxxx.js),只有用户访问对应页面时才会加载。
2. 组件级别按需加载
对于大型通用组件(比如数据表格、富文本编辑器),用Vue的defineAsyncComponent实现延迟加载:
<script setup> import { defineAsyncComponent } from 'vue'; // 仅当组件被渲染时才加载对应的chunk const DataTable = defineAsyncComponent(() => import('../Components/DataTable.vue')); const RichEditor = defineAsyncComponent(() => import('../Components/RichEditor.vue')); </script> <template> <DataTable v-if="showTable" /> <RichEditor v-if="showEditor" /> </template>
3. 拆分CSS文件(避免单个styles.css过大)
针对Vite(Laravel 9+默认)
在vite.config.js中配置CSS代码分割与chunk规则:
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, }, }, }), ], build: { rollupOptions: { output: { manualChunks(id) { // 把node_modules依赖拆到单独vendor chunk if (id.includes('node_modules')) { return id.toString().split('node_modules/')[1].split('/')[0].toString(); } // 把Pages目录下的文件拆成独立页面chunk if (id.includes('resources/js/Pages')) { const pathParts = id.split('resources/js/Pages/')[1]; return `page-${pathParts.split('.')[0]}`; } }, assetFileNames: (assetInfo) => { if (assetInfo.name.endsWith('.css')) { return `css/[name].[hash].css`; } return `assets/[name].[hash][extname]`; }, }, }, cssCodeSplit: true, // 启用CSS按chunk拆分 }, });
针对Laravel Mix(旧版本Laravel)
在webpack.mix.js中配置:
const mix = require('laravel-mix'); mix.js('resources/js/app.js', 'public/js') .vue() .webpackConfig({ output: { chunkFilename: 'js/[name].[chunkhash].js', }, optimization: { splitChunks: { chunks: 'all', cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendor', chunks: 'all', }, pages: { test: /[\\/]Pages[\\/]/, name: 'pages', chunks: 'all', enforce: true, }, }, }, }, }) .options({ extractStyles: true, // 拆分CSS到独立文件 processCssUrls: false, });
4. 可选优化:预加载常用页面
在控制器中用Inertia::preload()指定用户可能访问的下一个页面,提前加载对应chunk:
return Inertia::render('Dashboard') ->preload(['Users/Index', 'Settings/Profile']);
5. 验证效果
运行npm run build后,查看public/js和public/css目录,会生成多个带hash的chunk文件(如page-Dashboard.xxxx.js、css/page-Dashboard.xxxx.css)。访问不同页面时,浏览器只会加载对应页面的chunk,而非一次性加载所有代码。
内容的提问来源于stack exchange,提问作者viking
相关产品推荐
相关产品推荐

