likes
comments
collection
share

解决迁移到vite项目中的router组件动态加载问题

作者站长头像
站长
· 阅读数 86

解决迁移到vite项目中的router组件动态加载问题

问题描述

在迁移到vite项目后,使用component:()=>import(`/src/view/modules/${menu.component}\`.vue)的方式引入的路由组件在本地环境正常使用,但在打包后的线上环境中报错,页面跳转白页,提示Failed to fetch dynamically imported module

问题分析

线上环境的问题可能是由于Vite的构建方式与本地环境不同,导致动态导入的模块在构建过程中被错误处理。

解决过程

  1. 原来使用require的方式引入,vite不支持这种引入方式,所以改成import方式引入,但是发现只修改成import不能正常运行,通过与线上老项目对比发现router中component在console.log中不相同,于是修改动态引入的代码。
  2. 修改成component:()=>import()后发现在本地使用时正常,发布到线上会报Failed to fetch dynamically imported module,于是尝试修改component部分代码。
  3. 查阅Vite的文档,了解到Vite支持动态导入,但需要正确配置。
  4. 修改router组件的代码,尝试不同的导入方式。
  5. 尝试使用const componentPath = `../views/modules/${menu.component}.vue`; component:modules[componentPath]的方式

配置变更

  1. 修改router组件的代码,尝试使用component:modules[componentPath]的方式。

以下是package.jsonrouter.js的部分代码:

package.json

{
  "name": "your-project-name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "serve": "vite preview"
  },
  "dependencies": {
    "vue": "2.7.16",
    "vue-router": "3.0.1"
  },
  "devDependencies": {
    "@vitejs/plugin-vue2": "2.3.1",
    "@vitejs/plugin-vue2-jsx": "1.1.1",
    "vite": "^5.2.8",
    "vue-template-compiler": "2.7.16"
  }
}

router.js

//原代码
    //import-production.js  
    // module.exports = file => () => import('@/views/' + file + '.vue')

// const _import = require("./import-" + process.env.NODE_ENV);  

//修改后代码
let modules = import.meta.glob('../views/modules/**/**/*.vue')
console.log("🚀 ~ modules:", modules)
// ... (省略了部分代码)
// 添加动态(菜单)路由
function addDyRoute(menuList = [], routes = []) {
  // 初始化一个空数组用于存储菜单列表
  let menus = []
  // 遍历菜单列表
  menuList.forEach((menu, index) => {
    // 如果菜单有子菜单,则将子菜单合并到menus数组中
    if (menu.children && menu.children.length > 0) menus = [...menus, ...menu.children]
    // 如果菜单没有子菜单,则处理当前菜单项
    else {
      // 为当前菜单生成唯一的menuKey
      let key = utils.guid()
      menu = Object.assign(menu, {
        menuKey: key
      });
      let route = {};
      // 克隆当前菜单项,为其添加meta信息
      route = JSON.parse(JSON.stringify(menu))
      let meta = {
        menuKey: key,
        // ... (省略了部分meta信息)
      }
      if (route.meta) Object.assign(route.meta, meta)
      else Object.assign(route, meta)
      // 如果菜单有组件并且不是布局组件且不是URL,则尝试动态引入组件
      if (menu.component && menu.component.toLowerCase() !== 'layout' && !isURL(menu.path)) {
        try {
          //原代码
          // route["component"] = _import(`@/views/modules/${menu.component}`.vue) || null;
          
          const componentPath = `../views/modules/${menu.component}.vue`;
          route = {
            ...route,
            //本地好使,线上报错的版本
            // component:()=>import(`@/views/modules/${menu.component}`.vue) 
            //修改后代码
            component:modules[componentPath]
          }
        } catch (e) {
          route["component"] =  null;
        }
      } else if (isURL(menu.path)) {
        // route["path"] = `i-${menu.menuKey}`;
        // route["name"] = `i-${menu.menuKey}`;
        // 将处理后的菜单项添加到routes数组中
        route["meta"]["iframeUrl"] = menu.path;
      }
      routes.push(route)
    }
  })
  // 如果menus数组中有子菜单,则递归调用addDyRoute函数
  if (menus.length > 0) addDyRoute(menus, routes)
  // 如果menus数组中没有子菜单,则处理最终的routes数组
  else {
    // ...
  }
}


router.beforeEach(async (to, from, next) => {
  NProgress.start();
  // ...
   api_menu.getMenus({
        user_id: 1
      }).then(res => {
        console.log('路由列表', res);
        if (res.data.code === 200) {
          let menuList = res.data.data
          // 动态加载路由
          addDyRoute(menuList)
          router.options.isAddDynamicMenuRoutes = true
          sessionStorage.setItem('menuList', JSON.stringify(menuList || '[]'))
          sessionStorage.setItem('permissions', '[]')
          next({
            ...to,
            replace: true
          })
        }
      })
      //...
})

结果

在修改代码和配置后,线上环境的问题得到解决,页面可以正常跳转。

经验教训

  • 在迁移项目时,要注意新旧工具的差异,及时调整配置和代码。
  • 对于动态导入,要确保正确配置和代码实现,以避免线上环境的问题。
  • 在遇到问题时,要及时查阅官方文档和社区讨论,以便快速找到解决方案。

转载自:https://juejin.cn/post/7379792320156352552
评论
请登录