likes
comments
collection
share

webpack简单文件打包实例

作者站长头像
站长
· 阅读数 18

依赖版本

"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 = __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");

通过一个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 = __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标记

转载自:https://segmentfault.com/a/1190000041358845
评论
请登录