随着Vue3、Vite2的正式版发布,越来越多的人开始使用这些新技术来提高开发效率了。最近在尝试使用Vue3、Vite2、element-plus、Typescript做个后台管理Demo,遇到根据后台数据生成菜单路由动态导入的问题。
以下是代码核心逻辑:
... // 生成路由数据, menus是获取后台菜单数据 const routes = generateRoutes(menus) // router.addRoute 在路由实例router上增加路由 router.addRoute({ name: 'main', path: '/main', component: () => import('../components/Main.vue'), meta: { name: '首页' }, children: routes }) ... // 生成main的子路由数据 function generateRoutes(menus: any[]) { let routes: any[] = [] menus.forEach((menu: any) => { routes.push({ name: menu.menuId, path: menu.menuUrl, component: () => import('../components/' + menu.componentPath + '.vue'), meta: { name: menu.menuName } }) return routes }) }
在本地开发测试过程中,点击菜单能正常访问到对应的页面,但是打包部署到服务器后,就出现动态导入的错误,如下图:
本地开发没有问题,是因为vite支持动态加载当前访问的页面,但在打包的时,vite会根据项目中import来打包文件,上面代码import('../components/' + menu.componentPath + '.vue'),由于是运行时才能知道对应页面,vite在打包时并不知道应该打包哪些对应的文件,所以就出现上面的错误。要解决这个问题,就需要提前把路由菜单对应的文件打包到项目当中。
vite2中提供了一个Glob 导入功能,匹配到的文件默认是懒加载的,通过动态导入实现,并会在构建时分离为独立的 chunk。
修改后的代码核心逻辑:
... // 生成路由数据, menus是获取后台菜单数据 const routes = generateRoutes(menus) // router.addRoute 在路由实例router上增加路由 router.addRoute({ name: 'main', path: '/main', component: () => import('../components/Main.vue'), meta: { name: '首页' }, children: routes }) ... // 使用Glob导入 let modules = import.meta.glob('../components/**/*.vue'); // 生成main的子路由数据 function generateRoutes(menus: any[]) { let routes: any[] = [] menus.forEach((menu: any) => { // routes.push({ name: menu.menuId, path: menu.menuUrl, component: () => import('../components/' + menu.componentPath + '.vue'), meta: { name: menu.menuName } }) // 使用Glob方式 routes.push({ name: menu.menuId, path: menu.menuUrl, component: modules['../components/' + menu.componentPath + '.vue'], meta: { name: menu.menuName } }) return routes }) }
使用Glob这种方式后,vite打包时,就会将路径对应的文件打包到项目中了,就解决了上面出现的那个错误。
import.meta.glob('../components/**/*.vue')将匹配../components/**/*.vue这个路径下所有的vue文件打包,会存在打包一些没必要打包的文件,可以通过修改路径表达式来限制打包哪些文件,比如:
../components/**/*list.vue 打包路径下文件名为list结束的vue文件
../components/**/(*list.vue|test.vue) 打包路径下文件名为list结束的vue文件以及test.vue文件