webpack核心理念浅析
这段时间在推敲本人手写一个构建工具,不过在这之前,咱们先试着梳理一下webpack的理念,毕竟它山之石可以攻玉,有助于咱们想好该如何设计本人的我的项目。
简介
Webpack is a static module bundler for modern JavaScript applications.
这是对于webpack的介绍,实质上,他就是一个打包器。将js模块打包成一个或者多个。实现如下代码里的能力:
a.js + b.js + c.js. => bundle.js
打包器呈现的起因,在此不多讲,网上有很多文章都讲过了。接下来咱们讲一讲webpack把多个js文件打包成一个bundle文件的外围思路是什么。
从构建产物反推外围流程
Webpack 是一个宏大的体系,如果从源码的角度,剖析从头到尾的流程,那么就会过于简单,也没必要。毕竟咱们学习的次要是外围设计理念。
那么,咱们能够试着从后果反推过程,从打包后的代码来剖析,webpack的思路。
在 mode: ‘none’, devtool: ‘cheap-source-map’,的配置下,咱们能够看到打包进去的代码大略长这个样子:
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["Magotan"] = factory(); else root["Magotan"] = factory();})(window, function(){ return (function(modules){ // xxxx })([ //xxxx ])['default']})
不言而喻的是这是一个IIFE,简化一下,在加上具体的实现代码,就成了上面这样:
(function webpackUniversalModuleDefinition() { exports["Magotan"] = (function (modules) { 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; } return __webpack_require__(0); })([ /* 0 */ //模块数组列表 数组下标即为模块id (function (module, __webpack_exports__, __webpack_require__) { __webpack_exports__["default"] = ({ getInstance: function getInstance() { if (magotan === null) { throw new Error('未初始化实例,请先通过config初始化'); } return magotan; }, }), /* 1 */ (function (module, exports, __webpack_require__) { var toObject = __webpack_require__(2); var $keys = __webpack_require__(4); __webpack_require__(21)('keys', function () { return function keys(it) { return $keys(toObject(it)); }; }); }), // ...}); ])['default'];})()
通过下面的代码咱们能够看出,咱们将我的项目中所有应用到的模块的代码以及依赖关系存在一个modules的数组中,而后通过 webpack自定义的require办法,从入口文件,即id = 0 的模块为终点,递归执行模块。
至此咱们能够剖析得出,webpack外围流程就是两步
- reslove modules阶段 递归解析 产出 Dependency graphs
Bundle 阶段 将上个阶段的产物,组装成数组并用函数包裹,从入口文件开始递归执行
后续
无理分明了webpack的设计思路之后,更多的就是具体实现上的问题,比方如何拿到模块之间的关系(利用AST),如何保障不呈现循环援用(利用installedModules 对象) 等等,更多的内容会在后续文档中有介绍。