webpack打包后的文件如何異步加載模塊

一起探索最真實(shí)的世界

上一篇我們探討了 webpack打包后的文件如何在瀏覽器中運(yùn)行 涉及到了同步模塊的加載
本次我們對(duì)main.js進(jìn)行修改

main.js

// 異步加載 show.js
import('./show').then((show) => {
  // 執(zhí)行 show 函數(shù)
  show('Webpack');
});

webpack

打包后的文件

| -- dist
| ---- bundle.js
| ---- 0.bundle.js

這邊如果還是使用之前的webpack配置,會(huì)出現(xiàn)一個(gè)問(wèn)題,加載0.bundle.js時(shí)會(huì)出現(xiàn)加載失敗的問(wèn)題,我們可以看下我們之前配置
webpack.config.js

const path = require('path');

module.exports = {
  // JS 執(zhí)行入口文件
  entry: './main.js',
  output: {
    // 把所有依賴(lài)的模塊合并輸出到一個(gè) bundle.js 文件
    filename: 'bundle.js',
    // 輸出文件都放到 dist 目錄下
    path: path.resolve(__dirname, './dist'),
  }
};

我們把所有的模塊都輸出到當(dāng)前目錄的dist路徑下,在bundle文件中有一行代碼是

script.src = __webpack_require__.p + "" + chunkId + ".bundle.js";
// **
// __webpack_public_path__
__webpack_require__.p = "";

我們可以看到我們?nèi)ゼ虞d0.bundle.js時(shí)是直接加載index.html文件的同級(jí)目錄下的0.bundle.js,這肯定會(huì)加載失敗,那我們?cè)趺慈ジ淖冞@個(gè)webpack_require_.p呢,從注釋我們可以看到這個(gè)定義的是publicPath,webpack配置中就有publicPath

const path = require('path');

module.exports = {
  // JS 執(zhí)行入口文件
  entry: './main.js',
  output: {
    // 把所有依賴(lài)的模塊合并輸出到一個(gè) bundle.js 文件
    filename: 'bundle.js',
   // 配置publicPath
    publicPath: './dist/',
    // 輸出文件都放到 dist 目錄下
    path: path.resolve(__dirname, './dist'),
  }
};

此時(shí)重新

webpack

bundle.js

    (function (modules) { // webpackBootstrap
      // install a JSONP callback for chunk loading
      var parentJsonpFunction = window["webpackJsonp"];
      window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
        // 把moreModules加入到modules中,
        // then flag all "chunkIds" as loaded and fire callback
        var moduleId, chunkId, i = 0,
          resolves = [],
          result;
        for (; i < chunkIds.length; i++) {
          chunkId = chunkIds[i];
          if (installedChunks[chunkId]) {
            resolves.push(installedChunks[chunkId][0]);
          }
          installedChunks[chunkId] = 0;
        }
        for (moduleId in moreModules) {
          if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
            modules[moduleId] = moreModules[moduleId];
          }
        }
        if (parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
        while (resolves.length) {
          resolves.shift()();
        }
    
      };
    
      // The module cache
      var installedModules = {};
    
      // objects to store loaded and loading chunks
      var installedChunks = {
        1: 0
      };
    
      // The require function
      function __webpack_require__(moduleId) {
    
        // Check if module is in cache
        if (installedModules[moduleId]) {
          return installedModules[moduleId].exports;
        }
        // Create a new module (and put it into the cache)
        var module = installedModules[moduleId] = {
          i: moduleId,
          l: false,
          exports: {}
        };
    
        // Execute the module function
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
    
        // Flag the module as loaded
        module.l = true;
    
        // Return the exports of the module
        return module.exports;
      }
    
      // This file contains only the entry chunk.
      // The chunk loading function for additional chunks
      __webpack_require__.e = function requireEnsure(chunkId) {
        var installedChunkData = installedChunks[chunkId];
        // 如果installedChunkData 為0 那代表這個(gè)模塊已經(jīng)被加載直接返回Promise,并resolve
        if (installedChunkData === 0) {
          return new Promise(function (resolve) {
            resolve();
          });
        }
    
        // 如果installedChunkData非空且非0,那代表現(xiàn)在正在請(qǐng)求中,返回請(qǐng)求的promise
        if (installedChunkData) {
          return installedChunkData[2];
        }
    
        // setup Promise in chunk cache
        var promise = new Promise(function (resolve, reject) {
          installedChunkData = installedChunks[chunkId] = [resolve, reject];
        });
        installedChunkData[2] = promise;
    
        // start chunk loading
        var head = document.getElementsByTagName('head')[0];
        var script = document.createElement('script');
        script.type = "text/javascript";
        script.charset = 'utf-8';
        script.async = true;
        script.timeout = 120000;
    
        if (__webpack_require__.nc) {
          script.setAttribute("nonce", __webpack_require__.nc);
        }
        script.src = __webpack_require__.p + "" + chunkId + ".bundle.js";
        var timeout = setTimeout(onScriptComplete, 120000);
        script.onerror = script.onload = onScriptComplete;
    
        function onScriptComplete() {
          // avoid mem leaks in IE.
          script.onerror = script.onload = null;
          clearTimeout(timeout);
          var chunk = installedChunks[chunkId];
          if (chunk !== 0) {
            if (chunk) {
              chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));
            }
            installedChunks[chunkId] = undefined;
          }
        };
        head.appendChild(script);
    
        return promise;
      };
    
      // __webpack_public_path__
      __webpack_require__.p = "./dist/";
    
      // Load entry module and return exports
      return __webpack_require__(__webpack_require__.s = 0);
    })
    /************************************************************************/
    ([
      /* 0 */
      /***/
      (function (module, exports, __webpack_require__) {
    
        // 異步加載 show.js
        __webpack_require__.e /* import() */ (0).then(__webpack_require__.bind(null, 1)).then((show) => {
          // 執(zhí)行 show 函數(shù)
          show('Webpack');
        });
      })
    ]);

可以看到,webpack異步加載模塊是通過(guò)jsonp的方式,我們看到入口模塊函數(shù)中,先去調(diào)用 webpack_require.e(0) 加載模塊0.bundle.js
0.bundle.js

webpackJsonp([0],[
/* 0 */,
/* 1 */
/***/ (function(module, exports) {
function show(content) {
  window.document.getElementById('app').innerText = 'Hello,' + content;
}
// 通過(guò) CommonJS 規(guī)范導(dǎo)出 show 函數(shù)
module.exports = show;
/***/ })
]);

一旦通過(guò)動(dòng)態(tài)創(chuàng)建的script加載0.bundle.js后,就會(huì)執(zhí)行webapckJsonp··

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。 webpack介紹和使用 一、webpack介紹 1、由來(lái) ...
    it筱竹閱讀 11,460評(píng)論 0 21
  • GitChat技術(shù)雜談 前言 本文較長(zhǎng),為了節(jié)省你的閱讀時(shí)間,在文前列寫(xiě)作思路如下: 什么是 webpack,它要...
    蕭玄辭閱讀 12,892評(píng)論 7 110
  • 無(wú)意中看到zhangwnag大佬分享的webpack教程感覺(jué)受益匪淺,特此分享以備自己日后查看,也希望更多的人看到...
    小小字符閱讀 8,368評(píng)論 7 35
  • 這樣的生活狀態(tài)讓我越來(lái)越不喜歡北方的冬天,每一次的忍讓只會(huì)讓人得寸進(jìn)尺,人的自私真是不可估量。
    小小越前閱讀 153評(píng)論 0 0
  • 天冷啦,簡(jiǎn)單的晚餐
    左家半畝閑田閱讀 201評(píng)論 0 0

友情鏈接更多精彩內(nèi)容