Vue 路由懒加载问题

2021-04-18  本文已影响0人  BA_凌晨四点

首先描述一下我的开发环境配置:

  1. vue: 2.6.11
  2. vue-router: 3.2.0
  3. vue-cli: 3.9.3

目的:

上传Vue项目到服务器时,首次加载,发现请求太慢了,于是到网上找了很多方法,比如:分包、cdn加速、gzip压缩等,其中一个叫做路由懒加载

原先的路由配置方法:

import Vue from "vue";
import VueRouter from "vue-router";
import About from "@/view/About";
// 分别导入各个页面组件,此处省略...

const routes = [
  {
    path: "/About",
    name: "about",
    component: About;
  },
// ... 下面配置路由同上,此处省略
]

首次载入时,会把全部页面都载入

第一次配置路由懒加载:

import Vue from "vue";
import VueRouter from "vue-router";

const routes = [
  {
    path: "/About",
    name: "about",
    component: import("@view/About")  // 据说这样就是会当地址匹配到时候,才会加载
  },
// ... 下面配置路由同上,此处省略
]

第二次配置路由懒加载:

import Vue from "vue";
import VueRouter from "vue-router";

const routes = [
  {
    path: "/About",
    name: "about",
    component: import(/* webpackChunkName: "about" */ `@/views/About`)  
    // 这里加上了webpackChunkName,然后名字和该页面组件名字保持一致
  },
// ... 下面配置路由同上,此处省略
]

后来,我为了偷懒还封装了一个函数,专门用于生产:

/**
 * 生产懒加载的页面函数
 * @param {*} view 页面
 * @param {*} str 页面名字
 */
function loadView(view, str) {
  return () =>
    import(
      /* webpackChunkName: `${str}-[request]-[index]` */ `@/views/${view}`
    );
}

第三次配置路由懒加载:

import Vue from "vue";
import VueRouter from "vue-router";

const routes = [
  {
    path: "/About",
    name: "about",
    component: resolve => require(["@/view/About"], resolve);
  },
// ... 下面配置路由同上,此处省略
]

后来,我去到Vue开发者社区那看到这位老哥的回答:

router.png
说这是Webpack版本的差异导致写法的差异:
require这是CommonJs的写法,而import是ES6模块化的写法

可是事情就这么结束了吗?

遇到的问题:

我上面三次的配置方式,都会出现一个问题:产生许多的文件。。其中包括css和js等,我认真的看了下,它把我的每个路由都分离了出来,
如果不重命名,则它的名称是:

名称1~名称2.js ,每加多一个文件,就会多一个 “~名称n”

然后我又开始找方法。。
后来找到一个类似的问题,它的解决方法是:

// vue.config.js
// 移除 prefetch 插件
  chainWebpack config => {
    config.plugins.delete("prefetch"),
    config.plugins.delete("preload"),
    // 或者 修改它的选项:
    config.plugin("prefetch").tap(options => {
        options[0].fileBlacklist = options[0].fileBlacklist || [];
        options[0].fileBlacklist.push(/myasyncRoute(.)+?\.js$/);
        return options;
      });
  }

它的大概意思是 vue-cli3搭建的,会自动安装这2个插件,功能是预加载,预判你将要会加载的路径。

然后我按它方法设置了,再npm run build打包,发现还是没变,文件依然很多。。。

解决方法:

第一次尝试解决:

在上述第二次配置路由的方法中,设置每个webpackChunkName名字都一样

const routes = [
  {
    path: "/About",
    name: "about",
    component: import(/* webpackChunkName: "chunk-all" */ `@/views/About`)  
  // 每个路由每个都是这个 chunk-all 的名字
  },
// ... 下面配置路由同上,此处省略
]

npm run build,打包后发现,文件确实减少了,之前那些叠加出来的文件消失了。
但是,新的问题出现了。。报错了。。。
[Vue warn]: Failed to mount component: template or render function not defined.
此时,我又在网上找了一圈,有的说由于匹配问题,需要在路由后面加上具体的文件以及它的后缀

{
    path: "/About",
    name: "about",
    component: import(/* webpackChunkName: "chunk-all" */ `@/views/About/index.vue`)  
  },

可是问题还是没解决。。接着找。。。

该解决方法出来了:

component后面要加上s

{
    path: "/About",
    name: "about",
    components: import(/* webpackChunkName: "chunk-all" */ `@/views/About/index.vue`)  
  },

成功了,报错信息消失了。。,新的问题又出现了。。。我的页面组件呢。。?
我发现路由不是懒加载了,而是直接不加载了。。。

路由不加载.gif
按路由切换,router-view不会解析路径。。。

解决方法来了:

import 需要函数把它引入(注意以下注释部分)

import Vue from "vue";
import VueRouter from "vue-router";

const routes = [
  {
    path: "/About",
    name: "about",
    component: () => import(/* webpackChunkName: "chunk-all" */ `@/views/About`)  
    // 注意这里有 箭头函数,而 component不需要加s
  },
// ... 下面配置路由同上,此处省略
]

或者:使用require.ensure()这个方法也行

{
    path: "/",
    name: "about",
    component: resolve =>
      require.ensure([], () => resolve(require("@/views/About")), "chunk-all")
      // 这里的第三个参数 chunk-all ,后面所有路由都统一使用一样的名字
  }

可是,问题就这样结束了吗?

我又发现,如果像上面说的,为了减少生成的文件,而把名字全都设置成chunk-all,反而失去了css等懒加载。。

问题更新:

我发现,即使生成了很多文件,但是这些文件都不会在首次加载的时候 全部加载的。。
这真正实现的路由懒加载!

最终解决方法:

import Vue from "vue";
import VueRouter from "vue-router";

const routes = [
{
    path: "/",
    name: "about",
    component: resolve =>
      require.ensure([], () => resolve(require("@/views/About")), "about")
      // 这里的第三个参数 和该页面组件名字保持一致
  }
// ... 下面配置路由同上,此处省略
]

或者:

import Vue from "vue";
import VueRouter from "vue-router";

const routes = [
  {
    path: "/About",
    name: "about",
    component: () => import(/* webpackChunkName: "about" */ `@/views/About`)  
    // 这里加上了webpackChunkName,然后名字和该页面组件名字保持一致
  },
// ... 下面配置路由同上,此处省略
]
上一篇 下一篇

猜你喜欢

热点阅读