webpack打包后文件分析


平常遇到喜欢的页面总喜欢拿来欣赏一番,今天就以webpack+vue的项目为例分析一下打包后的源码。
环境:
webpack4.16
vue2.5.16

为了方便理解,先使用webpack打一个最简单的包(未使用vue),下面是混淆压缩前的伪代码

(function (modules) {
  var installedModules = {} // 缓存模块

   // 处理AMD commonjs ESModule
  function __webpack_require__(moduleId)() {  ...  return module.exports}
  __webpack_require__.m
  __webpack_require__.c
  __webpack_require__.d
  __webpack_require__.r
  __webpack_require__.n
  __webpack_require__.o
  __webpack_require__.p

  return __webpack_require__(__webpack_require__.s = "./src/index.js")
})(obj)

var obj = {

  // 入口js处理
  './src/index.js': (function(module, __webpack_exports__, __webpack_require__) {"use strict";
    eval(`__webpack_require__.r(__webpack_exports__);\n/* harmony import */
    var _js_home__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./js/home */ \"./src/js/home.js\");\n/* harmony import */ var _js_home__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_js_home__WEBPACK_IMPORTED_MODULE_0__);\n\r\n\r\n console.log('index.js')\n\n//# sourceURL=webpack:///./src/index.js?`); }), // 其他js处理 './src/js/home.js': { (function (module, exports,__webpack_require__) { eval("console.log('home') \n\n//# sourceURL=webpack:///./src/js/home.js?")
    })
  }
}

从结果来看,文件由一个立即执行函数(IIFE)组成,IIFE内部是webpack用于模块处理的逻辑,不需要关心,真正的业务逻辑以参数的形式传入,也就是obj,这个是我们需要重点关注的。
接下来是webpack+vue混淆压缩后的伪代码

!function(e){}([function(e, t, n){},function(e, t, n){},...])

通过和上一段代码对比,可以知道各个参数的含义

e: module t:export n:__webpack_require__

那么一个vue文件压缩后的是怎么样的,下面我从压缩文件中提取组成的代码片段



//-------------------template压缩前------------------ 
class="home"> <img class="logo" src="../images/logo.png"/> <h1>hello VueDemoh1> div> //-------------------template压缩后------------------ function (e, t, n) { "use strict"; var r = function () { var e = this.$createElement; this._self._c; return this._m(0) }, a = [function () { var e = this.$createElement, t = this._self._c || e; return t("div", { staticClass: "home" }, [t("img", { staticClass: "logo", attrs: { src: n(68) } }), this._v(" "), t("h1", [this._v("hello VueDemo")])]) }]; r._withStripped = !0, n.d(t, "a", function () { return r }), n.d(t, "b", function () { return a }) } //n(68): images/logo.82b9c7.png //function (e, t, n) { //e.exports = n.p + "images/logo.82b9c7.png" //} //n(0): window n(2): vue // -------------------script压缩前------------------ export default { data() { return { name: 'home' } }, mounted() {}, methods: {}, components: {} } // -------------------script压缩后------------------ function (e, t, n) { "use strict"; Object.defineProperty(t, "__esModule", { value: !0 }); n(45); t.default = { data: function () { return { name: "home" } }, mounted: function () {}, methods: {}, components: {} } } // -------------------style压缩前------------------ .home{font-size: 16px;text-align: center;} .logo{width: 100px;margin: 50px;} // -------------------style压缩后------------------ function (e, t, n) { var r = n(66); "string" == typeof r && (r = [ [e.i, r, ""] ]), r.locals && (e.exports = r.locals); (0, n(10).default)("d1dbaf94", r, !1, {}) } //n(66): //.home[data-v-324fb87d] {font-size: 0.21333333rem;text-align: center;} //.logo[data-v-324fb87d] {width: 1.33333333rem; margin: 0.66666667rem;} //function (e, t, n) { //(e.exports = n(11)(!1)).push([e.i, "\n.home[data-v-324fb87d] {\n font-size: 0.21333333rem;\n text-align: center;\n}\n.logo[data-v-324fb87d] {\n width: 1.33333333rem;\n margin: 0.66666667rem;\n}", ""]) //}

可以看到template模板中的t其实就是一个render函数,在render中构建一个vnode来描述原来DOM,之后如果修改template,vue就使用diff算法更新DOM。