VUE源码阅读笔记1:源码下载,从哪开始阅读,如何找到源码的入口文件

蛰伏已久 蛰伏已久 2019-02-13

之前简单看过VUE的源码,但是没有做好笔记,没有好好总结、复盘、记录的学习,收获是很低的,毕竟写笔记的过程也是思考的过程,VUE源码阅读的文章很多,不过那都是属于别人的,阅读源码和阅读源码解析文章,完全是两回事,so,赶紧行动起来吧。

要阅读源码大致分三步,第一步下载源码,废话,哈哈,第二步找到入口文件,第三步,阅读吧,哈哈

下载源码

我们要阅读的源码不是打包后的vue.js,这只是源码打包后的文件,我们要读的是作者开发vue.js的源码,从中理解vue的原理,更重要的是,学习大神的代码风格,从中找出对我们有益的地方。

下载源码很简单,github直接搜索vue,star数最高的就是了,下载地址:https://github.com/vuejs/vue

从何读起

下载之后看到一堆文件夹和文件,那么我们从何读起呢,首先要找到入口文件。

一般我们可以从package.json文件中的“scripts”入手,来看一下,可以看到vue采用rollup进行打包,并且可以打包成多种形式供不同场景使用,有dev的,build的,weex的

"scripts": {
  "dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev",
  "dev:cjs": "rollup -w -c scripts/config.js --environment TARGET:web-runtime-cjs",
  "dev:esm": "rollup -w -c scripts/config.js --environment TARGET:web-runtime-esm",
  "dev:test": "karma start test/unit/karma.dev.config.js",
  "dev:ssr": "rollup -w -c scripts/config.js --environment TARGET:web-server-renderer",
  "dev:compiler": "rollup -w -c scripts/config.js --environment TARGET:web-compiler ",
  "dev:weex": "rollup -w -c scripts/config.js --environment TARGET:weex-framework",
  "dev:weex:factory": "rollup -w -c scripts/config.js --environment TARGET:weex-factory",
  "dev:weex:compiler": "rollup -w -c scripts/config.js --environment TARGET:weex-compiler ",
  "build": "node scripts/build.js",
  "build:ssr": "npm run build -- web-runtime-cjs,web-server-renderer",
  "build:weex": "npm run build -- weex",
  "test": "npm run lint && flow check && npm run test:types && npm run test:cover && npm run test:e2e -- --env phantomjs && npm run test:ssr && npm run test:weex",
  "test:unit": "karma start test/unit/karma.unit.config.js",
  "test:cover": "karma start test/unit/karma.cover.config.js",
  "test:e2e": "npm run build -- web-full-prod,web-server-basic-renderer && node test/e2e/runner.js",
  "test:weex": "npm run build:weex && jasmine JASMINE_CONFIG_PATH=test/weex/jasmine.js",
  "test:ssr": "npm run build:ssr && jasmine JASMINE_CONFIG_PATH=test/ssr/jasmine.js",
  "test:sauce": "npm run sauce -- 0 && npm run sauce -- 1 && npm run sauce -- 2",
  "test:types": "tsc -p ./types/test/tsconfig.json",
  "lint": "eslint src scripts test",
  "flow": "flow check",
  "sauce": "karma start test/unit/karma.sauce.config.js",
  "bench:ssr": "npm run build:ssr && node benchmarks/ssr/renderToString.js && node benchmarks/ssr/renderToStream.js",
  "release": "bash scripts/release.sh",
  "release:weex": "bash scripts/release-weex.sh",
  "release:note": "node scripts/gen-release-note.js",
  "commit": "git-cz"
},

我们就以dev为例,来查找入口文件吧,可以看到,打包的入口文件为script/config.js,并传入了一个环境变量TARGET=web-full-dev

"dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev",

我们打开script/config.js,找到export相关的语句,一般在最底部,可以看到,我们需要去看getConfig函数,参数就是web-full-dev

......
if (process.env.TARGET) {
  module.exports = genConfig(process.env.TARGET)
} else {
  exports.getBuild = genConfig
  exports.getAllBuilds = () => Object.keys(builds).map(genConfig)
}

getConfig函数

function genConfig (name) {
  const opts = builds[name]
  const config = {
    input: opts.entry,
    
    //定义了一些文件的别名
    alias(Object.assign({}, aliases, opts.alias))
    ........

可以看到入口文件应该就是opts.entry,而opts=builds["web-full-dev"]

再去查看builds的配置,找到如下代码

....
'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
},
.....

可以看到入口文件为resolve('web/entry-runtime-with-compiler.js'),去看看resolve函数

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)
  }
}

resolve函数又调用了aliases[base],这里base就是web,即aliases[“web”],继续去看看aliases

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'),
  entries: resolve('src/entries'),
  sfc: resolve('src/sfc')
}

可以看到aliases[“web”]=resolve('src/platforms/web')

综上,入口文件就应该在src/platforms/web/entry-runtime-with-compiler.js,我们去看看这个文件

......
import Vue from './runtime/index'
......

//Vue之前定义了$mount方法,这里重写了
const mount = Vue.prototype.$mount
Vue.prototype.$mount=function (
  el?: string | Element,
  hydrating?: boolean
): Component {
   .......
   
   return mount.call(this, el, hydrating)
}


export default Vue

我们重点关注这几个地方,首先从./runtime/index 引入Vue,并重写了Vue的$mount方法,然后导出Vue

接下来就去./runtime/index中去看看,这里Vue是怎么导出的

import Vue from 'core/index'


Vue.prototype.$mount = function (
  el?: string | Element,
  hydrating?: boolean
): Component {
  el = el && inBrowser ? query(el) : undefined
  return mountComponent(this, el, hydrating)
}

if (inBrowser) {
  setTimeout(() => {
    //如果在浏览器里面,提示下载Vue Devtools 
  }, 0)
}


export default Vue

又看出Vue来自'core/index',这里是用到了路径的别名,在上面getConfig函数中有提过,实际路径为“src/core/index”

至此,我们算是找到vue核心代码的位置了,当然如果经验丰富了,可以直接就知道去src/core文件下面去查看,本文只是针对没有经验的,像我一样比较少阅读源码的初级程序员哈哈

下一篇就正式进入Vue核心源码的阅读,一起加油吧

分享到

点赞(5)