摘要:笔者系贡献者之一官方说明简单来说就是将文件变成,然后放入浏览器运行。部分首先分析部分从做右到左,也就是被先后被和处理过了。源码解析之二源码解析之三写作中源码解析之四写作中作者博客作者微博
官方说明笔者系 vue-loader 贡献者(#16)之一
vue-loader is a loader for Webpack that can transform Vue components written in the following format into a plain JavaScript module
简单来说就是:将 .vue 文件变成 .bundle.js,然后放入浏览器运行。
观察输入输出 输入测试是最好的文档,所以我们从测试用例开始分析,找到test/fixture/basic.vue,内容如下:
输出{{msg}}
通过运行测试之后,可以得到以下输出,但是由于文件巨大,笔者只抽出部分开始分析,如下
/* 2 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); // CONCATENATED MODULE: ./node_modules/babel-loader/lib!./lib/selector.js?type=script&index=0&bustCache!./test/fixtures/basic.vue /* harmony default export */ var basic = ({ data() { return { msg: "Hello from Component A!" }; } }); // CONCATENATED MODULE: ./lib/template-compiler?{"id":"data-v-b647d0ce","hasScoped":false,"buble":{"transforms":{}}}!./lib/selector.js?type=template&index=0&bustCache!./test/fixtures/basic.vue var render = function() { var _vm = this var _h = _vm.$createElement var _c = _vm._self._c || _h return _c("h2", { staticClass: "red" }, [_vm._v(_vm._s(_vm.msg))]) } var staticRenderFns = [] render._withStripped = true var esExports = { render: render, staticRenderFns: staticRenderFns } /* harmony default export */ var fixtures_basic = (esExports); if (false) { module.hot.accept() if (module.hot.data) { require("vue-hot-reload-api") .rerender("data-v-b647d0ce", esExports) } } // CONCATENATED MODULE: .!./test/fixtures/basic.vue var disposed = false function injectStyle (ssrContext) { if (disposed) return __webpack_require__(3) } var normalizeComponent = __webpack_require__(8) /* 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 var Component = normalizeComponent( basic, fixtures_basic, __vue_template_functional__, __vue_styles__, __vue_scopeId__, __vue_module_identifier__ ) Component.options.__file = "test/fixtures/basic.vue" if (Component.esModule && Object.keys(Component.esModule).some(function (key) { return key !== "default" && key.substr(0, 2) !== "__"})) { console.error("named exports are not supported in *.vue files.")} })()}分析输出
以上的输出就是最终可以拿到浏览器上运行的 javaScript,尽管笔者已经删除了一些会影响理解的部分代码,但是这么直接观察这个文件,难免还是无从下手。
那么我们继续细化分析步骤,vue-loader 将 basic.vue 编译到最终输出的 bundle.js 的过程中,其实调用了四个小的 loader。它们分别是:
selector
style-compiler
template-compiler
babel-loader
以上四个 loader ,除了 babel-loader 是外部的package,其他三个都存在于 vue-loader 的内部(lib/style-compiler 和 lib/template-compiler 和 lib/selector)。
首先 vue-loader 将 basic.vue 编译成以下内容
/* script */ import __vue_script__ from "!!babel-loader!../../lib/selector?type=script&index=0&bustCache!./basic.vue" /* template */ import __vue_template__ from "!!../../lib/template-compiler/index?{"id":"data-v-793be54c","hasScoped":false,"buble":{"transforms":{}}}!../../lib/selector?type=template&index=0&bustCache!./basic.vue" /* styles */ import __vue_styles__ from "!!vue-style-loader!css-loader!../../lib/style-compiler/index?{"vue":true,"id":"data-v-793be54c","scoped":false,"hasInlineConfig":false}!../../lib/selector?type=styles&index=0&bustCache!./basic.vue" var Component = normalizeComponent( __vue_script__, __vue_template__, __vue_template_functional__, __vue_styles__, __vue_scopeId__, __vue_module_identifier__ )
为了方便理解,笔者删除修改了一些内容。
在三个 import 语句中,不管它们用了多少个不同的 loader 去加载,loader chain 的源头都是 basic.vue。
JavaScript 部分首先分析 script 部分
/* script */ import __vue_script__ from "!!babel-loader!../../lib/selector?type=script&index=0&bustCache!./basic.vue"
从做右到左,也就是 basic.vue 被先后被 selector 和 babel-loader 处理过了。
selector(参数type=script) 的处理结果是将 basic.vue 中的 javaScript 抽出来之后交给babel-loader去处理,最后生成可用的 javaScript
Template 部分再来分析 template 部分
/* template */ import __vue_template__ from "!!../../lib/template-compiler/index?{"id":"data-v-793be54c","hasScoped":false,"buble":{"transforms":{}}}!../../lib/selector?type=template&index=0&bustCache!./basic.vue"
同样的,从左到右,basic.vue 先后被 selector 和 template-compiler 处理过了。
selector (参数type=template) 的处理结果是将 basic.vue 中的 template 抽出来之后交给 template-compiler 处理,最终输出成可用的 HTML。
Style 部分最后分析 style 部分
/* styles */ import __vue_styles__ from "!!vue-style-loader!css-loader!../../lib/style-compiler/index?{"vue":true,"id":"data-v-793be54c","scoped":false,"hasInlineConfig":false}!../../lib/selector?type=styles&index=0&bustCache!./basic.vue"
style 涉及的 loader 较多,一个一个来分析, 从上代码可知,basic.vue 先后要被 selector, style-compiler, css-loader 以及 vue-style-loader 处理。
selector (参数type=style) 的处理结果是将 basic.vue 中的 css 抽出来之后交给 style-compiler 处理成 css, 然后交给 css-loader 处理生成 module, 最后通过 vue-style-loader 将 css 放在 里面,然后注入到 HTML 里。
注意,这里之所以没有用 style-loader 是因为 vue-style-loader 是在 fork 了 style-loader 的基础上,增加了后端绘制 (SSR) 的支持。具体的不同,读者可以查看官方文档,笔者这里不再累述。
后续通过上面的介绍,想必读者已经对 vue-loader 以及它涉及的几个 loader 的作用有了一个大概的了解。
那么接下来,在后续文章中我们来开始一个个分析这几个 loader 的源码。
vue-loader 源码解析之二 selector
vue-loader 源码解析之三 style-compiler (写作中)
vue-loader 源码解析之四 template-compiler (写作中)
作者博客
作者微博
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/90064.html
摘要:当前正在处理的节点,以及该节点的和等信息。源码解析之一整体分析源码解析之三写作中源码解析之四写作中作者博客作者作者微博 笔者系 vue-loader 贡献者之一(#16) 前言 vue-loader 源码解析系列之一,阅读该文章之前,请大家首先参考大纲 vue-loader 源码解析系列之 整体分析 selector 做了什么 const path = require(path) co...
摘要:相关的内容为这样对于一个处理的第二阶段也就结束了,通过去拦截不同类型的,并返回新的,跳过后面的的执行,同时在内部会剔除掉,这样在进入到下一个处理阶段的时候,不在使用的范围之内,因此下一阶段便不会经由来处理。 文章首发于个人github blog: Biu-blog,欢迎大家关注~ Webpack 系列文章: Webpack Loader 高手进阶(一)Webpack Loader 高手...
摘要:以为例,编写来帮助我们完成重复的工作编译压缩我只要执行一下就可以检测到文件的变化,然后为你执行一系列的自动化操作,同样的操作也发生在这些的预处理器上。的使用是针对第三方类库使用各种模块化写法以及语法。 showImg(https://segmentfault.com/img/bVbtZYK); 一:前端工程化的发展 很久以前,互联网行业有个职位叫做 软件开发工程师 在那个时代,大家可能...
阅读 2900·2021-11-23 09:51
阅读 1545·2021-11-15 11:36
阅读 3004·2021-10-13 09:40
阅读 1861·2021-09-28 09:35
阅读 13039·2021-09-22 15:00
阅读 1366·2019-08-29 13:56
阅读 2923·2019-08-29 13:04
阅读 2696·2019-08-28 18:06