webpack异步加载的原理
把一些js模块给独立出一个个js文件,然后使用这个 模块的时候,webpack会构造script dom元素,浏览器会自动帮我们发起请求,去请求这个js文件
使用了异步加载,异步的文件会单独打包出来,浏览器运行的时候并不会一开始就请求出来,而是在调用这个文件的时候浏览器才会对此js文件发起请求.
举个例子:当我们项目用到统计图的时候,初始的时候并不会调用chart插件,只有点击了生成统计图按钮才会显示出来,这个时候我们就可以利用webpack的异步加载,用户点击了按钮,浏览器才会去下载chart.js.
下面这段代码是常规的操作,在点击的时候,才去加载chart,等chart加载完成后,在利用chart的对象去执行我们的操作
Btn.click(function() {
//获取head
var head = document.getElementsByTagName('head')[0];
//创建 <script>
var script = document.createElement('script');
script.src = "http://www.xxx.com/chart.js"
//添加到head节点中
head.appendChild(script);
})
那么用webpack要怎么操作呢?
// a.js
Btn.click(function() {
require.ensure([], function() {
var chart = require('./chart.js') //chart.js放在我们当前目录下
})
})
[]:require.ensure所依赖的其他 异步加载的模块,例如:如果a,c,d都是异步加载的,a中需要c,d,那么a下载之前,就要先下载c,d
// a.js
//require.ensure(['c','d'], function() {...})
分析一下:require.ensure这个函数是一个代码分离的分割线,表示 回调里面的require 是我们想要进行分割出去的,即require(’./chart.js’),把chart.js分割出去,形成一个 webpack打包的单独js文件。
如果ensure里面写一些同步的require的话,是不会单独被打包
实践一下:
我们创建async.js,sync.js和utils.js
// index.html中添加一个按钮
<button id="btn">btn</button>
// sync.js
export const radom = (x) => {
return parseInt(Math.radom()*10)*x;
}
//utils.js
export const add = (x,y) => {
return x+y;
}
// async.js // 点击按钮异步加载utils.js
import './sync'; // 引用同步的模块
document.getElementById('btn').onclick = ()=>{
require.ensure([], function() {
var bwork = require('./util')
console.log(bwork.add(1,2));
})
}
最后在入口的文件引用async.js
import './js/async'; // 引用异步模块
...
ReactDOM.render(
...,
document.querySelector('.container-index')
);
打包的结果(1.js文件是异步文件单独提出来的结果):
最后在浏览器中运行index.html
可以看到,只有在点击按钮的时候,浏览器才会请求1.js文件