搭建环境
获取地址:GitHub - vuejs/vue: This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core
安装依赖:npm i
安装 rollup:
npm i -g -rollup
修改dev脚本:添加 --sourcemap
"dev": "rollup -w -c scripts/config.js --sourcemap --environment TARGET:web-full-dev",
执行dev脚本:npm run dev
此处使用vue的版本是2.6
目录:
dist 发布目录
examples 范例
flow 试代码
node_modules
scripts 构建脚本
src 源码
compiler 编译器相关
core 核心代码
components 通用组件如keep-alive
global-api 全局api
instance 构造函数等
observer 响应式相关
util
vdom 虚拟DOM相关
......
术语解释:
runtime 仅包含运行时,不包含编译器
common cjs规范,适用于webpack1
esm es模块,用于webpack2+
umd universal module definition,兼容cjs和amd,用于浏览器,一般使用的都是这个版本。
入口文件
-c scripts/config.js //配置文件所在
TARGET:web-full-dev" //指明输出文件配置项
能够通过config.js找到对应的entry入口文件
// Runtime+compiler development build (Browser)
'web-full-dev': {
entry: resolve('web/entry-runtime-with-compiler.js'),
dest: resolve('dist/vue.js'),
format: 'umd',
env: 'development',
alias: { he: './entity-decoder' },
banner
},
所以默认是web开头的路径
const aliases = require('./alias')
const resolve = p => {
const base = p.split('/')[0]
if (aliases[base]) {
return path.resolve(aliases[base], p.slice(base.length + 1))
} else {
return path.resolve(__dirname, '../', p)
}
}
进入alias
module.exports = {
vue: resolve('src/platforms/web/entry-runtime-with-compiler'),
compiler: resolve('src/compiler'),
core: resolve('src/core'),
shared: resolve('src/shared'),
web: resolve('src/platforms/web'),
weex: resolve('src/platforms/weex'),
server: resolve('src/server'),
sfc: resolve('src/sfc')
}
找到了最终的路径
/Users/jerrychen/Desktop/vue-2.6/src/platforms/web/entry-runtime-with-compiler.js
//扩展$mount:解析模版
const mount = Vue.prototype.$mount
Vue.prototype.$mount = function (
el?: string | Element, //宿主元素
hydrating?: boolean
): Component {
el = el && query(el) //获取真实dom
......
}
解析模版相关选项,首先判断是否有render函数,所以render的优先级很高,再看template,最后是el。如果写了el,则可以省略$mount。template或者render需要加上$mount。
//检测render函数
if (!options.render) {
//再看template
let template = options.template
//解析template
if (template) {
if (typeof template === 'string') { //template:'#app' 选择器
if (template.charAt(0) === '#') {
template = idToTemplate(template)
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && !template) {
warn(
`Template element not found or is empty: ${options.template}`,
this
)
}
}
} else if (template.nodeType) { //dom节点
template = template.innerHTML
} else {
if (process.env.NODE_ENV !== 'production') {
warn('invalid template option:' + template, this)
}
return this
}
} else if (el) { //最后一种情况查看el选项
template = getOuterHTML(el)
}
//如何处理模版,编译渲染
if (template) {
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
mark('compile')
}
const { render, staticRenderFns } = compileToFunctions(template, {
outputSourceRange: process.env.NODE_ENV !== 'production',
shouldDecodeNewlines,
shouldDecodeNewlinesForHref,
delimiters: options.delimiters,
comments: options.comments
}, this)
//重新赋值给我们的选项
options.render = render
options.staticRenderFns = staticRenderFns
/* istanbul ignore