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插件的基本原理 ...
随机推荐
- day 08 课后作业
# -*- coding: utf-8 -*-# @Time : 2018/12/27 17:27# @Author : Endless-cloud# @Site : # @File : day 8课 ...
- mysql 查询小技巧
数据字段中存放的是id集,形如 1,2,15,35 也可类推json格式 查询时不用拆分了, 用上 instr.concat搜索和连接字符串 查询fids中包含15的 select * from ...
- Django-工程搭建
-----环境安装 1.创建虚拟环境 mkvirtualenv django_py3_1.11 -p python3 2.安装django pip install django==1.11.11 ...
- Maven自动FTP远程部署
参照官网文档: https://maven.apache.org/plugins/maven-deploy-plugin/examples/deploy-ftp.html 1.在pom.xml中加入: ...
- HDU - 6133 启发式合并
题意:给出一棵树共\(n\)个顶点,每个顶点有一个权值\(val_i\),你需要对每个节点统计一个最优解 每个节点的解按照一定规则产生:取出该节点的子树下所有的顶点,把顶点任意排序成一个序列,设为\( ...
- [Xamarin.Android] 如何使用Google Map V2 (转帖)
Google Map v1已經在2013年的3月開始停止支援了,目前若要在你的Android手機上使用到Google Map,就必須要使用 到Google Map v2的版本.在Xamarin要使用G ...
- 【Maven学习】maven中依赖的配置详解
根元素project下的dependencies可以包含一个或者多个dependency元素,以声明一个或多个项目依赖.每个依赖可以包含的元素有: groupId,artifactId和version ...
- 分层 DAO层,Service层,Controller层、View层
前部分摘录自:http://blog.csdn.net/zdwzzu2006/article/details/6053006 DAO层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务 ...
- Java如何操作对象(bean)进行动态排序?
原文出自:https://blog.csdn.net/seesun2012 简介如题:Java如何操作对象(bean)进行动态排序?Java实体类(bean)动态排序? 原理:利用反射根据指定的属性值 ...
- SQL Server 获取(本周、本月、本旬、本季、本年)的某一天
/*------------------------------本周----------------------------------------*/ --本周第一天 ),getdate()) -- ...