# webpack打包出的文件解析

# 基础配置

我们先来准备一下基础的打包配置,然后研究下打包出来的文件结构和组成




 
// src/index.js
const name = require('./a')
console.log(name)



// src/a.js
module.exports = 'chenying'

入口文件index.js引入了a.js文件的导出




 








// webpack.config.js
const path = require('path')
module.exports = {
    mode: 'development', //默认有2种模式 production(会压缩代码) development
    entry: './src/index.js', //入口
    output: {
        filename: 'bundle.js', //打包后的文件名
        path: path.resolve(__dirname, 'dist'), //路径必须是绝对路径

    }
}

然后我们通过命令npx webpack进行webpack打包,会在dist目录下产出一个bundle.js文件,接下来我们主要来解析这个文件

# 打包出来的文件解析

我们先把bundle.js中的注释和一些暂时不会涉及的代码给去掉,得到如下代码




 
































(function (modules) { // webpackBootstrap
  // The module cache
  var installedModules = {};
  // 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;
  }
  return __webpack_require__(__webpack_require__.s = "./src/index.js");
})
  ({
    "./src/a.js":
      (function (module, exports) {
        eval("module.exports = 'chenying'\n\n//# sourceURL=webpack:///./src/a.js?");
      }),
    "./src/index.js":
      (function (module, exports, __webpack_require__) {
        eval("const name = __webpack_require__(/*! ./a */ \"./src/a.js\")\r\nconsole.log(name)\n\n//# sourceURL=webpack:///./src/index.js?");
      })

  });

我们可以发现bundle.js其实是一个自执行函数,其中传入的参数是一个键值对的对象,键为"./src/index.js"等打包之前涉及的文件名称,值是一个函数

然后我们看下这个自执行函数里面干了什么

首先我们发现函数里面自己实现了一个__webpack_require__方法,然后通过对象installedModules实现缓存,而__webpack_require__方法里面通过modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);将一个函数执行,最后将module.l = true;表示这个文件已经加载完毕,最后返回module.exports;

我们最后总体梳理一下:

  • 在自执行函数里面,自己先调用了一次__webpack_require__方法,参数是我们的webpack配置的入口文件路径"./src/index.js",然后__webpack_require__会将这个路径缓存到installedModules

  • 然后通过call调用./src/index.js这个键对应的处理函数

  • 调用处理函数的时候发现函数中含有__webpack_require__(/*! ./a */ \"./src/a.js\"),走同样的逻辑,将./src/a.js缓存到installedModules中,然后执行这个函数,返回module.exports,也就是返回了'chenying'

# 总结

我们可以大致总结一下webpack打包出来的文件

  • 将入口文件以及入口文件开始涉及到的其他文件转化为对应的键值对,然后作为自执行函数的参数传入

  • 自执行函数内部构造了一个__webpack_require__函数,通过这个函数依次的让对应的值(对应的函数)执行,最后返回mudole.exports

  • 就这样递归将全部文件串在了一起