浅谈webpack编译vue项目生成的代码探索

网友投稿 494 2023-03-07


浅谈webpack编译vue项目生成的代码探索

本文介绍了webpack编译vue项目生成的代码探索,分享给大家,具体如下:

前言

往 main.js 里写入最简单的 vue 项目结构如下

import Vue from 'vue';

import App from './App.vue';

new Vue({

el: '#app',

template: '',

components: {

App

}

})

App.vue 如下

Core Docs

Forum

Community Chat

Twitter

vue-router

vuex

vue-loader

awesome-vue

编译生成后得到一个316kb的文件,而在316Kb中包含着什么,我很好奇想探索一番。

npm run build

> learning-in-vue@1.0.0 build /Users/everlose/workspace/github/learningInVue

> cross-env NODE_ENV=production webpack --progress --hide-modules

Hash: 18d868a423b48dc263e9

Version: webpack 3.9.1

Time: 3693ms

Asset Size Chunks Chunk Names

build.js 316 kB 0 [emitted] [big] main

build.js.map 399 kB 0 [emitted] main

代码分解

按顺序往下解读,本篇编译后的代码在这儿,如果只想看结论那么请拉到最后有一张结构梳理图。

webpack 模块机制

前面70行还是熟悉的 webpack 模块机制的基础代码,关于它的细致解读参见上一篇webpack模块机制,编译后的代码格式如下,并且我做了代码美化,并且插上了中文注释

/******/ (function(modules) { // webpackBootstrap

/******/ // The module cache

/******/ // 缓存模块,所有被加载过的模块都会成为installedModules对象的属性,靠函数__webpack_require__做到。

/******/ 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)

/******/ // 创造一个新模块并放入缓存中,i是模块标识,l意为是否加载此模块完毕,exports是此模块执行后的输出对象

/******/ 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 标为true代表模块执行完成。

/******/ module.l = true;

/******/

/******/ // Return the exports of the module 返回此模块输出的对象

/******/ return module.exports;

/******/ }

/******/

/******/

/******/ // expose the modules object (__webpack_modules__)

/******/ // webpack 私有变量,保存传入的modules,即所有的模块组成的数组

/******/ __webpack_require__.m = modules;

/******/

/******/ // expose the module cache

/******/ // 保存缓存中的模块数组

/******/ __webpack_require__.c = installedModules;

/******/

/******/ // define getter function for harmony exports

/******/ // 为 es6 exports 定义 getter

/******/ __webpack_require__.d = function(exports, name, getter) {

/******/ // 如果 exports 输出的对象本身不包含 name 属性时,定义一个。

/******/ if(!__webpack_require__.o(exports, name)) {

/******/ Object.defineProperty(exports, name, {

/******/ configurable: false,

/******/ enumerable: true,

/******/ get: getter

/******/ });

/******/ }

/******/ };

/******/

/******/ // getDefaultExport function for compatibility with non-harmony modules

/******/ // 解决 ES module 和 Common js module 的冲突,ES 则返回 module['default']

/******/ __webpack_require__.n = function(module) {

/******/ var getter = mhttp://odule && module.__esModule ?

/******/ function getDefault() { return module['default']; } :

/******/ function getModuleExports() { return module; };

/******/ __webpack_require__.d(getter, 'a', getter);

/******/ return getter;

/******/ };

/******/

/******/ // Object.prototype.hasOwnProperty.call

/******/ // 工具方法,判断是否object有property属性。

/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };

/******/

/******/ // __webpack_public_path__

/******/ // 大概和 webpack.config.js 的 output 有关吧,webpack 的公共路径

/******/ __webpack_require__.p = "/dist/";

/******/

/******/ // Load entry module and return exports 执行第一个依赖模块并且返回它输出。

/******/ return __webpack_require__(__webpack_require__.s = 0);

/******/ })

0号模块

导出一个全局变量,在web端就是指代window

/* 0 */

(function (module, exports) {

var g;

// This works in non-strict mode

g = (function () {

return this;

})();

try {

// This works if eval is allowed (see CSP)

g = g || Function("return this")() || (1, eval)("this");

} catch (e) {

// This works if the window reference is available

if (typeof window === "object")

g = window;

}

// g can still be undefined, but nothing to do about it...

// We return undefined, instead of nothing here, so it's

// easier to handle this case. if(!global) { ...}

module.exports = g;

/***/

}),

1号模块

实际上做的事情很明显,就是导出了 main.js 的代码,一个vue实例对象

/* 1 */

/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";

Object.defineProperty(__webpack_exports__, "__esModule", { value: true });

/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_vue__ = __webpack_require__(2);

/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__App_vue__ = __webpack_require__(6);

// 从2号模块导出的一个叫a的变量,就是Vue对象本身

new __WEBPACK_IMPORTED_MODULE_0_vue__["a" /* default */]({

el: '#app',

template: '',

components: {

App: __WEBPACK_IMPORTED_MODULE_1__App_vue__["a" /* default */]

}

});

/***/ })

2号模块

即是 Vue 源码本身,从114行一直到了10818行,一共是10705行代码,啧啧啧

webpack 有所配置,所以导出的 Vue 实际上是 vue/dist/vue.esm.js 的完整编译版本。

/* 2 */

/***/ (function (module, __webpack_exports__, __webpack_require__) {

"use strict";

/*!

* Vue.js v2.5.9

* (c) 2014-2017 Evan You

* Released under the MIT License.

*/

// 作用域指向__webpack_exports__,并把__webpack_require__(0)作为global,实际上就是window

// __webpack_require__(3).setImmediate)作为setsetImmediate参数传入函数

(function (global, setImmediate) {

// 省略近1w行的代码,关于vue原本本身的解读以后再做......

// 最终 export 出来一个叫 Vue$3的对象

/* harmony default export */

__webpack_exports__["a"] = (Vue$3);

/* WEBPACK VAR INJECTION */

}.call(__webpack_exports__, __webpack_require__(0), __webpack_require__(3).setImmediate))

}),

3,4,5号模块

都和 node_modules/setimmediate 有关,由于 vue 的 DOM 异步更新机制使用到了它,所以被引入。

这里也不做详解,只给出结构。

/* 3 */

/***/

(function (module, exports, __webpack_require__) {

// 省略代码...

// setimmediate attaches itself to the global object

__webpack_require__(4);

exports.setImmediate = setImmediate;

exports.clearImmediate = clearImmediate;

/***/

}),

/* 4 */

/***/

(function (module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */

(function (global, process) {

// 省略代码...

}.call(exports, __webpack_require__(0), __webpack_require__(5)))

/***/

}),

/* 5 */

/***/

(function (module, exports) {

// shim for using process in browser

var process = module.exports = {};

// 省略代码...

process.cwd = function () {

return '/'

};

process.chdir = function (dir) {

throw new Error('process.chdir is not supported');

};

process.umask = function () {

return 0;

};

/***/

}),

6号模块

和 App.vue 的解析有关,把 App.vue 中的 template 和 script 编译为一个 vue components,并把 style 标签内的样式插入到DOM中。

/* 6 */

/***/

(function (module, __webpack_exports__, __webpack_require__) {

"use strict";

// 返回具体 App.vue 中 的script 中的代码

var __WEBPACK_IMPORTED_MODULE_0__babel_loader_node_modules_vue_loader_lib_selector_type_script_index_0_App_vue__ = __webpack_require__(13);

// 把App.vue 的 template 解析为一堆 vue render 函数。

var __WEBPACK_IMPORTED_MODULE_1__node_modules_vue_loader_lib_template_compiler_index_id_data_v_66ce2159_hasScoped_false_buble_transforms_node_modules_vue_loader_lib_selector_type_template_index_0_App_vue__ = __webpack_require__(14);

// 注入vue文件里写入的css函数

function injectStyle(ssrContext) {

// 由此可知7号模块是编译并插入vue中的css到DOM上的

__webpack_require__(7)

}

// 12号模块用于输出components渲染函数

var normalizeComponent = __webpack_require__(12)

/* script */

/* template */

/* template functional */

var __vue_template_functional__ = false

/* styles */

var __vue_styles__ = injectStyle

/* scopeId */

var __vue_scopeId__ = null

/* moduleIdentifier (server only) */

var __vue_module_identifier__ = null

// 编译模块,混杂template和script。

var Component = normalizeComponent(

__WEBPACK_IMPORTED_MODULE_0__babel_loader_node_modules_vue_loader_lib_selector_type_script_index_0_App_vue__["a" /* default */ ],

__WEBPACK_IMPORTED_MODULE_1__node_modules_vue_loader_lib_template_compiler_index_id_data_v_66ce2159_hasScoped_false_buble_transforms_node_modules_vue_loader_lib_selector_type_template_index_0_App_vue__["a" /* default */ ],

__vue_template_funchttp://tional__,

__vue_styles__,

__vue_scopeId__,

__vue_module_identifier__

)

/* harmony default export */

__webpack_exports__["a"] = (Component.exports);

/***/

}),

7、8、9、10、11

都和样式有关,简言之就是7号模块加载8号模块获取css代码作为参数,并作为参数传入10号模块进行插入

太长也只大意上列出结构

7号模块由 style-loader 带入,把所有的css插入到 style 标签里

8号模块加载具体的css代码,

9号模块由css-loader代入,用于做css的sourceMap

10号模块返回具体插入动作函数,供7号模块调用

11号模块把所有的样式组成的数组转为字符串,给10号模块做插入。

/* 7 */

/***/

(function (module, exports, __webpack_require__) {

// style-loader: Adds some css to the DOM by adding a


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Mybatis中的config.xml配置文件详细解析
下一篇:Spring FTP上传下载工具类遇到问题小结
相关文章

 发表评论

暂时没有评论,来抢沙发吧~