Vue3源码学习 - 项目结构
项目结构
该代码仓库采用了单体仓库的设置,将许多相关的包放在packages
目录下:
-
reactivity
:响应性系统。可以作为一个与框架无关的包独立使用。 -
runtime-core
:平台无关的运行时核心。包括虚拟 DOM 渲染器、组件实现和 JavaScript API 的代码。可以使用该包创建针对特定平台的高阶运行时(例如自定义渲染器)。 -
runtime-dom
:面向浏览器的运行时。包括处理原生 DOM API、属性、属性、事件处理程序等。 -
runtime-test
:用于测试的轻量级运行时。可以在任何 JavaScript 环境中使用,因为它“渲染”了一棵普通 JavaScript 对象的树。该树可用于断言正确的渲染输出。还提供了用于序列化树、触发事件和记录更新期间执行的实际节点操作的实用程序。 -
server-renderer
:用于服务器端渲染的包。 -
compiler-core
:平台无关的编译器核心。包括编译器的可扩展基础和所有平台无关的插件。 -
compiler-dom
:带有专门针对浏览器的附加插件的编译器。 -
compiler-sfc
:用于编译 Vue 单文件组件的较低级别实用程序。 -
compiler-ssr
:生成针对服务器端渲染进行优化的渲染函数的编译器。 -
shared
:多个包之间共享的内部实用程序(尤其是运行时和编译器包都使用的与环境无关的实用程序)。 -
vue
:公共“全功能构建”,包括运行时和编译器。 -
私有实用程序包:
-
dts-test
:包含针对生成的 dts 文件的仅类型测试。 -
sfc-playground
:在 https://play.vuejs.org 上持续部署的 playground。要在本地运行 playground,请使用nr dev-sfc
。 -
template-explorer
:用于调试编译器输出的开发工具,持续部署在 https://template-explorer.vuejs.org/。要在本地运行,请运行nr dev-compiler
。
-
包依赖关系
在跨包边界导入时需要遵循一些规则:
-
从另一个包导入项目时,不要直接使用相对路径 - 在源包中导出它,并在包级别导入。
-
编译器包不应从运行时导入项目,反之亦然。如果需要在编译器端和运行时端之间共享某些内容,应将其提取到
@vue/shared
中。 -
如果一个包(A)有非类型导入,或者从另一个包(B)重新导出类型,则应在(A)的
package.json
中将(B)列为依赖项。这是因为这些包在 ESM-bundler/CJS 构建和类型声明文件中是外部化的,因此当从包注册表中使用时,依赖包必须实际安装为依赖项。
英文原文
Project Structure
This repository employs a monorepo setup which hosts a number of associated packages under the packages
directory:
-
reactivity
: The reactivity system. It can be used standalone as a framework-agnostic package. -
runtime-core
: The platform-agnostic runtime core. Includes code for the virtual dom renderer, component implementation and JavaScript APIs. Higher-order runtimes (i.e. custom renderers) targeting specific platforms can be created using this package. -
runtime-dom
: The runtime targeting the browser. Includes handling of native DOM API, attributes, properties, event handlers etc. -
runtime-test
: The lightweight runtime for testing. Can be used in any JavaScript environment since it “renders” a tree of plain JavaScript objects. The tree can be used to assert correct render output. Also provides utilities for serializing the tree, triggering events, and recording actual node operations performed during an update. -
server-renderer
: Package for server-side rendering. -
compiler-core
: The platform-agnostic compiler core. Includes the extensible base of the compiler and all platform-agnostic plugins. -
compiler-dom
: Compiler with additional plugins specifically targeting the browser. -
compiler-sfc
: Lower level utilities for compiling Vue Single File Components. -
compiler-ssr
: Compiler that produces render functions optimized for server-side rendering. -
shared
: Internal utilities shared across multiple packages (especially environment-agnostic utils used by both runtime and compiler packages). -
vue
: The public facing “full build” which includes both the runtime AND the compiler. -
Private utility packages:
-
dts-test
: Contains type-only tests against generated dts files. -
sfc-playground
: The playground continuously deployed at https://play.vuejs.org. To run the playground locally, usenr dev-sfc
. -
template-explorer
: A development tool for debugging compiler output, continuously deployed at https://template-explorer.vuejs.org/. To run it locally, runnr dev-compiler
.
-
Importing Packages
The packages can import each other directly using their package names. Note that when importing a package, the name listed in its package.json
should be used. Most of the time the @vue/
prefix is needed:
import { h } from '@vue/runtime-core'
This is made possible via several configurations:
- For TypeScript,
compilerOptions.paths
intsconfig.json
- Vitest and Rollup share the same set of aliases from
scripts/aliases.js
- For plain Node.js, they are linked using PNPM Workspaces.
Package Dependencies
There are some rules to follow when importing across package boundaries:
-
Never use direct relative paths when importing items from another package - export it in the source package and import it at the package level.
-
Compiler packages should not import items from the runtime, and vice versa. If something needs to be shared between the compiler-side and runtime-side, it should be extracted into
@vue/shared
instead. -
If a package (A) has a non-type import, or re-exports a type from another package (B), then (B) should be listed as a dependency in (A)'s
package.json
. This is because the packages are externalized in the ESM-bundler/CJS builds and type declaration files, so the dependency packages must be actually installed as a dependency when consumed from package registries.
以上内容来自Vue Github仓库文档: https://github.com/vuejs/core/blob/main/.github/contributing.md