在 Vue 中使用 Webpack 动态注释进行路由懒加载

Avatar of Jorge Baumann
Jorge Baumann

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

JavaScript 中路由的工作方式通常是指定要为哪个组件呈现哪个相对 URL 模式。因此,对于 /about,您希望呈现 <About /> 组件。让我们看看如何在 Vue/Vue Router 中使用懒加载来实现这一点,并尽可能简洁地完成。我在自己的工作中一直使用这个小技巧。

包含本文中所有内容的代码库 可在 GitHub 上获取

您可能见过这样的 Vue 路由(URL)

import Vue from 'vue'
import VueRouter from 'vue-router'

import Home from '../views/Home.vue'
import About from '../views/About.vue'
import Login from '../views/Login.vue'

Vue.use(VueRouter)

const routes = [
  { path: '/', name: 'Home', component: Home },
  { path: '/about', name: 'About', component: About },
  { path: '/login', name: 'Login', component: Login }
]

const router = new VueRouter({
  routes
})

export default router

这将在 / 路由处加载 <Home /> 组件,在 /about 路由处加载 <About /> 组件,在 /login 路由处加载 <Login /> 组件。

但这在代码分割方面做得并不好,因为所有这三个组件都将捆绑在一起,而不是根据需要动态加载。

This is a terminal screenshot with a dark purple background with text in white green and blue. The content shows the final build after compiling.

这是另一种方法,它使用动态导入语句和 webpack 块名称进行代码分割

const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')
  },
  {
    path: '/about',
    name: 'About',
    component: () => import(/* webpackChunkName: "About" */ '../views/About.vue')
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import(/* webpackChunkName: "Login" */ '../views/Login.vue')
  }
]

这很好,没有明显的缺点,除了有点冗长和重复之外。由于我们是优秀的开发人员,让我们进行一些抽象来帮助我们,使用一个我们将循环遍历的 array

const routeOptions = [
  { path: '/', name: 'Home' },
  { path: '/about', name: 'About' },
  { path: '/login', name: 'Login' }
]

const routes = routeOptions.map(route => {
  return {
    ...route,
    component: () => import(`@/views/${route.name}.vue`)
  }
})

const router = new VueRouter({
  routes
})

现在我们通过使用路由 name 作为 import 函数的参数减少了 component 键的使用。

但是,如果我们想设置块名称会发生什么?

据我所知,如果没有某种构建步骤,您无法在 JavaScript 中使用动态注释。因此,在这种情况下,我们牺牲了注释(webpackChunkName)以换取编写更少代码的机会。完全取决于您喜欢哪种方式。

开玩笑的,让我们修复它。

从 webpack 2.6.0 开始,支持占位符 [index][request],这意味着我们可以像这样设置生成的块的名称

// ...

const routeOptions = [
  { path: '/', name: 'Home' },
  { path: '/about', name: 'About' },
  { path: '/login', name: 'Login' }
]

const routes = routeOptions.map(route => {
  return {
    ...route,
    component: () => import(/* webpackChunkName: "[request]" */ `../views/${route.name}.vue`)
  }
})

const router = new VueRouter({
  routes
})

不错!现在我们拥有了所有功能,以及具有命名块的动态加载路由。它适用于 Vue 2 和 Vue 3。您可以通过在终端中运行 npm run build 来查看它

This is the same terminal screenshot as before, but with three of the JavaScript built files highlighted with the words "Named Chunks" annotated beside them.
看到了吗?现在组件被分块了……并且构建为我们完成了所有命名工作!

但是,我们还可以通过将懒加载路由分组到命名块中而不是单个组件中来更进一步。例如,我们可以创建组,将我们最重要的组件组合在一起,并将其余组件放在另一个“不太重要”的组中。我们只需更新 webpack 块名称以替换我们之前使用的 [request] 占位符

const routes = [
  {
    path: "/",
    name: "Home",
    component: () =>
      import(/* webpackChunkName: "VeryImportantThings" */ "../views/Home.vue")
  },
  {
    path: "/about",
    name: "About",
    component: () =>
      import(/* webpackChunkName: "VeryImportantThings" */ "../views/About.vue")
  },
  {
    path: "/login",
    name: "Login",
    component: () =>
      import(/* webpackChunkName: "NotSoImportant" */ "../views/Login.vue")
  },
  {
    path: "/contact",
    name: "Contact",
    component: () =>
      import(/* webpackChunkName: "NotSoImportant" */ "../views/Contact.vue")
  }
];

现在我们的四个组件被分组到两个单独的块中。

The same terminal with different compiled JavaScript files.

就是这样!一种在 Vue 中懒加载路由的技术,以及一些关于如何在构建时命名和分组它们的思路。