当前位置: 首页 > news >正文

广州网站搜索排名石家庄网站建设开发

广州网站搜索排名,石家庄网站建设开发,网站1g空间多大,智慧团建网登录入口前言 在平时的开发中#xff0c;我们经常使用 import()实现代码分割和懒加载。在低版本的浏览器中并不支持动态 import()#xff0c;那 webpack 是如何实现 import() polyfill 的#xff1f; 原理分析 我们先来看看下面的 demo function component() {const btn docume…前言 在平时的开发中我们经常使用 import()实现代码分割和懒加载。在低版本的浏览器中并不支持动态 import()那 webpack 是如何实现 import() polyfill 的 原理分析 我们先来看看下面的 demo function component() {const btn document.createElement(button);btn.onclick () {import(./a.js).then((res) {console.log(动态加载a.js.., res);});};btn.innerHTML Button;return btn; }document.body.appendChild(component()); 点击按钮动态加载 a.js脚本查看浏览器网络请求可以发现a.js请求返回的内容如下 简单看实际上返回的就是下面这个东西 (self[webpackChunkwebpack_demo] self[webpackChunkwebpack_demo] || []).push([[src_a_js],{./src/a.js: () {},}, ]); 从上面可以看出 3 点信息 1.webpackChunkwebpack_demo 是挂到全局 window 对象上的属性 2.webpackChunkwebpack_demo 是个数组 3.webpackChunkwebpack_demo 有个 push 方法用于添加动态的模块。当a.js脚本请求成功后这个方法会自动执行。 再来看看 main.js 返回的内容 仔细观察动态 import 经过 webpack 编译后变成了下面的一坨东西 __webpack_require__.e(src_a_js).then(__webpack_require__.bind(__webpack_require__, ./src/a.js)).then((res) {console.log(动态加载a.js.., res);}); 上面代码中__webpack_require__ 用于执行模块比如上面我们通过webpackChunkwebpack_demo.push添加的模块里面的./src/a.js函数就是在__webpack_require__里面执行的。 __webpack_require__.e函数就是用来动态加载远程脚本。因此从上面的代码中我们可以看出 首先 webpack 将动态 import 编译成 __webpack_require__.e 函数 __webpack_require__.e函数加载远程的脚本加载完成后调用 __webpack_require__ 函数 __webpack_require__函数负责调用远程脚本返回来的模块获取脚本里面导出的对象并返回 源码分析及实现 如何动态加载远程模块 在开始之前我们先来看下如何使用 script 标签加载远程模块 var inProgress {}; // url: http://localhost:8080/src_a_js.main.js // done: 加载完成的回调 const loadScript (url, done) {if (inProgress[url]) {inProgress[url].push(done);return;}const script document.createElement(script);script.charset utf-8;script.src url;inProgress[url] [done];var onScriptComplete (prev, event) {var doneFns inProgress[url];delete inProgress[url];script.parentNode script.parentNode.removeChild(script);doneFns doneFns.forEach((fn) fn(event));if (prev) return prev(event);};script.onload onScriptComplete.bind(null, script.onload);document.head.appendChild(script); }; loadScript(url, done) 函数比较简单就是通过创建 script 标签加载远程脚本加载完成后执行 done 回调。inProgress用于避免多次创建 script 标签。比如我们多次调用loadScript(http://localhost:8080/src_a_js.main.js, done)时应该只创建一次 script 标签不需要每次都创建。这也是为什么我们调用多次 import(a.js)浏览器 network 请求只看到家在一次脚本的原因 实际上这就是 webpack 用于加载远程模块的极简版本。 __webpack_require__.e 函数的实现 首先我们使用installedChunks对象保存动态加载的模块。key 是 chunkId // 存储已经加载和正在加载的chunks此对象存储的是动态import的chunk对象的key是chunkId值为 // 以下几种 // undefined: chunk not loaded // null: chunk preloaded/prefetched // [resolve, reject, Promise]: chunk loading // 0: chunk loaded var installedChunks {main: 0, }; 由于 import() 返回的是一个 promise然后import()经过 webpack 编译后就是一个__webpack_require__.e函数因此可以得出__webpack_require__.e返回的也是一个 promise如下所示 const scriptUrl document.currentScript.src.replace(/#.*$/, ).replace(/\?.*$/, ).replace(/\/[^\/]$/, /);__webpack_require__.e (chunkId) {return Promise.resolve(ensureChunk(chunkId, promises)); };const ensureChunk (chunkId) {var installedChunkData installedChunks[chunkId];if (installedChunkData 0) return;let promise;// 1.如果多次调用了__webpack_require__.e函数即多次调用import(a.js)加载相同的模块只要第一次的加载还没完成就直接使用第一次的Promiseif (installedChunkData) {promise installedChunkData[2];} else {promise new Promise((resolve, reject) {// 2.注意此时的resolvereject还没执行installedChunkData installedChunks[chunkId] [resolve, reject];});installedChunkData[2] promise; //3. 此时的installedChunkData 为[resolve, reject, promise]var url scriptUrl chunkId;var error new Error();// 4.在script标签加载完成或者加载失败后执行loadingEnded方法var loadingEnded (event) {if (Object.prototype.hasOwnProperty.call(installedChunks, chunkId)) {installedChunkData installedChunks[chunkId];if (installedChunkData ! 0) installedChunks[chunkId] undefined;if (installedChunkData) {console.log(加载失败.....);installedChunkData[1](error); // 5.执行上面的reject那resolve在哪里执行呢}}};loadScript(url, loadingEnded, chunk- chunkId, chunkId);}return promise; }; __webpack_require__.e的主要逻辑在ensureChunk方法中注意该方法里面的第 1 到第 5 个注释。这个方法创建一个 promise并调用loadScript方法加载动态模块。需要特别主要的是返回的 promise 的 resolve 方法并不是在 script 标签加载完成后改变。如果脚本加载错误或者超时会在 loadingEnded 方法里调用 promise 的 reject 方法。实际上promise 的 resolve 方法是在脚本请求完成后在 self[webpackChunkwebpack_demo].push()执行的时候调用的 如何执行远程模块 远程模块是通过self[webpackChunkwebpack_demo].push()函数执行的 前面我们提到a.js请求返回的内容是一个self[webpackChunkwebpack_demo].push()函数。当请求完成会自动执行这个函数。实际上这就是一个 jsonp 的回调方式。该方法的实现如下 var webpackJsonpCallback (data) {var [chunkIds, moreModules] data;var moduleId,chunkId,i 0;for (moduleId in moreModules) {// 1.__webpack_require__.m存储的是所有的模块包括静态模块和动态模块__webpack_require__.m[moduleId] moreModules[moduleId];}for (; i chunkIds.length; i) {chunkId chunkIds[i];if (installedChunks[chunkId]) {// 2.调用ensureChunk方法生成的promise的resolve回调installedChunks[chunkId][0]();}// 3.将该模块标记为0表示已经加载过installedChunks[chunkId] 0;} };self[webpackChunkwebpack_demo] []; self[webpackChunkwebpack_demo].push webpackJsonpCallback.bind(null); 所有通过import()加载的模块经过 webpack 编译后都会被 self[webpackChunkwebpack_demo].push()包裹。 总结 在 webpack 构建编译阶段import()会被编译成类似__webpack_require__.e(src_a_js).then(__webpack_require__.bind(__webpack_require__, ./src/a.js))的调用方式 __webpack_require__.e(src_a_js).then(__webpack_require__.bind(__webpack_require__, ./src/a.js)).then((res) {console.log(动态加载a.js.., res);}); __webpack_require__.e()方法会创建一个 script 标签用于请求脚本方法执行完返回一个 promise此时的 promise 状态还没改变。 script 标签被添加到 document.head 后触发浏览器网络请求。请求成功后动态的脚本会自动执行此时self[webpackChunkwebpack_demo].push()方法执行将动态的模块添加到__webpack_require__.m属性中。同时调用 promise 的 resolve 方法改变状态模块加载完成。 脚本执行完成后最后执行 script 标签的 onload 回调。onload 回调主要是用于处理脚本加载失败或者超时的场景并调用 promise 的 reject 回调表示脚本加载失败
http://www.zqtcl.cn/news/357877/

相关文章:

  • 安阳汤阴县网站建设下载wix做的网站
  • 福清市建设局网站深圳工业设计协会封昌红
  • 网站建设公司做网站要多少费用重庆找工作哪个网站好
  • 苏州网站建设方法cnzz网站排名是怎么做的
  • 烟台网站建设服务专业的企业智能建站制造厂家
  • 网站信息查询制作闹钟网站
  • 永久免费个人网站申请注册禁止 wordpress ajax
  • 建设网站江西一个简单的游戏网站建设
  • 织梦大气婚纱影楼网站源码优化大师电脑版
  • 衡水企业网站制作报价怎么通过局域网建设网站
  • 服装网站建设课程知道ip怎么查域名
  • 上海政务网站建设上行10m企业光纤做网站
  • 杭州做公司网站aso搜索优化
  • 南京越城建设集团网站网站空间续费多少钱
  • 深圳nft网站开发公司如何制作微信公众号里的小程序
  • 做网站美工要学什么聊城网站建设电话
  • 南通个人网站建设快手秒刷自助网站
  • html5 做网站网站开发找工作
  • 聚成网站建设艺术公司网站定制中心
  • 阿里云上可以做网站吗十六局集团门户网
  • 门户网站建设询价函有哪些网站可以做设计挣钱
  • 如何建立自己网站奔奔网站建设
  • 自由做图网站做网站所用的工具
  • 广西南宁做网站专业网站建设案例
  • 视屏网站的审核是怎么做的群辉 搭建wordpress
  • 嘉兴网站快速排名优化衡阳网站建设制作
  • 建设公共资源交易中心网站成都APP,微网站开发
  • dede网站地图修改厦门百度seo
  • 可以做行程的网站网站详情怎么做的
  • 网站建设心得8000字营销型网站建设的注意事项