本文介绍了webpack编译vue项目生成的代码探索,分享给大家,具体如下:
前言
往 main.js 里写入最简单的 vue 项目结构如下
el: '#app',template: '
App
}
})
App.vue 如下
编译生成后得到一个316kb的文件,而在316Kb中包含着什么,我很好奇想探索一番。
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模块机制,编译后的代码格式如下,并且我做了代码美化,并且插上了中文注释
0号模块
导出一个全局变量,在web端就是指代window
// 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实例对象
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',components: {
App: WEBPACK_IMPORTED_MODULE_1__App_vue["a" / default /]
}
});
/***/ })
2号模块
即是 Vue 源码本身,从114行一直到了10818行,一共是10705行代码,啧啧啧
webpack 有所配置,所以导出的 Vue 实际上是 vue/dist/vue.esm.js 的完整编译版本。
/*!
- 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 异步更新机制使用到了它,所以被引入。
这里也不做详解,只给出结构。
// setimmediate attaches itself to the global object
__webpack_require__(4);
exports.setImmediate = setImmediate;
exports.clearImmediate = clearImmediate;
//
}),/ 4 /
//
(function (module,__webpack_require__) {
/ WEBPACK VAR INJECTION /
(function (global,process) {
// 省略代码...
}.call(exports,__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中。
// 返回具体 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_functional,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号模块做插入。
(function (module,__webpack_require__) {
// style-loader: Adds some css to the DOM by adding a