为什么要捐赠
API 资源管理器
升级指南
NEW!
quasar.config 文件
转换为使用 Webpack 的 CLI
浏览器兼容性
支持 TypeScript
目录结构
命令列表
CSS 预处理器
路由
延迟加载 - 代码分割
处理资源
启动文件
预取功能
API 代理
处理 Webpack
处理 process.env
使用 Pinia 进行状态管理
使用 Vuex 进行状态管理
代码检查器
测试 & 审核
开发移动应用
Ajax 请求
将开发服务器开放到公网
Quasar CLI with Webpack - @quasar/app-webpack
延迟加载/代码分割

当您的网站/应用程序很小时,您可以在初始捆绑包中加载所有布局/页面/组件,并在启动时提供所有内容。 但是,当您的代码变得复杂并具有许多布局/页面/组件时,这样做并非最佳选择,因为它会极大地影响加载时间。 幸运的是,有一种方法可以解决这个问题。

我们将介绍如何延迟加载/代码分割您的应用程序的部分,以便它们仅在需要时自动请求。 这是通过动态导入完成的。 让我们从一个示例开始,然后将其转换为使用延迟加载的示例 - 我们将专注于加载页面,但相同的原理可以应用于加载任何内容(资产、JSON 等)。

延迟加载路由页面

通常使用 Vue Router 调用静态组件,如下所示。

警告

Quasar 文档假设您已经熟悉 Vue Router。 以下是关于如何在 Quasar CLI 项目中使用它的基本介绍。 有关其所有功能的完整列表,请访问 Vue Router 文档

import SomePage from 'pages/SomePage'

const routes = [
  {
    path: '/some-page',
    component: SomePage
  }
]

现在让我们更改此内容,并使用动态导入仅在需要时加载页面

const routes = [
  {
    path: '/some-page',
    component: () => import('pages/SomePage')
  }
]

很简单,对吧? 这会为 /src/pages/SomePage.vue 创建一个单独的块,该块仅在需要时加载。 在这种情况下,当用户访问“/some-page”路由时。

延迟加载组件

通常,您会导入组件,然后将其注册到页面、布局或组件。

<script>
import SomeComponent from 'components/SomeComponent'

export default {
  components: {
    SomeComponent,
  }
}
</script>

现在让我们更改此内容,并使用动态导入仅在需要时加载组件

<script>
import { defineAsyncComponent } from 'vue'
export default {
  components: {
    SomeComponent: defineAsyncComponent(() => import('components/SomeComponent')),
  }
}
</script>

动态延迟加载

如您在上面注意到的,我们使用动态导入 (import('..resource..')) 而不是常规导入 (import Resource from './path/to/resource')。 动态导入本质上返回一个 Promise,您可以使用它

import('./categories.json')
  .then(categories => {
    // hey, we have lazy loaded the file
    // and we have its content in "categories"
  })
  .catch(() => {
    // oops, something went wrong...
    // couldn't load the resource
  })

与常规导入相比,使用动态导入的一个优势是,导入路径可以在运行时确定

import('pages/' + pageName + '/' + id)

供应商导入的注意事项

默认情况下,Quasar 会将来自 node_modules 的包包含在供应商块中,即使您的代码动态导入它们也是如此。 这会增加供应商块的大小,但由于您通常不会更改依赖项,因此浏览器将使用此块的缓存版本,并且实际上会加快应用程序在后续访问时的加载速度。

例如,如果您安装了某个包(我们将其称为 my-package),您可以像这样动态导入它

import('my-package')
  .then(myPackage => {
    // use the package
  })

但是,如果您希望 Quasar CLI 将 my-package 放置到它自己的块中,则需要编辑 /quasar.config 文件

/quasar.config 文件

return {
  vendor: {
    remove: [ 'my-package' ]
  }
}

有关更多详细信息,请参阅 /quasar.config 文件的 供应商部分

动态导入的注意事项

在使用具有变量部分(如上一个示例中)的动态导入时,有一个注意事项。 当网站/应用程序被捆绑时,即在编译时,我们无法确定运行时的确切导入路径。 结果,将为每个可能与变量路径匹配的文件创建块。 您可能会在构建日志中看到不必要的文件。

那么我们如何在这种情况下限制创建的块数量呢? 想法是尽可能地限制变量部分,以便匹配的路径尽可能少。

  1. 添加文件扩展名,即使没有它也能工作。 这将仅为该文件类型创建块。 当该文件夹包含许多文件类型时很有用。
// bad
import('./folder/' + pageName)

// much better
import('./folder/' + pageName + '.vue')
  1. 尝试创建可以限制该变量路径中可用文件的文件夹结构。 使其尽可能具体
// bad -- makes chunks for any JSON inside ./folder (recursive search)
const asset = 'my/jsons/categories.json'
import('./folder/' + asset)

// good -- makes chunks only for JSONs inside ./folder/my/jsons
const asset = 'categories.json'
import('./folder/my/jsons/' + asset)
  1. 尝试从仅包含文件的文件夹导入。 以之前的示例为例,并想象 ./folder/my/jsons 进一步包含子文件夹。 我们通过指定更具体的路径使动态导入更好,但在这种情况下仍然不是最佳选择。 最好使用仅包含文件的终端文件夹,这样我们就可以限制匹配路径的数量。

  2. 使用 Webpack 魔法注释 webpackIncludewebpackExclude 使用正则表达式来约束捆绑的块,例如

await import(
  /* webpackInclude: /(ar|en-US|ro)\.js$/ */
  'quasar/lang/' + langIso
)
  .then(lang => {
    Lang.set(lang.default)
  })

这将导致仅捆绑您网站/应用程序所需的语言包,而不是捆绑所有语言包(超过 40 个!),这可能会影响命令 quasar devquasar build 的性能。

请记住,匹配路径的数量等于生成的块数量。