源码

本文研究的源码地址为:https://github.com/collect-webpack/practice/tree/master/webpack-01

在本研究的前提是 entry 的配置为 string。随着 webpack 配置的不同。打包后的代码结构在有些部分也不相同,举个例子:

  • entry 为 String 类型,我们的第一个执行模块(下面注释中可以找到)是这样子:
/***/ (function(module, exports, __webpack_require__) {

eval("const str = __webpack_require__(/*! ./test.txt */ \"./src/test.txt\");\nconst test = __webpack_require__(/*! ./test */ \"./src/test.js\");\nconsole.log(str);\nconsole.log(test);\n\n//# sourceURL=webpack:///./src/index.js?");

/***/ }),
  • entry 为 Array 类型时:
/***/ 0:
/*!********************************************!*\
!*** multi ./src/index2.js ./src/index.js ***!
\********************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("__webpack_require__(/*! ./src/index2.js */\"./src/index2.js\");\nmodule.exports = __webpack_require__(/*! ./src/index.js */\"./src/index.js\");\n\n\n//# sourceURL=webpack:///multi_./src/index2.js_./src/index.js?"); /***/ })

可以看出当 entry 为数组时,两个chunk的执行顺序就是 entry 数组的配置顺序。而且他们的执行互不干扰。

编译后代码

/******/ (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
/******/ modules[moduleId].call(module.exports, module, module.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;
/******/
/******/ // define getter function for harmony exports
/******/ __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
/******/ __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
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like 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
/******/ __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 = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/index.js"); // 第一个执行模块
/******/ })
/************************************************************************/
/******/ ({ /***/ "./src/index.js":
/*!**********************!*\
!*** ./src/index.js ***!
\**********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) { eval("const str = __webpack_require__(/*! ./test.txt */ \"./src/test.txt\");\nconst test = __webpack_require__(/*! ./test */ \"./src/test.js\");\nconsole.log(str);\nconsole.log(test);\n\n//# sourceURL=webpack:///./src/index.js?"); /***/ }), /***/ "./src/test.js":
/*!*********************!*\
!*** ./src/test.js ***!
\*********************/
/*! no static exports found */
/***/ (function(module, exports) { eval("module.exports = {\n name: 'gaollard'\n}\n\n//# sourceURL=webpack:///./src/test.js?"); /***/ }), /***/ "./src/test.txt":
/*!**********************!*\
!*** ./src/test.txt ***!
\**********************/
/*! no static exports found */
/***/ (function(module, exports) { eval("module.exports = \"`hello world`\"\n\n//# sourceURL=webpack:///./src/test.txt?"); /***/ }) /******/ });

modules

由上面可以看出打包后的代码就是一个自执行函数里面,所以才会出现在全局作用域中找不到你在某一个具体模块定义的变量。这个函数接受一个对象类型参数 modules。我们去掉部分注释:

const modules = {
"./src/index.js": (function(module, exports, __webpack_require__) {
eval("const str = __webpack_require__(/*! ./test.txt */ \"./src/test.txt\");\nconst test = __webpack_require__(/*! ./test */ \"./src/test.js\");\nconsole.log(str);\nconsole.log(test);\n\n//# sourceURL=webpack:///./src/index.js?");
}), "./src/test.js": (function(module, exports) {
eval("module.exports = {\n name: 'gaollard'\n}\n\n//# sourceURL=webpack:///./src/test.js?");
}), "./src/test.txt": (function(module, exports) {
eval("module.exports = \"`hello world`\"\n\n//# sourceURL=webpack:///./src/test.txt?");
})
}

这样看就是清晰了。对象的 key 为模块的路径,value 为 一个函数,这个函数接受两个参数。

(1) module: 被缓存在 installedModules 中

var module = installedModules[moduleId] = {
i: moduleId, // 模块所在路径
l: false, // 是否已经加载(自执行)
exports: {} // 模块导出的结果
};

当使用 webpack_require 函数加载某个模块时,这个模块先执行,并且将执行结果赋值给 installedModules 对应 exports。并且标记该模块已经被加载了,第二次使用__webpack_require__

加载时就会直接返回 module.exports。这意味这一个模块只会被 eval执行一次。

名词解释

  • modules: 所有的模块集合
  • webpackBootstrap: 负责启动整个应用程序(上面这一段代码)
  • webpack_require: webpack 实现的加载函数
  • exports : 模块的导出值
  • installedModules: 缓存的模块集合

webpack: webpack简单打包后的代码(1)的更多相关文章

  1. webpack快速入门——打包后如何调试

    在配置devtool时,webpack给我们提供了四种选项. source-map:在一个单独文件中产生一个完整且功能完全的文件.这个文件具有最好的source map,但是它会减慢打包速度: che ...

  2. 分析 webpack 打包后的代码

    写在前面的:使用的 webpack 版本 3.0.0 一.开始 1. 准备 当前只创建一个文件 index.js,该文件作为入口文件,代码如下. console.log('hello, world') ...

  3. web项目打包后在代码中获取资源文件

    在web项目里面,有时代码里面需要引用一些自定义的配置文件,这些配置文件如果放在类路径下,项目经过打包后使用的相对路径也会发生变化,所以以下给出了三种解决方案. 一.properties下配置 在类路 ...

  4. webpack学习笔记——打包后直接访问页面,图片路径错误

    我说的这种图片路径错误是这样的,运行webpack-dev-server,一切正常,没有错误.当webpack之后,直接打开index页面,报错,图片找不到,找不到的原因是路径错误. 先看我的项目代码 ...

  5. vue2.4+vue-cli+webpack history模式打包后 刷新404

    开启HTML5 History Mode后,尤其需要server端的支持,官方文档里就有介绍:(传送门: https://router.vuejs.org/zh-cn/essentials/histo ...

  6. Vue项目用webpack打包后,预览时资源路径出错(文末有vue项目链接分享)

    最近用vue写了一些项目,项目写完之后需要打包之后才能放到网上展示,所以在这里记录一下项目打包的过程以及遇到的一些问题. --------------------------------------- ...

  7. webpack打包的基础原理-打包后的文件解读

    1.概念 本质上,webpack 基于node平台,利用 node 的各种api来实现 javascript 应用程序的一个静态模块的打包工具. 在打包过程中,构建依赖关系,并且实现模块引用预处理,以 ...

  8. webpack 的简单使用

    p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px "Helvetica Neue"; color: #323333 } p. ...

  9. 初识webpack——webpack四个基础概念

    前面的话 webpack是当下最热门的前端资源模块化管理和打包工具.它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源.当webpack处理应用程序时,它会递归地构建一个依赖关系图表 ...

随机推荐

  1. H5_0013:CSS特色样式集

    按比例变化,同时又限制最大宽高 ".start-wrap {", " width:40%;", " top: 83.21%;", " ...

  2. python接口自动化-requests-toolbelt处理multipart/form-data

    1.requests-toolbelt官方文档:https://pypi.org/project/requests-toolbelt/ 2.环境安装 pip install requests-tool ...

  3. 优化公式排版和Beamer相关知识

    做优化的同学可能会碰到排列形如 max    ******* s.t.   ***** = *        ***** > ***        ...    的格式 既要要求 max 和 s ...

  4. 01-SV入门及仿真环境搭建

    1.SV入门 参考书籍<SystemVerilog验证 测试平台编写指南> [美]克里斯·斯皮尔 著 2.仿真环境搭建 仿真工具:modelsim se 2019.2,它不仅支持Veril ...

  5. Homebrew安装Mysql后的两步必要的命令

    linxmousedeiMac:~ linxmouse$ mysql.server start Starting MySQL .. SUCCESS! linxmousedeiMac:~ linxmou ...

  6. format的使用

    v="敬爱可亲的{0},最喜欢在{1}地方干{2}" name1=input("名字>") lang=input("地点>") ...

  7. Matlab的sort函数

    1.Matlab自带排序函数sort用法     [Y,I] = sort(X,DIM,MODE)     sort函数默认Mode为'ascend'为升序,sort(X,'descend')为降序排 ...

  8. SQL语法(UNION,JOIN)

    SQL语法 union, union all UNION 操作符用于合并两个或多个 SELECT 语句的结果集. 注意,UNION 内部的每个SELECT语句必须拥有相同数量的列.列也必须拥有相似的数 ...

  9. 对象Bean与Map互转问题

    一.摘要 在实际开发过程中,经常碰到需要进行对象与map之间互转的问题,其实对于对象.Map 之间进行互转有很多种方式,下面我们一起来梳理一下: 利用 JSON 工具包,将对象转成字符串,之后再转成 ...

  10. 实用 docker history

    关闭安装认证, 开启tcp 端口 sudo vi /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd --insecur ...