webpack简单文件打包实例

依赖版本

"webpack": "^4.44.2", "webpack-cli": "^3.3.12"

一个简单的文件通过webpack打包
// 导出 console.log('index.js') module.exports = '导出内容'// 导入 let log = require('./log.js') console.log('index.js内容') console.log(log)

打包后文件
(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 //把index.js导出内容挂载到exports上 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; }// expose the modules object (__webpack_modules__) __webpack_require__.m = modules; // expose the module cache __webpack_require__.c = installedModules; // define getter function for harmony exports __webpack_require__.d = function (exports, name, getter) { if (!__webpack_require__.o(exports, name)) { Object.defineProperty(exports, name, { enumerable: true, get: getter }); } }; // define __esModule on exports __webpack_require__.r = function (exports) { if (typeof Symbol !== 'undefined' && Symbol.toStringTag) { Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); } Object.defineProperty(exports, '__esModule', { value: true }); }; // create a fake namespace object // mode & 1: value is a module id, require it // mode & 2: merge all properties of value into the ns // mode & 4: return value when already ns object // mode & 8|1: behave like require __webpack_require__.t = function (value, mode) { if (mode & 1) value = https://www.it610.com/article/__webpack_require__(value); if (mode & 8) return value; if ((mode & 4) && typeof value ==='object' && value && value.__esModule) return value; var ns = Object.create(null); __webpack_require__.r(ns); Object.defineProperty(ns, 'default', { enumerable: true, value: value }); if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function (key) { return value[key]; }.bind(null, key)); return ns; }; // getDefaultExport function for compatibility with non-harmony modules __webpack_require__.n = function (module) { var getter = module && module.__esModule ? function getDefault() { return module['default']; } : function getModuleExports() { return module; }; __webpack_require__.d(getter, 'a', getter); return getter; }; // Object.prototype.hasOwnProperty.call __webpack_require__.o = function (object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; // __webpack_public_path__ __webpack_require__.p = ""; // Load entry module and return exports return __webpack_require__(__webpack_require__.s = "./src/index.js"); }) ({"./src/index.js": /*! no static exports found */ (function (module, exports) { console.log('index.js内容') module.exports = '入口文件导出内容' }) });

打包文件分析特点分析
  1. 打包后的文件就是一个函数自调用,当前函数调用时传入一个对象。这个对象是一个键值对
  2. 这个键名就是当前被加载模块的文件名与某个目录的拼接()
  3. 这个键值就是一个函数,和 node.js 里的模块加载有一些类似,会将被加载模块中的内容包裹于一个函数中
  4. 这个函数在将来某个时间点上会被调用,同时会接收到一定的参数,利用这些参数就可以实现模块的加载操作
  5. 针对于上述的代码就相当于是将 {}(模块定义) 传递给了 modules
webpack简单文件打包实例
文章图片

__webpack_require__方法是 webpack 当中自定义的,它的核心作用就是返回模块的 exports。
单文件模块打包产出文件,会得到一个自调用函数,模块定义会传给modules,在文件中会调用__webpack_require__方法,传入主入口文件id,导出内容会挂载到module.exports上,最后被返回给
return __webpack_require__(__webpack_require__.s = "./src/index.js");

【webpack简单文件打包实例】通过一个CommonJS单步调试,结合打包后代码可以知道打包后文件一些方法的大概作用
// 定义对象用于缓存已加载过的模块 var installedModules = {}; //__webpack_require__方法是 webpack 自定义的一个加载方法,核心功能就是返回被加载模块中导出的内容(具体内部是如何实现的,后续再分析) function __webpack_require__(moduleId)// 将模块定义保存一份,通过 m 属性挂载到自定义的方法身上 __webpack_require__.m = modules; // o属性判断被传入的对象 obj 身上是否具有指定的属性*,如果有则返回 true __webpack_require__.o = function (object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; // define getter function for harmony exports __webpack_require__.d = function (exports, name, getter) { // 如果当前 exports 身上不具备 name 属性,则条件成立,添加成员属性name if (!__webpack_require__.o(exports, name)) { Object.defineProperty(exports, name, { enumerable: true, get: getter }); }// define __esModule on exports,给对象加一个标记,判断是否是esModule __webpack_require__.r = function (exports) { // 处理 esModule if (typeof Symbol !== 'undefined' && Symbol.toStringTag) { // Object.prototype.toString.call(exports),添加键,值是Module Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); } // 如果条件不成立,我们也直接在 exports 对象的身上添加一个 __esModule 属性,它的值就是true Object.defineProperty(exports, '__esModule', { value: true }); }; // 调用 t 方法之后,我们会拿到被加载模块中的内容 value,对于 value 来说我们可能会直接返回,也可能会处理之后再返回 __webpack_require__.t = function (value, mode) { if (mode & 1) value = https://www.it610.com/article/__webpack_require__(value); if (mode & 8) return value; if ((mode & 4) && typeof value ==='object' && value && value.__esModule) return value; var ns = Object.create(null); __webpack_require__.r(ns); Object.defineProperty(ns, 'default', { enumerable: true, value: value }); if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function (key) { return value[key]; }.bind(null, key)); return ns; };

CommonJS导入EsModule
// log.js文件下EsMoudle导出 export default "jack" export const age = 18; // index.js文件下CommonsJS导入EsModule let log = require('./log.js') console.log('index.js内容') console.log("log", log.default, log.age)

通过 yarn webpack打包
webpack默认支持CommonJS打包,而通过CommonJS规范引入EsMoudle导出对象,
webpack简单文件打包实例
文章图片

export default "jack"默认导出时,直接挂载default属性。而export const age = 18; 首先调用r方法标记为一个esModule,然后调用d方法往对象身上挂载一个age属性,并且给age属性通过一个getter方法。
webpack简单文件打包实例
文章图片

webpack简单文件打包实例
文章图片

EsModule导入CommonJS或者EsModule在于区分导入模块是否是EsModule,会通过r方法挂载EsModule标记

    推荐阅读