VUE源码阅读笔记1:源码下载,从哪开始阅读,如何找到源码的入口文件
之前简单看过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)