webpack-bundle.js原理
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原理的更多相关文章
- webpack最简单的入门教程里bundle.js之运行单步调试的原理解析
读这篇文章的朋友,请确保对webpack有最基础的认识. 您可以阅读我前一篇文章:Webpack 10分钟入门 来在本地运行一个Webpack的hello world项目.https://www.to ...
- 解读webpack的bundle.js
可能就是好奇心略重了,读了一下webpack打包后的bundle.js的代码,复杂的模块可能读不懂,但简单的hello world模块我还是能看懂的.没什么目的,就是想通过几个简单的模块,一条简单的w ...
- 解决webpack因新版本打包失败问题--ERROR in multi ./src/main.js ./dist/bundle.js
最近在学习webpack打包过程中遇到的一个问题向大家分享下! 创建了一个webpacksty的目录,目录下放着dist,src子目录,然后通过node环境下,npm init -y 初始化项目出现p ...
- webpac4k运行webpack .\src\main.js .\dist\bundle.js打包出错
打包的命令格式:webpack 要打包的文件的路径 打包好的输出文件的路径 运行webpack .\src\main.js .\dist\bundle.js 提示错误,错误信息如下: WARNING ...
- 在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 ...
- 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
- 解决 webpack .\src\main.js .\dist\bundle.js 错误
打包的命令格式:webpack 要打包的文件的路径 打包好的输出文件的路径 栗子: webpack .\src\main.js .\dist\bundle.js 提示错误,错误信息如下: 错误原因 w ...
- webpack+React.js
Webpack是目前基于React和Redux开发的应用的主要打包工具.我想使用Angular 2或其他框架开发的应用也有很多在使用Webpack. 当我第一次看到Webpack的配置文件时,它看起来 ...
- 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 一. 问题描述 在 ...
- 如何编写一个WebPack的插件原理及实践
_ 阅读目录 一:webpack插件的基本原理 二:理解 Compiler对象 和 Compilation 对象 三:插件中常用的API 四:编写插件实战 回到顶部 一:webpack插件的基本原理 ...
随机推荐
- HTML基础总纲
我看了很多博客感觉如果自己写的话还不一定有人家写的好,在介于我没有时间从这么细小的知识总结,那么人家总结好的我们为什么不用,完了之后在就自己的感受和不足之处在做补充. 我们一个的讲:主要参考: 一,H ...
- Bootstrap Table使用方法详解
http://www.jb51.net/article/89573.htm bootstrap-table使用总结 bootstrap-table是在bootstrap-table的基础上写出来的,专 ...
- dbporxy-mysql 协议流转图
dbproxy 支持 in 查询, 当in 中的字段 属于不同的分表时, QPS约为 5000左右, 如果为 等值查询, qps的30000左右 主要原因是 对于in操作,会产生多个不同分表的sql ...
- User类 新增共有属性Current ID
一.题目描述 每个用户有用户编号(id),用户名(name),密码(passwd)三个属性.其中: 用户编号(id)由系统自动顺序编号,用户名和密码都是字母.数字.符合的组合,新用户密码,默认“111 ...
- 直接线性变换解法(DLT)用于标定相机
直接线性变换法是建立像点坐标和相应物点物方空间坐标之间直接的线性关系的算法.特点:不需要内外方位元素:适合于非量测相机:满足中.低精度的测量任务:可以标定单个相机. 1 各坐标系之间的关系推导直接线性 ...
- Kali/Ubuntu无法和物理机之间复制粘贴解决办法
Vmware安装Linux,传统的vmtools已经被抛弃,当前建议使用Open-VM-tools 安装Open-VM-tools//Kali,Ubuntu: sudo apt install Ope ...
- Java 线程类别
Java 线程类别 守护线程和非守护线程 守护线程和非守护线程之前的唯一区别在于:是否阻止JVM的正常退出. JVM正常退出是与异常退出相对的概念,异常退出如调用System.exit(status) ...
- asp.net 网站在Apache下的配置,就这么简单
asp.net 网站在Apache下的配置,就这么简单 # # Virtual Hosts # # If you want to maintain multiple domains/hostnames ...
- javascript绑定事件addEventListener与attachEvent
1.eleObj.addEventListener(eventName,handle,useCapture); eleObj:DOM元素: eventName:事件名称.注意,这里的事件名称没有“ o ...
- rocksDB vs InnoDB vsTokuDB
原文地址 https://minervadb.com/index.php/2018/08/06/comparing-tokudb-rocksdb-and-innodb-performance-on-i ...