摘要:静态模块不能被取消注册也不能延迟注册,并且在初始化后不能更改静态模块的结构不是状态。为此,我们将在路由对应的组件中加载模块,而不是在中导入并注册它。能代码分割模块是一个强大的工具。
在前一部分,我们学习了足够强大的模式,可以显着提高应用程序的性能 - 按每个路由分割代码。虽然按路由分割代码非常有用,但是在用户访问我们的站点后,仍然有很多代码是不需要的。在本系列的这一部分中,我们将重点关注分离我们的状态管理(state management ) - Vuex模块。
本系列文章基于对 Vue Storefront 性能优化过程的学习。通过使用下面的技术,我们能够将初始文件的大小减少70%,并在眨眼间使其加载。
Part 1 — Introduction to performance optimization and lazy loading.
Part 2 — Lazy loading routes and vendor bundle anti-pattern.
Part 3 — Lazy loading Vuex modules
Part 4 — Delivering good waiting experience and lazy loading individual components — soon
Part 5 — Lazy loading libs and finding smaller equivalents — soon
Part 6 — Performance-friendly usage of UI libraries
Part 7 — Making use of Service Worker cache — soon
Part 8 — Prefetching
两种类型的Vuex模块在我们进一步了解如何延迟加载 Vuex 模块 之前,您需要注意一件重要的事情,了解注册 Vuex 模块的方法,以及它们的优缺点。
静态 Vuex 模块(Static Vuex modules) 是在 Store 初始化期间声明注册。 以下是显式创建的静态模块的示例:
// store.js import { userAccountModule } from "./modules/userAccount" const store = new Vuex.Store({ modules: { user: userAccountModule } })
上面的代码将创建一个带有静态模块 userAccountModule 新的 Vuex 实例。静态模块不能被取消注册(也不能延迟注册),并且在 Store 初始化后不能更改静态模块的结构(不是状态(not state))。
虽然这种限制对大多数模块来说都不是问题,而且将所有模块声明在一个地方,确实有助于将所有与数据相关的内容保存在一起,但是这种方法也有一些缺点。
假设我们的应用程序中有一个专用的 Vuex 模块的 admin 面板。
// store.js import { userAccountModule } from "./modules/userAccount" import { adminModule } from "./modules/admin" const store = new Vuex.Store({ modules: { user: userAccountModule, admin: adminModule } })
你可以想象这样的模块可能会非常的庞大。尽管 admin 面板可能只会被一小部分用户使用,并且只能在特定的路由下使用(一个特殊的 /admin 路径),但由于这些静态模块都是被集中注册的,最终这些代码都会被打包到主文件中。
我们所有的模块都打包在一个文件中
这当然不是我们想要的结果。我们需要一种方法只在访问 /admin 路由时才加载。您可能已经猜到静态模块不能满足我们的需要。所有静态模块都需要在 Vuex Store 创建时进行注册。
这就是动态模块可以帮助我们的地方!
动态模块相比静态模块来说,可以在 Vuex Store 创建后再进行注册。这种简洁的功能意味着我们不需要在应用程序初始化时下载动态模块,而是可以将其打包在不同的代码块中,或者在需要时延迟加载。
首先,让我们看看前面的 admin 模块用动态注册是什么样子的:
// store.js import { userAccountModule } from "./modules/userAccount" import { adminModule } from "./modules/admin" const store = new Vuex.Store({ modules: { user: userAccountModule, } }) store.registerModule("admin", adminModule)
我们没有直接将 adminModule 模块写在 modules 属性中,而是在 Vuex.Store 创建之后使用 registerModule 方法注册这个模块。
动态注册不需要对模块本身进行任何更改,因此可以静态或动态注册任何 Vuex 模块。
当然,在目前来看,这个动态注册的模块并没有给我们任何好处。
适当的分割Vuex模块让我们回到我们的问题上来,既然我们知道了如何动态注册 admin 模块,我们当然可以尝试将其代码放入 /admin 路由文件中。
让我们暂时停下来,简要了解一下我们正在使用的应用程序:
// router.js import VueRouter from "vue-router" const Home = () => import("./Home.vue") const Admin = () => import("./Admin.vue") const routes = [ { path: "/", component: Home }, { path: "/admin", component: Admin } ] export const router = new VueRouter({ routes })
在 router.js 中,我们有两个路由做了代码分割,它们被延迟加载。使用我们在上面看到的代码,我们的 admin 模块仍然会打包到主文件 app.js 中,因为它在 store.js 中是静态导入的。
让我们修复这个问题,并将此模块仅给访问 /admin 路由的用户使用,这样其他人就不会下载冗余的代码。
为此,我们将在 /admin 路由对应的组件中加载 admin 模块,而不是在 store.js 中导入并注册它。
// store.js import { userAccountModule } from "./modules/userAccount" export const store = new Vuex.Store({ modules: { user: userAccountModule, } }) // Admin.vue import adminModule from "./admin.js" export default { // other component logic mounted () { // 在这里动态注册模块 this.$store.registerModule("admin", adminModule) }, beforeDestroy () { // 当组件被销毁时,取消注册 this.$store.unregisterModule("admin") } }
让我们看看发生了什么!
我们在 /admin 路由对应的 Admin.vue 组件中导入了 admin 模块,并在组件挂载(mounted)之后注册到了 Store 中。一旦用户退出 damin 面板,销毁该组件,我们就会取消注册该模块,以防止同一模块被多次注册。
现在因为 admin 模块是在 Admin.vue 导入的,而不是在 store.js 中导入的,所以它将与代码分割的 admin.vue 打包在一个文件中!
重要提示:如果使用SSR模式,请确保在 mounted 钩子中 注册模块。否则,它可能导致内存泄漏,因为beforeDestroy钩子在服务器端不能执行。
现在我们知道了如何使用动态注册 Vuex 模块,并适当的分配到特定路由的文件中。让我们看一下稍微复杂一点的用例。
延迟加载Vuex模块假如说,我们的 home.vue 上有一个客户评价的部分,我们希望用户可以对我们的服务有积极的建议。这样的评价部分有很多,我们不想在用户进入我们的网站后立即显示它们, 只有在用户需要时才能显示它们。我们可以添加“Show Testimonials”按钮,点击后才加载并显示客户评价的部分。
为了存储客户评价数据,我们还需要一个Vuex模块。我们称它为 testimonials 吧。该模块将负责显示以前添加的评价和添加的新评价。我们不需要知道实现细节。
我们希望只有用户点击按钮才下载 testimonials 模块,在此之前是不需要它的。让我们看看如何利用动态模块注册和动态导入来实现此功能,Testimonials.vue 是被 Home.vue 使用的一个组件。
让我们快速回顾一下代码。当用户单击 "Show Testimonials" 按钮时,将调用 getTestimonials() 方法,它负责调用 getTestimonialsModule() 来获取 testimonials.js。一旦 promise 为成功状态(resolved)(这意味着模块已被加载),我们就会动态注册它并触发 action 获取客户评价。
多亏了动态导入,testmonials.js 内容被打包到一个多带带的文件中,只有在调用 gettestmonialsModule 方法时才下载该文件。
当我们需要退出 admin 面板时,我们在 beforeDestroy 生命周期钩子中取消注册已注册过的模块,如果我们再次进入这个路由,就不会出现重复注册的情况。
总结尽管静态 Vuex 模块注册对于大多数用例来说已经足够了,但是在某些特定的情况下,我们可能需要使用动态注册。
如果模块只在特定的路由上需要,那么我们可以在适当的路由组件中动态注册它,这样它就不会打包在主文件中。
如果模块只有在一些交互之后才需要,那么我们需要将动态模块注册与动态导入结合起来,并以适当的方法延迟加载模块。
能代码分割Vuex模块是一个强大的工具。您在应用程序中处理的与数据相关的操作越多,就可以从文件大小方面节省的越多。
在本系列的下一部分中,我们将学习如何延迟加载各个组件,更重要的是,应该延迟加载哪些组件。
如果对你有帮助,请关注【前端技能解锁】:
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/109635.html
摘要:我的目标是使本系列成为关于应用程序性能的完整指南。代码分割就是将应用程序分割成这些延迟加载的块。总结延迟加载是提高应用程序性能并减少其大小的最佳方法之一。在本系列的下一部分中,我将向您展示如何使用和路由来分割应用程序代码。 当移动优先(mobile-first)的方式逐渐成为一种标准,而不确定的网络环境因素应该始终是我们考虑的一点,因此保持让应用程序快速加载变得越来越困难。在本系列文章...
摘要:现在,我们将更深入地研究,并学习用于分割应用程序最实用的模式。本系列文章基于对性能优化过程的学习。路径时才被下载。为了便于理解,文件名称并不是由生成的真实名称。接下来,我们将学习其他部分和单独的组件也能够从主文件分割出来并延迟加载。 在前一篇文章中,我们学习了什么是代码分割,它是如何与 Webpack 一起工作的,以及如何在Vue应用程序中使用延迟加载。现在,我们将更深入地研究,并学习...
摘要:在中新建组件许文瑞正在吃屎。。。。在中添加如下代码三歌手组件开发歌手首页开发数据获取数据获取依旧从音乐官网获取歌手接口创建我们和以前一样,利用我们封装的等发放,来请求我们的接口,返回给。 Vue-Music 跟学一个网课老师做的仿原生音乐APP跟学的笔记,记录点滴,也希望对学习vue初学小伙伴有点帮助 showImg(https://segmentfault.com/img/remot...
摘要:是一款基于的服务端渲染框架,跟的异曲同工。该配置项用于定义应用客户端和服务端的环境变量。 Vue因其简单易懂的API、高效的数据绑定和灵活的组件系统,受到很多前端开发人员的青睐。国内很多公司都在使用vue进行项目开发,我们正在使用的简书,便是基于Vue来构建的。 我们知道,SPA前端渲染存在两大痛点:(1)SEO。搜索引擎爬虫难以抓取客户端渲染的页面meta信息和其他SEO相关信息,使...
阅读 2687·2021-09-22 15:58
阅读 2231·2019-08-29 16:06
阅读 900·2019-08-29 14:14
阅读 2811·2019-08-29 13:48
阅读 2452·2019-08-28 18:01
阅读 1496·2019-08-28 17:52
阅读 3319·2019-08-26 14:05
阅读 1612·2019-08-26 13:50