bundle.js

源码

//a.js
import { log } from './b.js'
log('hello')
//b.js
export const log = function (m) {
console.log(m)
} export const error = function (m) {
console.error(m)
}

自执行函数

//其中 module0 和 module1 是我们的 a 和 b两个模块,不过也被一个函数包起来了。这段代码会把我们的模块放入一个数组,传给自执行函数,他来负责调用模块。

(function(modules) {
var installedModules = {};
function __webpack_require__(moduleId) {}
// Load entry module and return exports
return __webpack_require__(__webpack_require__.s = 0);
})
(function (modules) {})([module0, module1])

require模块

function __webpack_require__(moduleId){
//检查模块是否在缓存中
if(installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
//创建一个新的模块并将其放入缓存中
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
}
//执行模块方法
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); //将模块标记为已加载
module.l = true; //返回模块的导出
return module.exports;
}

require静态方法

__webpack_require__.m = modules;//获取模块列表
__webpack_require__.c = installedModules; //获取缓存模块列表
__webpack_require__.d = function(exports, name, getter) {//定义一个getter方法
if(!__webpack_require__.o(exports, name)) {
Object.defineProperty(exports, name, { enumerable: true, get: getter });
}
}
//如果此exports对象__esModule属性为true的话,表示这是一个es6的模块
__webpack_require__.r = function(exports) {
if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
}
Object.defineProperty(exports, '__esModule', { value: true });
} /**
* 创建一个伪命名空间对象
* mode & 1 value 是一个模块id,require(value)加载模块
* mode & 8 将value的所有属性合并到ns对象当中
* mode & 4 返回已经是nsobject到value
* mode & 8 | 1 绑定getter方法
*/
__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;
}
//兼容模块对象,给模块对象绑定getter方法
__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 = "";

依赖关系


因为webpack从entry开始,对每一个 module 都进行处理,碰到 require 之后就跳入到对应的 module 的处理,也就是递归的对这颗依赖树进行处理,这是典型的深度优先遍历的递归解法,而且是先序优先遍历。处理的过程是这样的 处理 main.js,记录入口 [main]
碰到 require(a),记录 [main, a]
进入到 a 模块,碰到语句 require(c), 记录下来 [main, a, c]
同理碰到 require(d),记录下来 [main, a, c, d]
返回到 main.js,下一句是 require('b'),记录下来 [main, a, c, d, b]
进入模块 b,碰到语句 require(e),记录下来[main, a, c, d, b, e]
返回,结束

打包后代码

(function(modules){
/**
* {
* "./src/b.js":fn(...),
* "./src/test.js":fn(...)
* }
*/
//缓存模块
var installedModules = {}; //引入模块的方法
function __webpack_require__(moduleId){
//检查模块是否在缓存中
if(installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
//创建一个新的模块并将其放入缓存中
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
}
//执行模块方法
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); //将模块标记为已加载
module.l = true; //返回模块的导出
return module.exports;
} //挂在静态方法
__webpack_require__.m = modules;//获取模块列表
__webpack_require__.c = installedModules; //获取缓存模块列表
/**
let obj={};
let age='age';
function getter() {
return 9;
}
Object.defineProperty(obj,age,{enumerable: true,get: getter});
console.log(obj.age)
*/
//检查exports对象上有没有挂载name属性,没有就挂载一个
__webpack_require__.d = function(exports, name, getter) {//定义一个getter方法
if(!__webpack_require__.o(exports, name)) {
Object.defineProperty(exports, name, { enumerable: true, get: getter });
}
}
/**
* 对象的Symbol.toStringTag属性,指向一个方法
* 在该对象上面调用Object.prototype.toString方法时,如果这个属性存在,它的返回值会出现在toString方法返回的字符串之中,表示对象的类型
* 也就是说,这个属性可以用来定制[object Object]或[object Array]中object后面的那个字符串
* ({[Symbol.toStringTag]: 'Foo'}.toString()) "[object Foo]"
*/
// define __esModule on exports 在导出对象上定义__esModule属性
//如果此exports对象__esModule属性为true的话,表示这是一个es6的模块
__webpack_require__.r = function(exports) {
if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
}
Object.defineProperty(exports, '__esModule', { value: true });
} /**
* 创建一个伪命名空间对象
* mode & 1 value 是一个模块id,require(value)加载模块
* mode & 8 将value的所有属性合并到ns对象当中
* mode & 4 返回已经是nsobject到value
* mode & 8 | 1 绑定getter方法
*/
__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;
} //兼容模块对象,给模块对象绑定getter方法
__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 = ""; //__webpack_require__.s 模块id
return __webpack_require__(__webpack_require__.s = "./src/test.js");
})
({
"./src/b.js":(function(module, __webpack_exports__, __webpack_require__){
"use strict";
//判断下exports是否是es模块内部方法挂载到exports对象上
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"log\", function() { return log; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"error\", function() { return error; });\nconst log = function (m) {\n console.log(m)\n }\n \n const error = function (m) {\n console.error(m)\n }\n\n//# sourceURL=webpack:///./src/b.js?");
}),
"./src/test.js":(function(module, __webpack_exports__, __webpack_require__){
"use strict";
//主模块,加载bmodule,并执行引入的module
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _b_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./b.js */ \"./src/b.js\");\n\nObject(_b_js__WEBPACK_IMPORTED_MODULE_0__[\"log\"])('hello')\n\n//# sourceURL=webpack:///./src/test.js?");
})
})

webpack-bundle.js原理的更多相关文章

  1. webpack最简单的入门教程里bundle.js之运行单步调试的原理解析

    读这篇文章的朋友,请确保对webpack有最基础的认识. 您可以阅读我前一篇文章:Webpack 10分钟入门 来在本地运行一个Webpack的hello world项目.https://www.to ...

  2. 解读webpack的bundle.js

    可能就是好奇心略重了,读了一下webpack打包后的bundle.js的代码,复杂的模块可能读不懂,但简单的hello world模块我还是能看懂的.没什么目的,就是想通过几个简单的模块,一条简单的w ...

  3. 解决webpack因新版本打包失败问题--ERROR in multi ./src/main.js ./dist/bundle.js

    最近在学习webpack打包过程中遇到的一个问题向大家分享下! 创建了一个webpacksty的目录,目录下放着dist,src子目录,然后通过node环境下,npm init -y 初始化项目出现p ...

  4. webpac4k运行webpack .\src\main.js .\dist\bundle.js打包出错

    打包的命令格式:webpack 要打包的文件的路径  打包好的输出文件的路径 运行webpack .\src\main.js .\dist\bundle.js 提示错误,错误信息如下: WARNING ...

  5. 在Visual Studio Code 运行 webpack ./src/main.js --output-filename ./dist/bundle.js --output-path . --mode development 提示 Module no t found:Error:Can't resolve' 'jquery' 是因为vs code还没安装jquery

    在Visual Studio Code 运行 webpack ./src/main.js --output-filename ./dist/bundle.js --output-path . --mo ...

  6. webpack打包错误 ERROR in multi ./src/main.js ./dist/bundle.js

    webpack打包错误 ERROR in multi ./src/main.js ./dist/bundle.js:https://www.jianshu.com/p/a55fb5bf75e1

  7. 解决 webpack .\src\main.js .\dist\bundle.js 错误

    打包的命令格式:webpack 要打包的文件的路径 打包好的输出文件的路径 栗子: webpack .\src\main.js .\dist\bundle.js 提示错误,错误信息如下: 错误原因 w ...

  8. webpack+React.js

    Webpack是目前基于React和Redux开发的应用的主要打包工具.我想使用Angular 2或其他框架开发的应用也有很多在使用Webpack. 当我第一次看到Webpack的配置文件时,它看起来 ...

  9. webpack.config.js配置遇到Error: Cannot find module '@babel/core'&&Cannot find module '@babel/plugin-transform-react-jsx' 问题

    下文是网上找到的方法,是因为版本冲突的原因,参照后安装7版本解决 cnpm install -D babel-loader@ babel-core babel-preset-env 一. 问题描述 在 ...

  10. 如何编写一个WebPack的插件原理及实践

    _ 阅读目录 一:webpack插件的基本原理 二:理解 Compiler对象 和 Compilation 对象 三:插件中常用的API 四:编写插件实战 回到顶部 一:webpack插件的基本原理 ...

随机推荐

  1. 【微信小程序】——rpx、px、rem等尺寸间关系浅析

    最近开发微信小程序,在写样式表的时候发现用PX的效果不太理想,而官方文档用rpx来做响应式布局单位,就仔细研究了下,在此做个小总结: 这里先引用官方定义的尺寸单位‘rpx’:可以根据屏幕宽度进行自适应 ...

  2. log 模块使用 (直接用的方法)

    前情提要: 生活中经常用到log 模块. 但是原生的log 模块复杂或者有许多不好用得地方, 在此记录一个经常用的log 的基本操作方法 一:首先导入模块 import logging.config ...

  3. day05 --class --home

    # -*- coding: utf-8 -*-# @Time : 2018/12/25 14:24# @Author : Endless-cloud# @Site : # @File : day05 ...

  4. 4.1.1 Choosing the SST Donor

    摘要: 出处:黑洞中的奇点 的博客 http://www.cnblogs.com/kelvin19840813/ 您的支持是对博主最大的鼓励,感谢您的认真阅读.本文版权归作者所有,欢迎转载,但请保留该 ...

  5. DataTables复杂表头

    工作上的需要,要做一个复杂的表头的DataTables thead如下 遇到的问题(详细问题可以浏览官网的答案 链接) 需自定义表头(thead),如果不自定义则会 Cannot read prope ...

  6. 华南理工大学“三七互娱杯”程序设计竞赛 HRY and codefire(概率期望DP)

    https://ac.nowcoder.com/acm/contest/874/A 题目:有两个账号 , 一开始都为0级 , 求任意一个账号升级到N的期望 要求:如果当前账号嬴了 , 就继续沿用当前的 ...

  7. 【性能测试】:关于测试F5负载均衡的问题

    在压测过程中,前置分发机的请求分发策略有多种,轮询,随机,DNS均衡,最小连接数等 问题出现的前提:因测试的一个系统对用户安全性校验较强,例如做交易之前,需要验证用户安全信息等 问题出现的现象:当lo ...

  8. Neo4j安装&入门&一些优缺点(转)

    本篇将介绍Neo4j的安装,入门,和自己使用了一段时间后发现的优点缺点,争取简洁和实用. 如果你是第一次接触Neo4j,并且之前也都没接触过类似的Graph Database的话,建议先浏览一下我之前 ...

  9. Gradle学习系列(三)

    上一篇我们已经学习了 Gradle 打包,那么这一节 就开始讲讲本章的第二版块:打包及使用Gradle过程中的常见错误问题. 有时候我们需要编辑一个开源项目之类的,希望把它导入了我们自己的IDE工具中 ...

  10. Mac 10.12常用软件清单

    链接: https://pan.baidu.com/s/1slds1OD 密码: 7m5t 配套教程:http://www.cnblogs.com/EasonJim/tag/mac/ 如果失效了,联系 ...