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插件的基本原理 ...
随机推荐
- Linux安装 jdk、tomcat、eclipse、mysql
概述如果需要在Linux下进行JavaEE的开发,我们需要安装如下软件: 安装JDK 安装步骤 0) 先将软件通过xftp5 上传到/opt 下 1) 解压缩到/opt tar -zxvf jdk. ...
- 【算法笔记】A1071 Speech Patterns
1071 Speech Patterns (25 分) People often have a preference among synonyms of the same word. For ex ...
- .NET熔断之Polly
1. Net Core 中有一个被.Net 基金会认可的库 Polly,可以用来简化熔断降级的处理.主要功能:重试(Retry):断路器(Circuit-breaker):超时检测(Timeout): ...
- Q72 编辑距离
给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 . 你可以对一个单词进行如下三种操作: 插入一个字符 删除一个字符 替换一个字符 示例 1: 输 ...
- testng XMl 参数化
方法一: 方法二: 方法三: (1)如果测试的数据较多的情况下,很显然这种方式不适合,那么可以通过@DataProvider生成测试数据,通过@Test(dataProvider = "&q ...
- Neo4j使用简单例子(转)
Neo4j Versions Most of the examples on this page are written with Neo4j 2.0 in mind, so they skip th ...
- MONO MessageBox 类
MessageBox类,负责提示各种消息. using System; using Android.App; using Android.Content; namespace Box { publ ...
- javascript中Function与Object
1. 先来一段代码: console.log(Function); // function Function() { [native code] } console.log(Object); // f ...
- Struts2方法调用的三种方式(有新的!调用方法的说明)
在Struts2中方法调用概括起来主要有三种形式 第一种方式:指定method属性 <action name="heroAction" class="com.ABC ...
- django+mysql+html简单demo之 views+html
#coding=utf-8 from __future__ import unicode_literals from django.shortcuts import render,render_to_ ...