PanJiaChen / vue-element-admin

:tada: A magical vue admin https://panjiachen.github.io/vue-element-admin
MIT License
88k stars 30.48k forks source link

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

Open kimmy-wang opened 5 years ago

kimmy-wang commented 5 years ago

Question(提问)

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

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 默认有所有页面权限,具体多仔细看看,作者在权限这块其实写的很灵活的

yutaolian commented 5 years ago

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

kimmy-wang commented 5 years ago

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

xlb commented 5 years ago

同问

xlb commented 5 years ago

`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 }` 可以参考下

kimmy-wang commented 5 years ago

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

xlb commented 5 years ago

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

iceMilkAndSugar commented 5 years ago

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

kimmy-wang commented 4 years ago

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

shanzhaozhen commented 4 years ago

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

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

kimmy-wang commented 4 years ago

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

shanzhaozhen commented 4 years ago

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

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

lovlyhao commented 4 years ago

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

kimmy-wang commented 4 years ago

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'
    ],
]
mactanxin commented 4 years ago

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)
shanzhaozhen commented 4 years ago

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的名称即可。这个方案应该还可以继续优化一下,达到前后端解耦

zxx370455951 commented 4 years ago

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

通问怎么升级的

iceMilkAndSugar commented 4 years ago

我又回来了

image

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

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

F5F5 commented 4 years ago

我又回来了

image

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

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

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

heyfavour commented 3 years ago

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的名称即可。这个方案应该还可以继续优化一下,达到前后端解耦

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

zzp0373 commented 3 years ago

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

llt22 commented 3 years ago

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 的

rehack commented 3 years ago

@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

注释掉就不报错了,不知道你是怎么处理的?
llt22 commented 3 years ago

@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 里面的代码是非开发环境用的,这个报错是什么环境下的?

rehack commented 3 years ago

@

@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 commented 3 years ago

终于找到问题了

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分割也正常。

yaodaxia commented 3 years ago

Question(提问)

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

最终这个问题解决了没

llt22 commented 3 years ago

Question(提问)

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

最终这个问题解决了没

上面有可行的方案

yaodaxia commented 3 years ago

提问(提问)

  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 commented 3 years ago

提问(提问)

  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}) } }

是的,此方案是可行的

rehack commented 3 years ago

提问(提问)

  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}) } }

是的,此方案是可行的

用此方案,我打包后发现有几个路由被合在了一起,打包到了同一个js文件,其他打包后都是独立的chunk js 。这几个路由组件并没有关联,不知道是怎么回事,至今没找到原因,

yaodaxia commented 3 years ago

提问(提问)

  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}) } }

是的,此方案是可行的

用此方案,我打包后发现有几个路由被合在了一起,打包到了同一个js文件,其他打包后都是独立的chunk js 。这几个路由组件并没有关联,不知道是怎么回事,至今没找到原因,

提问(提问)

  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}) } }

是的,此方案是可行的

用此方案,我打包后发现有几个路由被合在了一起,打包到了同一个js文件,其他打包后都是独立的chunk js 。这几个路由组件并没有关联,不知道是怎么回事,至今没找到原因,

你们都确定吗 为啥这种写法 我build出来的文件只有本地静态路由被chunk了 其他动态路由就没有

yaodaxia commented 3 years ago

return () => import(@/views/${view}) 请问这种方案打包的dist文件是按组件chunk js 文件嘛 同时表现上是不是和静态路由一样用户点击路由才加载对应的chunk资源

llt22 commented 3 years ago

return () => import(@/views/${view}) 请问这种方案打包的dist文件是按组件chunk js 文件嘛 同时表现上是不是和静态路由一样用户点击路由才加载对应的chunk资源

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

llt22 commented 3 years ago

return () => import(@/views/${view}) 请问这种方案打包的dist文件是按组件chunk js 文件嘛 同时表现上是不是和静态路由一样用户点击路由才加载对应的chunk资源

懒加载的目的就是为了能够实现用户到了对应的路由才去加载资源,所以肯定就是这样的效果

rehack commented 3 years ago

return () => import(@/views/${view}) 请问这种方案打包的dist文件是按组件chunk js 文件嘛 同时表现上是不是和静态路由一样用户点击路由才加载对应的chunk资源

懒加载的目的就是为了能够实现用户到了对应的路由才去加载资源,所以肯定就是这样的效果

@llt22 为什么我有几个组件被打包到一起了,这几个组件没有关联,最后导致这个js文件偏大,控制台发出警告 WX20210826-150710 WX20210826-151726

yaodaxia commented 3 years ago

我感觉你的问题会不会出在webpack配置上,我这边动态路由拆分也没实现呢

llt22 commented 3 years ago

我感觉你的问题会不会出在webpack配置上,我这边动态路由拆分也没实现呢

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

yaodaxia commented 3 years ago

我感觉你的问题会不会出在webpack配置上,我这边动态路由拆分也没实现呢

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

return () => import(@/views/${view}) 请问这种方案打包的dist文件是按组件chunk js 文件嘛 同时表现上是不是和静态路由一样用户点击路由才加载对应的chunk资源

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

@llt22 此方案还没解决我动态路由拆分 可否分享更多些代码 (vuecli版本,webpack版本,动态路由的生成过程)相关代码 谢谢

llt22 commented 3 years ago

我感觉你的问题会不会出在webpack配置上,我这边动态路由拆分也没实现呢

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

return () => import(@/views/${view}) 请问这种方案打包的dist文件是按组件chunk js 文件嘛 同时表现上是不是和静态路由一样用户点击路由才加载对应的chunk资源

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

@llt22 此方案还没解决我动态路由拆分 可否分享更多些代码 (vuecli版本,webpack版本,动态路由的生成过程)相关代码 谢谢

你看这个就行 https://gitee.com/y_project/RuoYi-Vue/tree/master/ruoyi-ui ,所有代码都在这里

gatspy commented 2 years ago

也在寻找解决方法

menglingfei commented 2 years ago

提问(提问)

  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}) } }

项目过大的情况下,在打包构建时使用import比require要慢很多很多,是什么情况