浅谈vue项目优化之页面的按需加载(vue+webpack)


Posted in Javascript onDecember 11, 2017

通过vue写的单页应用时,可能会有很多的路由引入。当打包构建的时候,javascript包会变得非常大,影响加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应的组件,这样就更加高效了。这样会大大提高首屏显示的速度,但是可能其他的页面的速度就会降下来。结合Vue的异步组件和webpackde code splitting feature,轻松实现路由组件的懒加载。

就像图片的懒加载一样,如果客户根本就没有看到那些图片,而我们却在打开页面的时候全部给加载完了,这样会大大的增加请求的时间,降低用户的体验程度。懒加载在很多的网站都有用到,比如淘宝、京东等等这样的购物网站,上面的图片链接等等都很多,如果你把滚轴迅速的往下拉的时候,你可能会看到图片加载的情况。

单页应用也是一样,用户可能没有通过点击跳转到其他的的页面,而是只在主页面进行了停留,那么我们就没有必要把其他页面的资源全部加载过来。如果用户点进去再加载。这样就可以大大提高请求时间,提高用户的体验程度。

webpack中提供了require.ensure()来实现按需加载。以前引入路由是通过import 这样的方式引入,改为const定义的方式进行引入。

不进行页面按需加载引入方式:import  home   from '../../common/home.vue'

进行页面按需加载的引入方式:const  home = r => require.ensure( [], () => r (require('../../common/home.vue')))

下面的内容讲解的更为详细

webpack ensure相信大家都听过。有人称它为异步加载,也有人说做代码切割,那这个家伙到底是用来干嘛的?其实说白了,它就是把js模块给独立导出一个.js文件的,然后使用这个模块的时候,webpack会构造script dom元素,由浏览器发起异步请求这个js文件。

场景分析:

比如应用的首页里面有个按钮,点击后可以打开某个地图。打开地图的话就要利用百度地图的js,于是我们不得不在首页中把百度地图的js一起打包进去首页,一个百度地图的js文件是非常大的,假设为1m,于是就造成了我们首页打包的js非常大,用户打开首页的时间就比较长了。

有没有什么好的解决方法呢?

解决1

既然打包成同一个js非常大的话,那么我们完全可以把百度地图js分类出去,利用浏览器的并发请求js文件处理,这样的话,会比加载一个js文件时间小得多。嗯,这也是个不错的方案。为baidumap.js配置一个新的入口就行了,这样就能打包成两个js文件,都插入html即可(如果baidumap.js被多个入口文件引用的话,也可以不用将其设置为入口文件,而且直接利用CommonsChunkPlugin,导出到一个公共模块即可)可以参考我之前文章webpack模块打包

那还有没有更好的解决方案呢?

解决2

当然还是有的!我们细想,百度地图是用户点击了才弹出来的,也就是说,这个功能是可选的。那么解决方案就来了,能不能在用户点击的时候,我在去下载百度地图的js.当然可以。那如何实现用户点击的时候再去下载百度地图的js呢?于是,我们可以写一个按钮的监听器

mapBtn.click(function() {
 //获取 文档head对象
 var head = document.getElementsByTagName('head')[0];
 //构建 <script>
 var script = document.createElement('script');
 //设置src属性
 script.async = true;
 script.src = "http://map.baidu.com/.js"
 //加入到head对象中
 head.appendChild(script);
})

上面的几行代码对大家来说都不难。可以在点击的时候,才加载百度地图,等百度地图加载完成后,在利用百度地图的对象去执行我们的操作。ok,讲到这里webpack.ensure的原理也就讲了一大半了。它就是
把一些js模块给独立出一个个js文件,然后需要用到的时候,在创建一个script对象,加入到document.head对象中即可,浏览器会自动帮我们发起请求,去请求这个js文件,在写个回调,去定义得到这个js文件后,需要做什么业务逻辑操作。

ok,那么我们就利用webpack的api去帮我们完成这样一件事情。点击后才进行异步加载百度地图js,上面的click加载js时我们自己写的,webpack可以轻松帮我们搞定这样的事情,而不用我们手写

mapBtn.click(function() {
 require.ensure([], function() {
  var baidumap = require('./baidumap.js') //baidumap.js放在我们当前目录下
 })
})

搞定!当然还是分析一下。require.ensure这个函数是一个代码分离的分割线,表示 回调里面的require是我们想要进行分割出去的,即require('./baidumap.js'),把baidumap.js分割出去,形成一个webpack打包的单独js文件。当然ensure里面也是可以写一些同步的require的,比如

var sync = require('syncdemo.js')  //下面ensure里面也用到
mapBtn.click(function() {
 require.ensure([], function() {
  var baidumap = require('./baidumap.js') //baidumap.js放在我们当前目录下
  var sync = require('syncdemo.js') //这个不会独立出去,因为它已经加载到模块缓存中了
 })
})

也就是说,ensure会把没有使用过的require资源进行独立分成成一个js文件. require.ensure的第一个参数是什么意思呢?[], 其实就是 当前这个 require.ensure所依赖的其他 异步加载的模块。你想啊?如果A 和 B都是异步加载的,B中需要A,那么B下载之前,是不是先要下载A啊?,所以ensure的第一个参数[]是它依赖的异步模块,但是这里需要注意的是,webpack会把参数里面的依赖异步模块和当前的需要分离出去的异步模块给一起打包成同一个js文件,这里可能会出现一个重复打包的问题,假设A 和 B都是异步的, ensure A 中依赖B,ensure B中 依赖A,那么会生成两个文件,都包含A和B模块。 如果想加载A require.ensure([‘A.js'],function) 即可

说完了上面的原理。下面就实践一下

浅谈vue项目优化之页面的按需加载(vue+webpack)

entry.js 依赖三个 js。

  1. Abtn-work.js 是封装了 abtn按钮点击后,才执行的业务逻辑
  2. Bbtn-work.js 是封装了 bbtn按钮点击后,才执行的业务逻辑
  3. util.js 是封装了 entry.js需要利用的工具箱

针对上面的需求,优化方案

假设 Abtn-work.js Bbtn-work.js util.js都是非常大的文件因为 Abtn-work.js Bbtn-work.js 都不是entry.js必须有的,即可能发生的操作,那么我们把他们利用异步加载,当发生的时候再去加载就行了

util.js是entry.js立即马上依赖的工具箱。但是它又非常的大,所以将其配置打包成一个公共模块,利用浏览器的并发加载,加快下载速度。ok,构思完成,开始实现

index.html

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>index</title>
 </head>
 <body>
  <div id="aBtn">Abtn</div>
  <div id="bBtn">Bbtn</div>
 </body>
</html>

定义了两个buttom

然后看看 entry.js

var util_sync = require('./util-sync.js')
alert(util_sync.data)
document.getElementById("aBtn").onclick = function() {
 require.ensure([], function() {
  var awork = require('./workA-async.js')
  alert(awork.data)
  //异步里面再导入同步模块--实际是使用同步中的模块
  var util1 = require('./util-sync.js')
 })
}
document.getElementById("bBtn").onclick = function() {
 require.ensure([], function() {
  var bwork = require('./workB-async.js')
  alert(bwork.data)
 })
}

可以看到,workA-async.js, workB-async.js 都是点击后才ensure进来的。什么时候加载完成呢?就是 require.ensure() 第二个函数参数,即回调函数,它表示当下载js完成后,发生的因为逻辑

webpack打包后,形成

浅谈vue项目优化之页面的按需加载(vue+webpack)

其实, 1.1… 2.2…就是我们ensure导出来的js文件

我们看看代码是如何加载的执行的,点击打包插入js后的html

浅谈vue项目优化之页面的按需加载(vue+webpack)

可以看到,并没有加载 ensure导出来的 1.1…js 2.2…js

点击 abtn,

浅谈vue项目优化之页面的按需加载(vue+webpack)

发现浏览器下载并加载了 1.1…js

点击 bbtn

浅谈vue项目优化之页面的按需加载(vue+webpack)

发现浏览器下载并加载了 2.2…js

vue项目优化,还有通过减少向服务器请求的次数来减少等待的时间。比如,一个页面的数据包括图片、文字等用户都已经加载完了,然后用户通过点击跳转到了另外一个界面。然后从另外一个界面通过返回又回到了原先的界面。如果没有设置的话,那么原先界面的信息就要重新向服务器请求得到。而通过vue提供的keep-alive可以是页面的已经请求的数据得以保存,减少请求的次数,提高用户的体验程度。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JS网页播放声音实现代码兼容各种浏览器
Sep 22 Javascript
js中split和replace的用法实例
Feb 28 Javascript
BootStrap selectpicker后台动态绑定数据
Jun 01 Javascript
深入理解requireJS-实现一个简单的模块加载器
Jan 15 Javascript
vue项目中引入noVNC远程桌面的方法
Mar 05 Javascript
在iFrame子页面里实现模态框的方法
Aug 17 Javascript
Vue触发式全局组件构建的方法
Nov 28 Javascript
vue elementUI table表格数据 滚动懒加载的实现方法
Apr 04 Javascript
vue router 通过路由来实现切换头部标题功能
Apr 24 Javascript
vue history 模式打包部署在域名的二级目录的配置指南
Jul 02 Javascript
Vue 路由间跳转和新开窗口的方式(query、params)
Dec 25 Javascript
vue ssr+koa2构建服务端渲染的示例代码
Mar 23 Javascript
微信小程序使用radio显示单选项功能【附源码下载】
Dec 11 #Javascript
详解webpack编译多页面vue项目的配置问题
Dec 11 #Javascript
微信小程序使用checkbox显示多项选择框功能【附源码下载】
Dec 11 #Javascript
浅谈webpack编译vue项目生成的代码探索
Dec 11 #Javascript
微信小程序使用picker实现时间和日期选择框功能【附源码下载】
Dec 11 #Javascript
Mac中安装nvm的教程分享
Dec 11 #Javascript
jquery手机触屏滑动拼音字母城市选择器的实例代码
Dec 11 #jQuery
You might like
PHPMailer 中文使用说明小结
2010/01/22 PHP
PHP执行批量mysql语句的解决方法
2013/05/02 PHP
ThinkPHP模板判断输出Empty标签用法详解
2014/06/30 PHP
在PHP中使用FastCGI解析漏洞及修复方案
2015/11/10 PHP
mouse_on_title.js
2006/08/25 Javascript
JavaScript 学习笔记(六)
2009/12/31 Javascript
JQuery将文本转化成JSON对象需要注意的问题
2011/05/09 Javascript
jQuery EasyUI API 中文文档 - Spinner微调器使用
2011/10/21 Javascript
简介JavaScript中POSITIVE_INFINITY值的使用
2015/06/05 Javascript
SWFObject基本用法实例分析
2015/07/20 Javascript
基于JavaScript代码实现兼容各浏览器的设为首页和加入收藏
2016/01/07 Javascript
JavaScript判断用户名和密码不能为空的实现代码
2016/05/16 Javascript
实例讲解JavaScript中的this指向错误解决方法
2016/06/13 Javascript
Angular中使用ui router实现系统权限控制及开发遇到问题
2016/09/23 Javascript
Bootstrap复选框和单选按钮美化插件(推荐)
2016/11/23 Javascript
jQuery时间日期三级联动(推荐)
2016/11/27 Javascript
angular.JS实现网页禁用调试、复制和剪切
2017/03/31 Javascript
React中使用async validator进行表单验证的实例代码
2018/08/17 Javascript
详解webpack编译速度提升之DllPlugin
2019/02/05 Javascript
Easyui 关闭jquery-easui tab标签页前触发事件的解决方法
2019/04/28 jQuery
微信小程序后端(java)开发流程的详细步骤
2019/11/13 Javascript
[39:19]完美世界DOTA2联赛PWL S2 SZ vs LBZS 第二场 11.26
2020/11/30 DOTA
Python装饰器使用实例:验证参数合法性
2015/06/24 Python
Python编程中类与类的关系详解
2019/08/08 Python
linux下python中文乱码解决方案详解
2019/08/28 Python
Numpy对数组的操作:创建、变形(升降维等)、计算、取值、复制、分割、合并
2019/08/28 Python
详解CSS3中的box-sizing(content-box与border-box)
2019/04/19 HTML / CSS
纪伊国屋新加坡网上书店:Kinokuniya新加坡
2017/12/29 全球购物
国庆促销活动总结
2014/08/29 职场文书
12.4全国法制宣传日活动方案
2014/11/02 职场文书
学生检讨书范文
2015/01/27 职场文书
2016春季校长开学典礼致辞
2015/11/26 职场文书
2016年十一促销广告语
2016/01/28 职场文书
PostgreSQL存储过程实用脚本(二):创建函数入门
2021/04/05 PostgreSQL
pytorch通过训练结果的复现设置随机种子
2021/06/01 Python
如何让你的Nginx支持分布式追踪详解
2022/07/07 Servers