详解webpack 最简打包结果分析


Posted in Javascript onFebruary 20, 2019

现在的 webpack 不再是入门噩梦,过去 webpack 最让人心塞的莫过于配置文件,而 webpack4 诞生随之而来的是无配置 webpack。

使用 webpack4,至少只需要安装 webpack 和 webpack cli。所以大家完全可以自己打一个最简单的包,还能修改插件对比前后的区别。

npm i webpack webpack-cli -D 安装后,因为 webpack4 会默认 src 为入口目录,所以先新建 src/index.js

// src/index.js
import { sth } from './shouldImport'
import other from './shouldImport'

let test = 'this is a variable'

export default {
 a: test + ',' + sth,
 other,
}

为了更了解 webpack  导入机制所以再新建 src/shouldImport.js。

// src/shouldImport.js
export let sth = 'something you need'

export default {
 others: '',
}

然后运行 node_modules/.bin/webpack --mode development 即可在 dist/main.js 看到打包后的文件。

但是默认设置中模块文件会被 eval 包裹导致不便查看,所以需要再在设置做一点修改,把 devtool 属性改为 'source-map'

// 在根目录新建 webpack.config.js 文件
module.exports = mode => {
 if (mode === 'production') {
  return {}
 }

 return {
  devtool: 'source-map',
 }
}

然后再打包应该就能看到类似一下的文件结构,开发环境下打包得到的文件自带注释,理解起来不难:

;(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
  // 执行模块函数(有点不懂为什么 this 要传入 module.exports)
  modules[moduleId].call(
   module.exports, // this
   module, // 模块对象本身
   module.exports, // 模块对象的 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

 // Object.prototype.hasOwnProperty.call
 __webpack_require__.o = function(object, property) {
  return Object.prototype.hasOwnProperty.call(object, property)
 }

 // define getter function for harmony exports
 // 为 ES6 export 定义 getter 函数
 __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
 // 于 export 定义 __esModule
 __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
 // value 是模块 id,必要
 // mode & 2: merge all properties of value into the ns
 // 合并 value 所有属性到 ns
 // mode & 4: return value when already ns object
 // ns 已经是对象时返回 value
 // mode & 8|1: behave like require
 // 表现如 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
 // 用于兼容非 ES6 模块的 getDefaultExport 函数
 __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
 }

 // __webpack_public_path__
 __webpack_require__.p = ''

 // Load entry module and return exports
 // 加载入口模块并返回 export
 return __webpack_require__((__webpack_require__.s = './src/index.js'))
})({
 './src/index.js':
  /*! exports provided: default */
  function(module, __webpack_exports__, __webpack_require__) {
   'use strict'
   __webpack_require__.r(__webpack_exports__) // 于 export 定义 __esModule
   /* harmony import */
   var _shouldImport__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
    './src/shouldImport.js'
   )

   let test = 'this is a variable'

   /* harmony default export */

   __webpack_exports__['default'] = {
    a: test + ',' + _shouldImport__WEBPACK_IMPORTED_MODULE_0__['sth'],
    other: _shouldImport__WEBPACK_IMPORTED_MODULE_0__['default'],
   }
  },

 './src/shouldImport.js':
  /*! exports provided: sth, default */
  function(module, __webpack_exports__, __webpack_require__) {
   'use strict'
   __webpack_require__.r(__webpack_exports__)
   /* harmony export (binding) */

   __webpack_require__.d(__webpack_exports__, 'sth', function() {
    return sth
   })
   let sth = 'something you need'

   __webpack_exports__['default'] = {
    others: '',
   }
  },
})

源文件中的所有 import export 都会转换为对应的辅助函数。

  • import 对应 __webpack_require__
  • export 对应 __webpack_exports__['default'] 直接赋值和 __webpack_require__.d。

整理一下整个流程:

  1. 定义 __webpack_require__ 及其辅助函数
  2. 使用 __webpack_require__ 引入入口模块
  3. __webpack_require__ 函数载入模块,将模块放到模块缓存
  4. 调用模块
    1. 同样使用 __webpack_require__ 读取依赖(回到第 3 步)
    2. 运行模块内部功能
    3. 使用 __webpack_exports__['default'] 直接赋值和 __webpack_require__.d 输出
  5. 运行结束

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript公共脚本库系列(一): 弹出层脚本
Feb 24 Javascript
JS中实现replaceAll的方法(实例代码)
Nov 12 Javascript
javascript获取函数名称、函数参数、对象属性名称的代码实例
Apr 12 Javascript
使用jquery实现放大镜效果
Sep 02 Javascript
AngularJs中route的使用方法和配置
Feb 04 Javascript
JS实现的自定义显示加载等待图片插件(loading.gif)
Jun 17 Javascript
详解用webpack2.0构建vue2.0超详细精简版
Apr 05 Javascript
Vue单页式应用(Hash模式下)实现微信分享的实例
Jul 21 Javascript
jQuery Dom元素操作技巧
Feb 04 jQuery
Vue自定义过滤器格式化数字三位加一逗号实现代码
Mar 23 Javascript
AngularJS实现的自定义过滤器简单示例
Feb 02 Javascript
vue 解决data中定义图片相对路径页面不显示的问题
Aug 13 Javascript
jQuery表单元素过滤选择器用法实例分析
Feb 20 #jQuery
jQuery内容过滤选择器与子元素过滤选择器用法实例分析
Feb 20 #jQuery
小程序红包雨的实现示例
Feb 19 #Javascript
vue动态添加路由addRoutes之不能将动态路由存入缓存的解决
Feb 19 #Javascript
jQuery选择器之基本过滤选择器用法实例分析
Feb 19 #jQuery
Vue 实现手动刷新组件的方法
Feb 19 #Javascript
jQuery选择器之层次选择器用法实例分析
Feb 19 #jQuery
You might like
php mysql操作mysql_connect连接数据库实例详解
2016/12/26 PHP
php判断目录存在的简单方法
2019/09/26 PHP
laravel框架中间件简单使用方法示例
2020/01/25 PHP
YII2框架中查询生成器Query()的使用方法示例
2020/03/18 PHP
理解 JavaScript 预解析
2009/10/25 Javascript
jQuery 获取对象 根据属性、内容匹配, 还有表单元素匹配
2010/05/31 Javascript
jquery.Ajax()方法调用Asp.Net后台的方法解析
2014/02/13 Javascript
js中一维数组和二位数组中的几个问题示例说明
2014/07/17 Javascript
jquery插件jSignature实现手动签名
2015/05/04 Javascript
Jquery解析json字符串及json数组的方法
2015/05/29 Javascript
jquery实现简单的表单验证
2015/11/17 Javascript
jQuery基于cookie实现的购物车实例分析
2015/12/24 Javascript
基于JavaScript实现表单密码的隐藏和显示出来
2016/03/02 Javascript
JavaScript中setTimeout和setInterval函数的传参及调用
2016/03/11 Javascript
JS实现HTML表格排序功能
2016/08/05 Javascript
JS实现焦点图轮播效果的方法详解
2016/12/19 Javascript
webpack打包js文件及部署的实现方法
2017/12/18 Javascript
ES6 迭代器与可迭代对象的实现
2019/02/11 Javascript
node.js ws模块搭建websocket服务端的方法示例
2019/04/25 Javascript
寻找网站后台地址的python脚本
2014/09/01 Python
python开发之thread实现布朗运动的方法
2015/11/11 Python
用python爬取租房网站信息的代码
2018/12/14 Python
深入浅析python的第三方库pandas
2020/02/13 Python
django项目中新增app的2种实现方法
2020/04/01 Python
什么是Python变量作用域
2020/06/03 Python
Nike爱尔兰官方网站:Nike.com (IE)
2018/03/12 全球购物
美国购买当代和现代家具网站:MODTEMPO
2018/07/20 全球购物
师范生实习个人的自我评价
2013/09/28 职场文书
《问银河》教学反思
2014/02/19 职场文书
母亲节感恩寄语
2014/02/21 职场文书
学校班班通实施方案
2014/06/11 职场文书
党支部工作总结2015
2015/04/01 职场文书
夫妻吵架保证书
2015/05/08 职场文书
2019年预备党员的思想汇报:加深对党的认知
2019/09/25 职场文书
SpringBoot使用ip2region获取地理位置信息的方法
2022/06/21 Java/Android
SQL Server数据库的三种创建方法汇总
2023/05/08 MySQL