import按需加载资源优化实践

最近在做项目的首屏优化工作, 提起首屏优化会有很多方式,但是对于如何减小静态资源的加载体积少之又少, 这次记录下在项目中优化的过程.

背景

我们的项目是C端项目, 页面内容是强依赖后端接口数据, 后端接口不返回数据页面不会展示任何内容,(体验的事情,暂时先不谈😭)

页面组件结构

首页模版中用了一些组件,有第三方的,有自己写的

简单介绍下各个组件

  • XxxGuider:一个自定义的组件,展示一些业务相关的引导
  • loading:整个页面的loading
  • cb-ui-render:一个历史悠久的组件(也是后面重点优化的对象), 源码已经没人维护, (我有一次翻到源码,做了一次构建,构建出来的产物功能已经不全了😭), 页面的展示就是依靠它
  • popup, error, lottery,Risk-Control-Part: 自定义的功能性组件

cb-ui-render

关于cb-ui-render的组件要多说一些

在工程中的某个位置, 代码长这样,cb-ui-render是这一坨代码导出其中的一个组件

在项目中这样使用

javascript 复制代码
import CbPlugIn from '@phoenix'
Vue.use(CbPlugIn)

然后在模版中才能试用,否则汇报组件未定义的警告. 写过Vue插件的朋友应该大致猜到了, 这个 CbPlugIn 是一个install函数或者带有install 方法的对象, install 中执行类似这样一行代码 Vue.component('CbUiRender', cb-ui-render组件)

cb-ui-render 接收 uiData 这样的 props 属性, 由 uiData 的数据结构渲染界面

uiData 的数据结构长这样 uiData 是基于接口返回的数据生成的 整体是一个对象结构, 最外层是页面级的数据, elements 是页面中各个组件的数据, 其中的type 属性是组件名称, props 属性是组件用到的数据, on 属性是事件

这样的数据结构传入到 uiData 后, 会根据这样的数据结构生成一个vue的组件对象, 该组件对象的模板(template)属性字符串中用到的组件标签就是 uiData 中的各个 type 关于cb-ui-render 组件内部逻辑比较复杂,这里不在赘述

看下代码执行截图吧, 这里注册 CbUiRender , xs 是对应的组件对象 经过一系列的执行之后,这里生成一个组件对象, 看下 template 属性

这里箭头指的就是 uiData 中的 type

项目中自定义组件

在这样的前提下,我们想要用 cb-ui-render 渲染,就要提前把对应的组件通过Vue.component 注册(这里是为了不用的业务应用做了分开的注册)

然后在首页导入并执行 Vue.use

webpack 分包

由于这个 '@phoenix' 和自定义的 import { bocComponent } from '@/component/uiGadget/components/bocComponent.js' 会比较大,如果不用webpack做分包处理会达到默认的vendor

所以在webpack中这样配置下

这些包就被分到独立的 vendor 中,在浏览器中间加载看看

要等到这些vendor 加载完才会调用接口,获取数据渲染页面,严重影响页面渲染

开始优化

先看之前的 app.vue

cb-ui-render 这个组件依赖接口数据, 可以不在最开始写在模版中, 可以先写一个挂载的dom节点, 利用Vue组件实例挂载的方式等到接口获取到数据再挂载到dom上

具体代码如下:

模版中加一个 idrender_container 的 div

原本注册组件的逻辑由

javascript 复制代码
// 引入渲染器组件
import CbPlugIn from '@phoenix'
Vue.use(CbPlugIn)

// 注册自定义2c组件
import { bocComponent } from '@/component/uiGadget/components/bocComponent.js'
Vue.use(bocComponent)

改成用 import() 函数导入的方式, import 函数可以写在js的逻辑中, 在部署上线之后,每 import 一个js文件,就会发送一个js的请求

同时利用 Promise.all 和接口做并发请求, 这样在获取到数据,获取到两个js资源后,再注册组件,我给封装到一个函数中

处理组件挂载的逻辑,上图中的 this.mount

这里可以用Vue.extend,也可以用new Vue(), 用Vue.extend扩展出一个构造函数,在用这个构造函数生成一个Vue实例,然后挂载到dom中

bocComponent.perf.js 文件改造如下

(修改前) 这样写有个问题: 网络加载的资源中是包含所有组件的js, 体积庞大

(修改后)

index.perf.js 文件改造如下

(修改前)

(修改后)

目标实现接口中返回哪个组件就加载哪个组件, 即所谓的按需加载. 通过 import 函数在配合 /* webpackChunkName: 'xxx'*/ (这样改了之后,要把 webpack 原来 optimization 的分包逻辑去掉)

即可实现组件的按需加载,同时还能减小首屏加载js资源的个数和体积. 部署到线上再看资源的加载情况,

由修改之前的 phoenixSrcVendor(100kb), cxui-components-vendor(228kb), cxui-boc-components-vendor(387kb), cxui-other-components-vendor(104kb) 4个 bundle 减小到现在的 @phoenix(100kb), bocComponent(779b), components(73.5kb)

同时页面中用到了 cxui-title-new ,cxui-banner-new, cxui-nav-menu-new三个组件, 在网络请求中也只加载这三个组件

各个bundle体积也明显减小

总结

利用 import 函数,灵活调整导入组件位置, 同时利用webpack的分包机制, 实现组件的按需导入,减小原来bundle的体积, 加快页面的加载速度

相关推荐
格子软件37 分钟前
2026年GEO优化系统源码级状态机与多模型调度拆解
java·前端·vue.js·人工智能·vue·geo
HUMHSX1 小时前
Vue 项目启动全流程解析:从入口文件到全局指令注册与页面渲染
前端·javascript·vue.js
有颜有货2 小时前
PMC生产排产的4种算法,一次讲清
java·服务器·前端
小虎牙0072 小时前
Android kotlin图片库Coil源码详解
android·前端
随风一样自由2 小时前
【前端领域】前端开发核心应用场景与落地实践
前端·前端框架
an317422 小时前
弹窗数据流设计的两种高阶架构实践
前端·vue.js·架构
谢尔登2 小时前
【React】 状态管理方案
前端·react.js·前端框架
用户2136610035723 小时前
Vue商品详情与放大镜组件
前端·javascript
半个落月3 小时前
从Tapas小Demo理清localStorage、事件与this
前端·javascript
李明卫杭州3 小时前
Vue2 中 v-model 处理不同数据结构的技巧
前端·javascript·vue.js