观察研究一下vue-loader如何作用于单文件组件的:
创建单文件组件:
app.vue:
webpack配置:
打包运行,可以看到 vue-loader对.vue文件第一次处理后的生成的代码是这样的:
// 这里的import语句使用webpack loader的内联再次对app.vue文件进行处理,
// 对app.vue使用vue-loader进行处理生成的js中拿到render和staticRenderFns
import { render, staticRenderFns } from "./app.vue?vue&type=template&id=5ef48958&"
// 对app.vue使用vue-loader进行处理拿到script
import script from "./app.vue?vue&type=script&lang=js&"
export * from "./app.vue?vue&type=script&lang=js&"
/* normalize component */
import normalizer from "!../node_modules/vue-loader/lib/runtime/componentNormalizer.js"
// 使用normalizer初始化为一个标准的vue组件
var component = normalizer(
script,
render,
staticRenderFns,
false,
null,
null,
null
)
/* hot reload */ // 热加载内容相关
if (module.hot) {
var api = require("C:\\Users\\huhao\\Desktop\\vue-loader-learn\\node_modules\\vue-hot-reload-api\\dist\\index.js")
api.install(require('vue'))
if (api.compatible) {
module.hot.accept()
if (!api.isRecorded('5ef48958')) {
api.createRecord('5ef48958', component.options)
} else {
api.reload('5ef48958', component.options)
}
module.hot.accept("./app.vue?vue&type=template&id=5ef48958&", function () {
api.rerender('5ef48958', {
render: render,
staticRenderFns: staticRenderFns
})
})
}
}
// component的options的__file属性标记了文件名
component.options.__file = "src/app.vue"
// component的exports被暴露出去了
export default component.exports
下面分析一下这个文件:
新建一个js文件填入上述代码,对这个文件调用webpack打包,在需要打印的地方做标记,将生成的main.js植入到页面中运行,查看控制台进行分析:
再次用loader处理拿到的render,staticRenderFns,script:
import { render, staticRenderFns } from "./app.vue?vue&type=template&id=5ef48958&"
// 对app.vue使用vue-loader进行处理拿到script
import script from "./app.vue?vue&type=script&lang=js&"
export * from "./app.vue?vue&type=script&lang=js&"
这里的内容就是template块内容和script块内容再次被vue-loader自身调用的结果
template块使用的是vue-template-compiler
标准化生成一个component:
/* normalize component */
import normalizer from "!../node_modules/vue-loader/lib/runtime/componentNormalizer.js"
// 使用normalizer初始化为一个标准的vue组件
var component = normalizer(
script,
render,
staticRenderFns,
false,
null,
null,
null
)
查看一下normalizeComponent函数:
打印出的component的结构:
代码最后一个部分将exports部分给导出去了作为一个options
注意,如果组件中script部分用的是Vue.extend 那么生成的exports是一个函数
官方文档中的叙述:
* 什么是staticRenderFunctions
*vue-loader中对vue-template-compiler的引用 即:解析template代码块时的片段
...
结论: vue-loader是一个webpack loader,用于处理.vue后缀的单文件组件。首先将.vue文件转换成相应内容,相应内容中又分别对template,script,和css区域进行其它loader的调用,最终返回一个js对象形式的组件数据。