https://vue3js.cn/global/
调试环境搭建
git clone https://github.com/vuejs/vue-next.git
安装依赖: yarn
yarn install
生成sourcemap文件,package.json
"dev": "node scripts/dev.js --sourcemap"
编译:
yarn dev- 生成结果:
packages\vue\dist\vue.global.js 
结构:源码位置是在package文件件内,实际上源码主要分为两部分,编译器和运行时环境。
编译器
- compiler-core 核心编译逻辑
 - compiler-dom 针对浏览器平台编译逻辑
 - compiler-sfc 针对单文件组件编译逻辑
 - compiler-ssr 针对服务端渲染编译逻辑
 
运行时环境
- runtime-core 运行时核心
 - runtime-dom 运行时针对浏览器的逻辑
 - runtime-test 浏览器外完成测试环境仿真
 
- reactivity 响应式逻辑
 - template-explorer 模板浏览器
 - server-renderer 服务器端渲染
 - share 公用方法
 - vue 代码入口,整合编译器和运行时
+---------------------+ +----------------------+| | | |+------------>| @vue/compiler-dom +--->| @vue/compiler-core || | | | |+----+----+ +---------------------+ +----------------------+| || vue || |+----+----+ +---------------------+ +----------------------+ +-------------------+| | | | | | |+------------>| @vue/runtime-dom +--->| @vue/runtime-core +--->| @vue/reactivity || | | | | |+---------------------+ +----------------------+ +-------------------+
 
调试:https://vue3js.cn/run/start.html
createApp
runtime-dom/src/index.ts
export const createApp = ((...args) => {const app = ensureRenderer().createApp(...args)if (__DEV__) {injectNativeTagCheck(app)injectCustomElementCheck(app)}const { mount } = appapp.mount = (containerOrSelector: Element | ShadowRoot | string): any => {const container = normalizeContainer(containerOrSelector)if (!container) returnconst component = app._componentif (!isFunction(component) && !component.render && !component.template) {component.template = container.innerHTML}// clear content before mountingcontainer.innerHTML = ''const proxy = mount(container, false, container instanceof SVGElement)if (container instanceof Element) {container.removeAttribute('v-cloak')container.setAttribute('data-v-app', '')}return proxy}return app}) as CreateAppFunction<Element>
ensureRenderer()——->baseCreateRenderer()
vnode\diff\patch均在这个方法中实现
function baseCreateRenderer(options: RendererOptions,createHydrationFns?: typeof createHydrationFunctions): any {const {insert: hostInsert,remove: hostRemove,patchProp: hostPatchProp,createElement: hostCreateElement,createText: hostCreateText,createComment: hostCreateComment,setText: hostSetText,setElementText: hostSetElementText,parentNode: hostParentNode,nextSibling: hostNextSibling,setScopeId: hostSetScopeId = NOOP,cloneNode: hostCloneNode,insertStaticContent: hostInsertStaticContent} = options// ....此处省略两千行,我们先不管return {render,hydrate,createApp: createAppAPI(render, hydrate)}}
从源码中我们看到baseCreateRenderer最终返回render``hydrate``createApp3个函数, 但在createApp这个函数中我们本质上只需要返回createApp这个函数就好
接着将生成的render传给createAppAPI这个真正的createApp方法,hydrate为可选参数,ssr 的场景下会用到
export function createAppAPI<HostElement>(render: RootRenderFunction,hydrate?: RootHydrateFunction): CreateAppFunction<HostElement> {return function createApp(rootComponent, rootProps = null) {if (rootProps != null && !isObject(rootProps)) {__DEV__ && warn(`root props passed to app.mount() must be an object.`)rootProps = null}// 创建默认APP配置const context = createAppContext()const installedPlugins = new Set()let isMounted = falseconst app: App = {_component: rootComponent as Component,_props: rootProps,_container: null,_context: context,get config() {return context.config},set config(v) {if (__DEV__) {warn(`app.config cannot be replaced. Modify individual options instead.`)}},// 都是一些眼熟的方法use() {},mixin() {},component() {},directive() {},// mount 我们拎出来讲mount() {},unmount() {},// ...}return app}}
export function createAppContext(): AppContext {return {config: {isNativeTag: NO,devtools: true,performance: false,globalProperties: {},optionMergeStrategies: {},isCustomElement: NO,errorHandler: undefined,warnHandler: undefined},mixins: [],components: {},directives: {},provides: Object.create(null)}}
