Vue源码解析(笔记)
github vue源码分析
认识flow
flow类型检查
安装flow
sudo npm install -g flow-bin
初始化flow
flow init
运行flow命令
命令: flow
在js文件中需要有需要有一下标志
/*@flow*/
例子 void
/*@flow*/class Bar {x: string; // x 是字符串y: string | number | void; // y 可以是字符串或者数字z: boolean;constructor(x: string, y: string | number | void) {this.x = xthis.y = ythis.z = false}
}var bar: Bar = new Bar('hello')var obj: { a: string, b: number, c: Array<string>, d: Bar } = {a: 'hello',b: 11,c: ['hello', 'world'],d: new Bar('hello', 3)
}
Vue.js 源码目录设计
src
├── compiler # 编译相关
├── core # 核心代码
├── platforms # 不同平台的支持
├── server # 服务端渲染
├── sfc # .vue 文件解析
├── shared # 共享代码
Vue.js 源码构建
Vue.js 源码是基于Rollup 构建的,它的相关配置都在scripts目录下
构建脚本
通常一个基于NPM 托管的项目都会有一个package.json 文件,它的实际内容是JSON对象
我们通常会配置scripts字段作为NPM 执行脚本 Vue.js 源码构建脚本如下
{
"script":{
"build":"node scripts/build.js",
"build:ssr":"npm run build -- web-runtime-cjs,web-server-renderer",
"build:weex":" npm run build --weex"}
}
这里共有3条命令,作为都是构建Vue.js,后面2 条是在第一条命令的基础上,添加环境参数。
当在运行 npm run build
的时候 ,实际上就会执行 node scripts/build.js
接下来看看 它实际是怎么构建的
构建过程
我们对于构建过程分析是基于源码的,先打开构建的入口JS文件,在scripts/build.js 中
let builds = require('./config').getAllBuilds()
if(process.argv[2]){const filters = process.argv[2].split(',')builds = builds.filter(b => {return filters.some(f => b.oupput.file.indexOf(f)) > -f || b._name.indexOf(f) > -1
})
} else {builds = builds.filter(b => {return b.output.file.indexOf('weex') === -1})
}build(builds)
这端代码逻辑非常简单。先从配置文件读取信息,在通过命令行参数对构建配置过滤,这样就可以构建出不同用途的Vue.js了。配置文件 在 scripts/config.js
const builds = {
'web-runtime-cjs': {entry: resolve('web/entry-runtime.js'),dest: resolve('dist/vue.runtime.common.js'),format:'cjs',banner},'web-full-cjs': {entry: resolve('web/entry-runtime-with-compilter.js'),dest: resolve('dist/vue.common.js'),format: 'cjs',banner},'web-runtime-esm': {entry:resolve('web/entry-runtime.js'),dest: resolve('dist/vue.runtime.esm.js'),format:'es',banner},'web-full-esm': {entry: resolve('web/entry-runtime-with-compilter.js')}
}
这里列举了一些Vue.js 构建的配置 还有一些服务器渲染webpack 插件以及weex就不列举了
对于单个配置 它是遵循Rollop 的构建规则,其中entry 属性表示构建的入口JS文件地址,dess属性表示构建后的JS文件地址,fromat 属性表示构建的规则,cjs表示构建构建出来的文档遵循 CommonJS规范,es 表示构建出来的文件遵循ES Module 规范umd表示构建出来的文件遵循UMD规范
以web-runtime-cjs 配置为例 它的entry
是 resolve('web/entry-runtime.js')
先看一下resolve 函数的定义
源码目录 scripts/config。js
const aliases = require('./alias')
const resolve = p => {const base = p.split('/')[0]if(aliases[base]) {return path.resolve(aliases[base], p.splice(base.length + 1))}else {return path.resolve(__dirname, '..', p)}}
这里resolve 函数实现非常简单,它先把resolve 函数传入的参数p
通过/
做了分割数组,然后取数组的第一个元素设置base
。在这个例子中参数p
是web/entry-runtime.js
,那么base
则是web
,base
并不是实际路径,它的真实路径借助了别名的配置,我们来看一下配置别名的代码,在scripts/alias 中
const path = require('path')module.exports = {vue: path.resole(__dirname,'../src/platforms/web/entry-runtime-with-compiler'),compiler: path.resolve(__dirname,'../src/compiler'),core: path.resolve(__dirname,'../scr/core'),shared: path.resolve(__dirname,'../src/shared'),web: path.resolve(__dirname, '../src/platforms/web'),weex: path.resolve(__dirname, '../src/platforms/weex'),server: path.resolve(__dirname, '../src/server'),entries: path.resolve(__dirname, '../src/entries'),sfc: path.resolve(__dirname, '../src/sfc')
}
很显然,这里web 对应的真实路径是path.resolve(__dirname,'../src/platforms/web')
, 这个路径就找到了Vue.js源码的web目录,然后resolve
函数通过path.resolve(aliases[base], p.slice(base.length + 1))
找到最终路径,它即使Vue.js源码目录下面的entry-runtime.js 。因此 web-runtime-cjs 配置对应的文件入口就找到了
它经过Rollup 的构建打包后,最终会在dist 目录先生成 vue.runtime.common.js
Runtime Only VS Runtime+ Compiler
通常我们利用vue-cli 去初始化我们的Vue.js 项目的时候会询问我们用 Runtime Only 版本还是Runtime+Compiler 版本,下面我们来对比这两个版本
- Runtime Only
我们在使用Runtime Only 版本的Vue.js 的时候,通常需要借助webpack的vue-loader工具把.vue文件编译成 JavaScript , 因为在编译阶段做的,所以它只包运行时的Vue.js 代码, 因此代码体积更轻
- Runtime+Compiler
我们如果没有对代码进行预编译,但又使用了Vue的teplate 并传入了一个字符产,则需要在客户端编译模版 如下所示:
// 需要编译器的模版
new Vue({template:'<div>{{h1}}</div>'
})
// 这种情况不需要
new Vue({render (h) {return h('div',this.hi)}
})
因为在Vue.js 2.0 中最终渲染都是通过render 函数 ,如果写tempalte 属性, 则需要编译成render 函数,那么这个编译过程发生运行时,所以需要带有编译器的版本
很显然,这个编译过程对性能又一定损耗,所以通常我们更推荐 Runtime-Only 的Vue.js
zon
Vue源码解析(笔记)相关推荐
- React深入学习与源码解析笔记
***当前阶段的笔记 *** 「面向实习生阶段」https://www.aliyundrive.com/s/VTME123M4T9 提取码: 8s6v 点击链接保存,或者复制本段内容,打开「阿里云盘」 ...
- Vue源码解析(一)
前言:接触vue已经有一段时间了,前面也写了几篇关于vue全家桶的内容,感兴趣的小伙伴可以去看看,刚接触的时候就想去膜拜一下源码~可每次鼓起勇气去看vue源码的时候,当看到几万行代码的时候就直接望而却 ...
- 【vuejs深入三】vue源码解析之二 htmlParse解析器的实现
写在前面 一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. 昨天博主分析了一下在vue中,最为基础核心的api,parse函数,它的作用是将vue的模板字符串转换成ast,从而 ...
- [Vue源码解析] patching算法
[Vue源码解析] patching算法 pathching算法:通过对比新旧VNode的不同,然后找出需要更新的节点进行更新 操作:1.创建新增节点 2.删除废弃节点 3.修改需要更新的节点 创建节 ...
- 源码解析:Spring源码解析笔记(五)接口设计总览
本文由colodoo(纸伞)整理 QQ 425343603 Java学习交流群(717726984) Spring解析笔记 启动过程部分已经完成,对启动过程源码有兴趣的朋友可以作为参考文章. 源码解析 ...
- Vue源码解析(尚硅谷)
视频地址:Vue源码解析系列课程 一.Vue源码解析之mustache模板引擎 1. 什么是模板引擎 模板引擎是将数据要变为视图最优雅的解决方案 历史上曾经出现的数据变为视图的方法 2. mustac ...
- obs 源码解析笔记
obs 源码解析笔记 由于obs rtp音频传输有问题,所以可能需要修改obs源码,学习了两天,发现官方文档有些混乱,国内有关说明又少,特此记录,也方便以后自己查阅.这里主要涉及工作有关源码其他基本略 ...
- Vue源码解析之数组变异
力有不逮的对象 众所周知,在 Vue 中,直接修改对象属性的值无法触发响应式.当你直接修改了对象属性的值,你会发现,只有数据改了,但是页面内容并没有改变. 这是什么原因? 原因在于: Vue 的响应式 ...
- Vue源码解析:虚拟dom比较原理
通过对 Vue2.0 源码阅读,想写一写自己的理解,能力有限故从尤大佬2016.4.11第一次提交开始读,准备陆续写: 模版字符串转AST语法树 AST语法树转render函数 Vue双向绑定原理 V ...
最新文章
- jQuery源码分析系列:属性操作
- 【ARM】ARM接口技术
- [原]Oracle数据文件损坏的模拟和修复(一) |ORA-01578 data block corrupted|
- Loadrunner中socket协议中的三个关联函数
- 4n35光耦引脚图_光耦继电器的主要特点以及输入特性!先进光半导体
- matlab语言转化为python语言_matlab语言转译成python
- xml的应用与dtd约束
- getQueryString方法使用
- shell脚本实现一个彩色进度条
- win98老机子安装linux,只装了Win98电脑的Linux系统安装和修复
- 看图识WAF-搜集常见WAF拦截页面
- 用C++实现QQ自动登陆器,仿佛开了外挂,秒杀各种神操作!
- matlab 工具箱下载地址
- js实现 动态密码的实现
- 程序员成长之路(四)之有用的网址
- 根据高程值批量修改等高线为计曲线工具,FME实现等高线批量修改成计曲线,根据高程值自动识别计曲线,解决地形图计曲线丢失问题,等高线批量提取计曲线,首曲线根据高程批量转换成计曲线
- Mysql索引介绍及使用注意事项,limit分页查询,慢查询分析
- 人工神经网络算法与机器算法算两种算法吗
- cuug内部oracle视频教程-oracle sql_tune
- gearhost php,美国免费稳定全能空间:GearHost