webpack代码分离 ensure 看了还不懂,你打我(转)
webpack异步加载的原理
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) 即可
说完了上面的原理。下面就实践一下
entry.js 依赖三个 js。
- Abtn-work.js 是封装了 abtn按钮点击后,才执行的业务逻辑
- Bbtn-work.js 是封装了 bbtn按钮点击后,才执行的业务逻辑
- 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打包后,形成
其实, 1.1… 2.2…就是我们ensure导出来的js文件
我们看看代码是如何加载的执行的,点击打包插入js后的html
可以看到,并没有加载 ensure导出来的 1.1…js 2.2…js
点击 abtn,
发现浏览器下载并加载了 1.1…js
点击 bbtn
发现浏览器下载并加载了 2.2…js
ok 全部完成
webpack代码分离 ensure 看了还不懂,你打我(转)的更多相关文章
- Webpack 代码分离
Webpack 代码分离 代码分离是 webpack 中最引人注目的特性之一. 你可以把你的代码分离到不同的 bundle 中,然后你就可以去按需加载这些文件. 总的来说, webpack 分离可以分 ...
- 详细!Mybatis-plus常用API全套教程,我就不信你看完还不懂!
前言 官网:Mybatis-plus官方文档 简化 MyBatis ! 创建数据库 数据库名为mybatis_plus 创建表 创建user表 DROP TABLE IF EXISTS user; C ...
- 深度分析:面试阿里,字节跳动,美团90%被问到的List集合,看完还不懂算我输
1 List集合 1.1 List概述 在Collection中,List集合是有序的,可对其中每个元素的插入位置进行精确地控制,可以通过索引来访问元素,遍历元素. 在List集合中,我们常用到Arr ...
- webpack代码分离CommonsChunkPlugin插件的使用(防止重复)
1.webpack.config.js中添加: const path = require('path'); + const webpack = require('webpack'); const HT ...
- Java的BIO和NIO很难懂?用代码实践给你看,再不懂我转行!
本文原题“从实践角度重新理解BIO和NIO”,原文由Object分享,为了更好的内容表现力,收录时有改动. 1.引言 这段时间自己在看一些Java中BIO和NIO之类的东西,也看了很多博客,发现各种关 ...
- webpack学习之—— Code Spliting(代码分离)
代码分离特性能够把代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件.代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间. 有三种常 ...
- 看完此文还不懂NB-IoT,你就过来掐死我吧...【转】
转自:https://www.cnblogs.com/pangguoming/p/9755916.html 看完此文还不懂NB-IoT,你就过来掐死我吧....... 1 1G-2G-3G-4G-5G ...
- 看完此文还不懂NB-IoT,你就过来掐死我吧...
看完此文还不懂NB-IoT,你就过来掐死我吧....... 1 1G-2G-3G-4G-5G 不解释,看图,看看NB-IoT在哪里? 2 NB-IoT标准化历程 3GPP NB-IoT的标准化始于20 ...
- 使用Webpack的代码分离实现Vue懒加载(译文)
当一个Vue的项目体积变得十分庞大的时候,使用Webpack的代码分离功能将Vue Components,routes或Vuex的代码进行分离并按需加载,会极大的提高App的首屏加载速度. 在Vue的 ...
随机推荐
- CentOS 下做端口映射/端口转发
CentOS 下做端口映射/端口转发==[实现目标]==================[服务器A]有2块网卡,一块接内网,一块接外网,[服务器B]只有一块内网网卡:访问[服务器A]的7890端口跳转 ...
- oralce plsql案例练习
以下plsql程序用的scott用户的dept,emp表. 案例1 --查询80,81,82,87年员工入职人数 set serveroutput on declare cursor cemp is ...
- 关于define和const
1.通过define定义的常量,在C语言里面一般叫宏定义.define的本质是简单的文本替换. 2.const定义一个变量,但是这个变量的值只能在定义的时候赋予,之后就不能被更改了. 如果变量声明中带 ...
- 【mac】mac os X更新High Sierra后出现的问题
今天更新了一下macbook pro的系统到10.13.1版本,出现了几个小问题,总结一下解决方案: git客户端无法使用 解决方案如下: http://blog.csdn.net/kedongjun ...
- NIO基础篇(三)
NIO里对性能提升最显著的是内存映射(memory mapping),内存访问的速度往往比文件访问的速度快几个数量级. 在内存映射之前,还需要看NIO的一些其他的特性. 缓冲区分片 slice()方法 ...
- bzoj 4546: codechef XRQRS [可持久化Trie]
4546: codechef XRQRS 可持久化Trie codechef上过了,bzoj上蜜汁re,看别人说要开5.2e5才行. #include <iostream> #includ ...
- c语言中的#ifdef和#ifndef
#include "stdio.h"#include "conio.h"#define MAX#define MAXIMUM(x,y) (x>y)?x:y ...
- 2018/2/14 设计模式学习笔记(一) 自己实现ArrayList,LinkedList和Iterator,以及在此过程中对于面向对象,面向接口,还有抽象类的一些思考感悟
因为本人目前为止学习编程不过七个月,所以后面的感悟对于一些大神来说可能嗤之以鼻,但对于一些刚刚入门的萌新来说在理解面向对象的思想上,以及抽象类和接口应该怎么设计等方面应该还是会有所帮助的 首先我们定义 ...
- MIT-线性代数笔记(7-11)
第 07 讲 求解 Ax=0 :主变量,特解 矩阵的秩Rank(A):矩阵主元的个数. 找出“主变量”pivotvariables,主列,即主元所在的列,其他列,称为自由列.(自由列表示可以自由或任意 ...
- 📉 Draggable Curve Control (English)
Conmajia 2012 Updated on Feb. 18, 2018 In Photoshop, there is a very powerful feature called Curve A ...