vue-element-admin icon indicating copy to clipboard operation
vue-element-admin copied to clipboard

动态路由如何实现懒加载?

Open kimmy-wang opened this issue 4 years ago • 43 comments

Question(提问)

  1. 动态路由如何实现懒加载?
  2. 有没有现成的解决方案?
  3. 如果没有的话,是不是可以通过编写webpack插件实现?
思路: 在某个生命周期之前从数据库获取路由的信息,生成路由的静态配置文件,然后再执行正常编译打包流程。

kimmy-wang avatar Sep 23 '19 01:09 kimmy-wang

src\permission.js router.addRoutes(accessRoutes) 权限这里其实就是动态的加载路由的,不过封装了方法而已。具体可以多看看官方文档以及作者的权限思路,其实路由里面 roles 字段 ['admin', 'editor'],会给人一些误会,觉得这里只能静态的配置权限,其实不是的。这里完全可以根据模块名称设置为['shopList']、['itemList']、['ArticleList']... 注意 src\permission.js 中的 const { roles } = await store.dispatch('user/getInfo')这里一样是个数组,可以动态传入菜单全选比如['shopList', 'itemList']这样就不会有ArticleList的权限了 值得一提的是 admin 默认有所有页面权限,具体多仔细看看,作者在权限这块其实写的很灵活的

mayunhai avatar Sep 23 '19 07:09 mayunhai

// 路由懒加载 export const loadView = (view) => { return () => import(@/views/${view}) }

yutaolian avatar Sep 26 '19 02:09 yutaolian

我问的是动态路由如何实现懒加载?

kimmy-wang avatar Sep 29 '19 02:09 kimmy-wang

同问

xlb avatar Oct 24 '19 01:10 xlb

`export const formatRoutes = (aMenu) => { const aRouter = [] aMenu.forEach(oMenu => { const { path, component, name, icon, children, num } = oMenu

if (!validatenull(component)) {
  const componentPath = component

  const Other = () => import(`../${componentPath}.vue`)
  const oRouter = {
    path: path,
    component: Other,
    name: num || name,
    meta: {
      // 需要被缓存
      noCache: false,
      icon: icon,
      title: name
    },
    redirect: validatenull(children) ? null : 'noredirect',
    icon: icon,
    children: validatenull(children) ? [] : formatRoutes(children)
  }

  aRouter.push(oRouter)
}

})

return aRouter }` 可以参考下

xlb avatar Oct 24 '19 01:10 xlb

@xlb 动态路由能实现代码分割吗?

kimmy-wang avatar Oct 24 '19 04:10 kimmy-wang

@upcwangying 可以的,我正好也是做动态路由的代码分割

xlb avatar Oct 24 '19 08:10 xlb

@upcwangying 成了吗,刚好我也想分割,我打包后,页面都在一个js里

iceMilkAndSugar avatar Oct 31 '19 03:10 iceMilkAndSugar

@xlb webpack打包时,动态路由没有包含进去

kimmy-wang avatar Dec 19 '19 10:12 kimmy-wang

// 路由懒加载 export const loadView = (view) => { return () => import(@/views/${view}) }

不知道为何使用这句代码的时候,eslint报这个错,TypeError: Cannot read property 'range' of null

shanzhaozhen avatar Jan 21 '20 08:01 shanzhaozhen

我也遇到了这个问题,依赖库版本升级就搞定了

kimmy-wang avatar Jan 23 '20 07:01 kimmy-wang

我也遇到了这个问题,依赖库版本升级就搞定了

怎么升级依赖库的,我使用 ncu -u 升级了全部依赖包依然有这个问题

shanzhaozhen avatar Jan 27 '20 09:01 shanzhaozhen

vue-element-admin >4.2.1版 同问 Module build failed (from ./node_modules/eslint-loader/index.js): TypeError: Cannot read property 'range' of null 大佬怎么解决 @shanzhaozhen @upcwangying

lovlyhao avatar Mar 11 '20 13:03 lovlyhao

vue-element-admin >4.2.1版 同问 Module build failed (from ./node_modules/eslint-loader/index.js): TypeError: Cannot read property 'range' of null 大佬怎么解决 @shanzhaozhen @upcwangying

对我来说,有效,.eslintrc.js添加配置

rules: [
   "indent": [
      "error",
      2,
      {
        'SwitchCase': 1,
        "ignoredNodes": [
          "TemplateLiteral"
        ]
      }
    ],
  'template-curly-spacing': [
      'off'
    ],
]

kimmy-wang avatar Mar 11 '20 13:03 kimmy-wang

vue-element-admin >4.2.1版 同问 Module build failed (from ./node_modules/eslint-loader/index.js): TypeError: Cannot read property 'range' of null 大佬怎么解决 @shanzhaozhen @upcwangying

require([`@/views/${view}`], resolve)

mactanxin avatar May 07 '20 09:05 mactanxin

vue-element-admin >4.2.1版 同问 Module build failed (from ./node_modules/eslint-loader/index.js): TypeError: Cannot read property 'range' of null 大佬怎么解决 @shanzhaozhen @upcwangying

require([`@/views/${view}`], resolve)

我后来想了一下如果交给后端传入前端的路由地址觉得这样设计非常不妥,所以我把所有前端的路由组件写成一个静态数组,后端只需要保存对应view的名称即可。这个方案应该还可以继续优化一下,达到前后端解耦

shanzhaozhen avatar May 11 '20 06:05 shanzhaozhen

我也遇到了这个问题,依赖库版本升级就搞定了

通问怎么升级的

zxx370455951 avatar Jul 18 '20 10:07 zxx370455951

我又回来了

image

用的是花裤衩的文档里路由懒加载旧方案。 image

虽然有点小问题,但是可以解决后端传路由+按页面切面切分js

iceMilkAndSugar avatar Jul 27 '20 04:07 iceMilkAndSugar

我又回来了

image

用的是花裤衩的文档里路由懒加载旧方案。

image 虽然有点小问题,但是可以解决后端传路由+按页面切面切分js

@iceMilkAndSugar 怎么写的?能举个栗子嘛?

F5F5 avatar Aug 18 '20 09:08 F5F5

vue-element-admin >4.2.1版 同问 Module build failed (from ./node_modules/eslint-loader/index.js): TypeError: Cannot read property 'range' of null 大佬怎么解决 @shanzhaozhen @upcwangying

require([`@/views/${view}`], resolve)

我后来想了一下如果交给后端传入前端的路由地址觉得这样设计非常不妥,所以我把所有前端的路由组件写成一个静态数组,后端只需要保存对应view的名称即可。这个方案应该还可以继续优化一下,达到前后端解耦

我之前也是那样做的,但是这样实际开发会增加工作量,还是打算完全由后端来配置路由表,不知道怎么搞

heyfavour avatar Jan 25 '21 02:01 heyfavour

现在有完整的解决方案么?

zzp0373 avatar May 25 '21 09:05 zzp0373

require([`@/views/${view}`], resolve) 是无法实现动态路由懒加载的,动态路由对应的组件页面会打包到 app.js

经过测试,以下方案可以实现

export const loadView = (view) => {
  // 使用 require 无法实现动态路由的懒加载
  if(process.env.NODE_ENV === 'development') {
    return (resolve) => require([`@/views/${view}`], resolve)
  } else {
    // 使用 import 能实现生产环境的路由懒加载,但是开发环境不行
    return () => import(`@/views/${view}`)
  }
}

补充一下我打包后的效果,下面是生产环境打包后的文件,代码加了 webpackChunkName image

https://gitee.com/y_project/RuoYi-Vue/tree/master/ruoyi-ui 我用的这个后台模板,这个是借鉴 vue-element-admin 的

llt22 avatar Aug 02 '21 06:08 llt22

@llt22 else里的这句代码return () => import(@/views/${view})会报错

Syntax Error: TypeError: Cannot read property 'value' of null
Occurred while linting /Users/rehack/gitproject/lawyeroa-tp6/public/vue/admin/src/router/index.js:447
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)


 @ ./src/main.js 7:0-30 21:10-16
 @ multi (webpack)-dev-server/client?http://192.168.11.63:8080&sockPath=/sockjs-node (webpack)/hot/dev-server.js ./src/main.js


注释掉就不报错了,不知道你是怎么处理的?

rehack avatar Aug 09 '21 06:08 rehack

@llt22 else里的这句代码return () => import(@/views/${view})会报错

Syntax Error: TypeError: Cannot read property 'value' of null
Occurred while linting /Users/rehack/gitproject/lawyeroa-tp6/public/vue/admin/src/router/index.js:447
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)


 @ ./src/main.js 7:0-30 21:10-16
 @ multi (webpack)-dev-server/client?http://192.168.11.63:8080&sockPath=/sockjs-node (webpack)/hot/dev-server.js ./src/main.js


注释掉就不报错了,不知道你是怎么处理的?

没遇到你说的问题,else 里面的代码是非开发环境用的,这个报错是什么环境下的?

llt22 avatar Aug 09 '21 06:08 llt22

@

@llt22 else里的这句代码return () => import(@/views/${view})会报错

Syntax Error: TypeError: Cannot read property 'value' of null
Occurred while linting /Users/rehack/gitproject/lawyeroa-tp6/public/vue/admin/src/router/index.js:447
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)


 @ ./src/main.js 7:0-30 21:10-16
 @ multi (webpack)-dev-server/client?http://192.168.11.63:8080&sockPath=/sockjs-node (webpack)/hot/dev-server.js ./src/main.js


注释掉就不报错了,不知道你是怎么处理的?

没遇到你说的问题,else 里面的代码是非开发环境用的,这个报错是什么环境下的?

就在现在的开发环境下,即使程序没有进入else里,只要出现这句return () => import('@/views/${view}')就报错

rehack avatar Aug 09 '21 07:08 rehack

终于找到问题了

export const loadView = (view) => { // 路由懒加载
    return () => import(`@/views/${view}.vue`)
}

这段代码报错是由于babel-eslint包引起的,babel-eslint现在已经废弃了,官方要求使用@babel/eslint-parser代替。(Vue创建项目的时候,如果勾选了eslint,默认是安装的babel-eslint) image

换成@babel/eslint-parser后,return () => import(@/views/${view}.vue) 这种import动态导入写法就没有报错了,并且开发与生产环境按需加载路由都正常,webpack chunk分割也正常。

rehack avatar Aug 10 '21 06:08 rehack

Question(提问)

  1. 动态路由如何实现懒加载?
  2. 有没有现成的解决方案?
  3. 如果没有的话,是不是可以通过编写webpack插件实现?
思路: 在某个生命周期之前从数据库获取路由的信息,生成路由的静态配置文件,然后再执行正常编译打包流程。

最终这个问题解决了没

yaodaxia avatar Aug 24 '21 07:08 yaodaxia

Question(提问)

  1. 动态路由如何实现懒加载?
  2. 有没有现成的解决方案?
  3. 如果没有的话,是不是可以通过编写webpack插件实现?
思路: 在某个生命周期之前从数据库获取路由的信息,生成路由的静态配置文件,然后再执行正常编译打包流程。

最终这个问题解决了没

上面有可行的方案

llt22 avatar Aug 24 '21 07:08 llt22

提问(提问)

  1. 动态语音如何实现懒加载?
  2. 有没有现成的解决方案?
  3. 如果没有的话,是不是可以通过写webpack插件实现?
思路: 在某个生命周期之前从数据库获取路由的信息,生成路由的静态配置文件,然后再执行正常编译打包流程。

最终这个问题解决了没有

上面有那个方案 是你分享的这个么? export const loadView = (view) => { // 使用 require 无法实现动态路由的懒加载 if(process.env.NODE_ENV === 'development') { return (resolve) => require([@/views/${view}], resolve) } else { // 使用 import 能实现生产环境的路由懒加载,但是开发环境不行 return () => import(@/views/${view}) } }

yaodaxia avatar Aug 24 '21 10:08 yaodaxia

提问(提问)

  1. 动态语音如何实现懒加载?
  2. 有没有现成的解决方案?
  3. 如果没有的话,是不是可以通过写webpack插件实现?
思路: 在某个生命周期之前从数据库获取路由的信息,生成路由的静态配置文件,然后再执行正常编译打包流程。

最终这个问题解决了没有

上面有那个方案 是你分享的这个么? export const loadView = (view) => { // 使用 require 无法实现动态路由的懒加载 if(process.env.NODE_ENV === 'development') { return (resolve) => require([@/views/${view}], resolve) } else { // 使用 import 能实现生产环境的路由懒加载,但是开发环境不行 return () => import(@/views/${view}) } }

是的,此方案是可行的

llt22 avatar Aug 25 '21 03:08 llt22