Skip to content

Commit

Permalink
chore: update md (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
ErKeLost authored Jan 4, 2024
1 parent d73829f commit 9fa2c57
Showing 1 changed file with 21 additions and 21 deletions.
42 changes: 21 additions & 21 deletions rfcs/001-core-architecture/rfc.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@

# 总结

本 RFC 设计使用 Typescript 和 Rust 实现极速的 Web 编译器。该编译器设计继承现有工具(如 webpack 和 vite)的优点,同时避免它们的缺点并且将会更加高效
本 RFC 设计使用 Typescript 和 Rust 实现极速的 Web 编译器。该编译器设计继承现有工具(如 webpack 和 vite)的优点,同时避免它们的缺点,并且显著提高性能

# 动机

随着 web 项目的复杂度以及规模的不断增加, 构建性能成为了 web 开发中的一个重要的瓶颈, 使用 webpack 构建的 web 项目可能需要十分钟甚至更长时间, 并且 (HMR) 的更新的时间可能花费数十秒甚至更长时间, 降低了开发效率, 这对于开发体验来说是不可接受的。

然后就出现了类似 vite 的工具来解决这个问题, vite 采用原生 ESM 和 unbundled 解决开发模式的问题, 这样就可以避免 webpack 的构建过程中的大量的 IO 操作。但是缺点是原生 ESM 模块以及动态加载模块, 导致大量开发模块的请求成为了新的瓶颈, 当你有数千个模块的请求时, 可能会导致网络面板崩溃
然后就出现了像 (vite, snowpack) 的工具来解决这个问题, vite 采用原生 ESM 和 unbundled 解决开发模式的问题, 这样就可以避免 webpack 的构建过程中的大量的 IO 操作。但是缺点是原生 ESM 模块以及动态加载模块, 导致大量开发模块的请求成为了新的瓶颈, 当你有数千个模块的请求时, 可能会导致网络面板崩溃

Vite 的速度非常快, 因为使用了 Go 编写的 Esbuild, 并利用本地性能。然而,对于旧版浏览器来说 ESM 不可用,而且 esbuild 还不稳定,不能在生产中使用。因此,在生产环境中 vite 使用 Rollup 作为打包工具来解决兼容性和稳定性问题。这引入了新的问题,例如开发和生产环境之间行为差异显著,并且与 esbuild 相比由于 Rollup 是用 Typescript 编写的导致性能较慢
Vite 的速度非常快, 是因为使用了由 Go 编写的 Esbuild, 能够利用原生的性能优势。然而,Esm 并不支持旧版浏览器,而且 esbuild 目前还不够稳定,不适合在生产中使用。因此,在生产环境中 vite 使用 Rollup 作为打包工具来解决兼容性和稳定性问题。这引入了新的问题,例如开发和生产环境之间行为差异显著,并且 Rollup 和 Esbuild 相比性能较慢

我们可以充分利用 webpack 和 vite,同时避免它们的缺点。Webpack 构建速度较慢,但是我们可以使用系统级语言(Rust)来显著提高构建性能。Vite 的 unbundled, 这意味着缓存比 webpack 更细粒度,但它存在一些问题,如不一致性(在开发和生产之间)和大量请求(可能会减慢资源加载甚至导致浏览器崩溃)。我们可以采用部分打包策略来减少请求数量而不失去缓存粒度
我们可以充分利用 webpack 和 vite 的优势,同时避免它们的缺点。Webpack 虽然慢,但是我们可以使用系统级语言(Rust)来显著提高构建性能。Vite 的 unbundled, 这意味着缓存比 webpack 更加细致 颗粒度更高,但它存在一些问题,如开发和生产之间的不一致性, 以及大量请求(可能会减慢资源加载甚至导致浏览器崩溃)。那么我们可以采用部分打包策略来减少请求数量而不失去缓存粒度

综上所述, Farm 是一个旨在更快(无论是构建性能还是资源加载性能)和更一致的 Web 构建工具,利用现有工具并丢弃它们的缺点。 Farm 团队最初将专注于 Web 项目编译,这意味着我们的输入主要是 Web 资产,例如 HTML、JS/JSX/TS/TSX、CSS/SCSS/LESS、PNG/SVG 等。我们做出的每个设计决策都将优先考虑浏览器兼容性。尽管通用打包程序(将所有内容捆绑在一起并输出各种格式)目前不是我们的主要目标,但您可以通过插件实现任何想要达到的效果
综上所述, Farm 是一个更快(无论是构建性能还是资源加载性能)和更一致的 Web 构建工具,利用现有工具的优势并且摒弃他们的不足。 Farm 团队最初将专注于 Web 项目编译,这意味着我们的输入主要是 Web 资产,例如 HTML、JS/JSX/TS/TSX、CSS/SCSS/LESS、PNG/SVG 等。我们做出的每一个设计决策都将优先考虑浏览器兼容性。尽管通用打包程序(将所有内容捆绑在一起并输出各种格式)目前不是我们的主要目标,但您依然可以通过插件实现任何想要达到的效果

我们的目标是设计出一个真正现代化的 web 编译器, 它将会是快速, 稳定, 构建产物一致, 以及兼容性良好, 优先考虑现代 web 技术, 我们希望创建出一个能够满足开发者需求的下一代构建工具
我们的目标是设计一个真正现代化的 Web 编译器,它不仅要性能极致,还要稳定、一致、兼容,并且优先考虑现代 Web 技术。我们希望创建一个下一代的构建工具,真正满足开发者的需求。

> 注意:本 RFC 主要涵盖核心架构设计, 后续每个部分的详细信息将拆分为单独的 RFC。
Expand All @@ -30,23 +30,23 @@ Vite 的速度非常快, 因为使用了 Go 编写的 Esbuild, 并利用本地

- **性能优先**: 我们的目标是所有都用 Rust 编写, 只有极少数或者不是性能瓶颈的部分才会使用 js。
- **Rollup 风格的插件系统**: 以类似 Rollup 的方式设计插件系统, 使得插件可以更加灵活并且更加简便的使用, 并且易于从 Rollup/Vite/Webpack 迁移您的插件/项目。
- **对所有 web 资源提供支持**: 我们不在需要把所有内容都转换到 javascript, 我们将把任何东西视为一等公民, 在 Farm 中, 默认支持基本资源(如 `html``js/jsx/ts/tsx``css/scss``png/svg/...`),您可以使用插件来支持更多资源。
- **浏览器优先**: Farm 的目标是在浏览器或者 nodejs 中运行(仅用于 SSR), 我们不会成为通用打包工具, 而是专注提高在 web 的性能和效率。
- **首选非捆绑的方式**: 当模块数量或大小达到限制时,我们只会构建部分模块。当部分模块构建时,我们将使用强大的局部捆绑策略控制资源请求数量而不失去缓存粒度
- **对所有 Web 资源提供支持**: 我们不在需要把所有内容都转换到 javascript, 我们将把任何东西视为一等公民, 在 Farm 中, 默认支持基本资源(如 `html``js/jsx/ts/tsx``css/scss``png/svg/...`),您可以使用插件来支持更多资源。
- **浏览器优先**: Farm 的目标是在浏览器或者 nodejs 中运行(仅用于 SSR), 专注提高在 Web 的性能和效率。
- **首选非捆绑的方式**: 当模块数量或大小达到限制时,我们只会构建部分模块。在部分捆绑模块时,我们将使用强大的部分捆绑策略来控制资源请求数量,而不会失去缓存的细致度。
- **始终保持一致性**: 开发环境和生产环境产物完全相同。您在开发中看到的内容将与生产中获得的内容相同。
- **兼容性**: Farm 将适用于传统和现代浏览器。

## 2. 术语
## 2. 术语定义

Farm 使用的术语定义如下:

- **模块(Module)**:基本编译单元,可以是文件或虚拟模块。例如各种 Web 资源,如`js、ts、jsx、tsx、css、scss、png、svg...`或由插件实现的虚拟模块
- **模块(Module)**:基本编译单元,可以是文件或虚拟模块。例如各种 Web 资源,如`js、ts、jsx、tsx、css、scss、png、svg...`或者是由插件实现的虚拟模块

- **资源(Resource)**:表示一个 `js/css/html/png/svg/map/..` 文件,并可能包含多个原始模块。

- **资源池(ResourcePot)**:可以生成一个或多个 `Resource``ResourcePot` 可能是一些部分打包的 `Module`, 例如将许多 `js` 模块捆绑到一个 `ResourcePot`, 并且一个 ResourcePot 会生成 `.js` 文件和 `.js.map` 文件。

- **模块组(ModuleGroup)**: 所有从入口静态导入的模块都在同一 ModuleGroup 中。
- **模块组(ModuleGroup)**: 所有从入口静态导入的模块都在同一 `ModuleGroup` 中。

- **模块依赖图(ModuleGraph)**:所有已解析模块的依赖关系图。

Expand All @@ -70,9 +70,9 @@ Farm 核心由两部分组成:

## 4. 编译上下文

编译上下文包含了整个编译过程中的所有共享信息。本小节将详细介绍编译上下文。
编译上下文包含了整个编译过程中的所有共享信息。本小节将详细介绍编译上下文 `CompilationContext`

Rust 插件可以通过钩子访问 CompilationContext
插件可以通过钩子参数访问 `CompilationContext`

```rust
struct MyPlugin {}
Expand Down Expand Up @@ -103,7 +103,7 @@ pub struct CompilationContext {
}
```

`meta`是编译过程中共享的数据,例如 swc 的 SourceMap。插件还可以添加自定义数据并将其插入到`meta.custom`中。
`meta`是编译过程中共享的数据,例如 `swc``SourceMap`。插件还可以添加自定义数据并将其插入到`meta.custom`中。

对于其他数据结构,如`module_graph`或者`resource_graph`, 是在 Farm 核心的编译生命周期内构建的。

Expand All @@ -127,13 +127,13 @@ pub struct CompilationContext {

### 5.1 构建阶段

构建阶段的目标是去构建出一套模块依赖图。
从入口配置文件开始解析, 加载, 转换并且解析入口模块, 然后分析依赖, 并且对所有依赖模块进行相同的操作, 直到所有模块都被解析完毕。
每个模块的构建流程如下:
`构建阶段的目标是构建一个模块依赖图(ModuleGraph)`
从用户配置的编译入口开始,解析、加载、转换、解析入口模块,然后分析其依赖关系,并对依赖项进行相同的操作,直到处理完所有相关模块。

`./index.html -> 解析 -> 加载 -> 转换 -> 语法分析 -> 解析模块 -> 分析依赖关系 ----> 递归地解决依赖关系`
每个模块的构建流程如下所示。
`./index.html -> 解析(resolve)-> 加载(load)-> 转换(transform)-> 解析(parse)-> 模块解析完毕(moduleParsed)-> 分析依赖(analyzeDeps)----> 递归解析依赖(resolve deps recursively)`

每个模块由线程池中的单独线程构建, 在分析依赖关系之后, 我们将再次返回解析其他依赖项
每个模块将在线程池中的一个单独线程中构建,在完成analyzeDeps之后,我们会再次返回到解析(resolve)阶段,为每个依赖项进行处理。

#### 5.1.1 Resolve

Expand Down Expand Up @@ -578,7 +578,7 @@ export default defineConfig({
},
output: {
// details will be described later...
}
},
},
// dev server config
server: {
Expand Down

0 comments on commit 9fa2c57

Please sign in to comment.