vue源代码学习-intro

Vue鼎鼎大名不用过多介绍,在GitHub上已经收获了8W+Star, 是一个渐进式的用于构建界面的框架,并且只关注视图层。工作中使用vue,也让自己对vue本身的实现产生了好奇,断断续续学习了一下vue的源代码(当时最新的2.5.3版本)。后来想想干脆把这些都记录下来,也算是学有所获,若有错误,欢迎拍砖。


这篇博客应该是一个系列篇的开篇,想要围绕vue重要功能(mvvm, component等)以及其重要生态圈(vuex,router等)进行源代码学习,希望不弃坑。

为什么是vue源码

  • 体积小(源代码少 😉 )
  • 社区繁荣(容易查询问题)
  • 纯净(不依赖任何第三方库,只发现了虚拟dom算法基于Snabbdom)

准备工作

克隆一份tag v2.5.3版本的vue项目

1
2
3
git clone --branch v2.5.3 https://github.com/vuejs/vue.git
cd vue
npm i

工程概览

第一步当然是先去看看package.json文件, 再结合项目结构, 大致得出vue项目开发主要依赖如下

  • rollup 打包工具, 支持tree shaking
  • babel vue采用es6语法开发
  • flow javascript静态类型检查工具
  • karma 测试
  • lint 规范代码

目录结构

准备开始

既然要分析源代码,笔者是习惯将源码逐步调试来走读学习,那么就要将es6编写的vue源文件打包,然后利用sourcemap做调试来跟踪源码。查看package.json文件,直接就可以看到很多条script,从命令名也能看出这些都是以不同模块方式或用途打包(umd, commonjs, es module等)。这里直接使用web-full-dev

1
"dev": "rollup -w -c build/config.js --environment TARGET:web-full-dev"

然后进入build/config文件,找到对应的配置

1
2
3
4
5
6
7
8
'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
}

entry-runtime-with-compiler作为入口文件进行打包,接下来运行

1
npm run dev

dist目录对应生成了相应的vue文件,但是还缺少sourcemap,查阅一下rollup资料后,在build/config.js中添加如下配置

1
2
3
4
5
6
7
output: {
file: opts.dest,
format: opts.format,
banner: opts.banner,
name: opts.moduleName || 'Vue',
+ sourceMap: true
}

再重新打包,map文件也已经生成。找到examples/commits/index.html,修改:

1
2
-	  <script src="../../dist/vue.min.js"></script>
+ <script src="../../dist/vue.js"></script>

浏览器打开index.html

我们从entry-runtime-with-compiler.js作为入口开始。打开entry-runtime-with-compiler.js, 可以发现这个文件其实是Vue.prototype.$mount方法的一个增强(针对运行时再编译template的场景), 真正对Vue对象的声明其实是在core/instance/index.js中:

1
2
3
4
5
6
7
8
function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options)
}

到这里,准备工作就已经完成。之后的博客中,涉及到vue源码中,如果是中文注释则是笔者自己添加方便查阅,英文则是vue自己的(基本没有 😞 )