🔥Rust Farm v1.0 发布!极致性能兼容体验,海量编译特性,真正的下一代 Rust web 构建引擎!

Farm⭐️ 是基于 Rust 语言编写的下一代 Web 构建引擎,是目前最强大、最快、最稳定的 Rust Web 构建工具。Farm 自 2023 年 3 月份开源 0.3 版本以来,经过众多社区开发者一年的开发和贡献,v1.0 版本终于面世!v1.0 版本支持包括懒编译、持久缓存、Rust/Js插件扩展、局部打包等能力在内的海量特性,同时兼容 Vite 插件生态,在完美解决 Vite 等工具的现有痛点的基础上,兼具极致性能和兼容性,是真正意义上的下一代构建引擎!

目前 Farm 已经生产可用,已有不少企业级项目迁移到 Farm,并且效果非常好!

如下图,在 benchmark 测试 1000 react 组件,Farm 比 webpack 快 20 倍 ,比 Vite 快 10 倍 ,在冷启动、热启动、HMR等方面对比其他工具,均有压倒性的性能优势。Farm 支持并默认启用了一系列的性能优化手段,如 懒编译持久缓存/增量构建多线程并行编译等 等,项目越大,源文件越多,Farm 的性能优势越大。

基于 Linux Mint 21 / i5 / 16GB,取三次平均得到上述数据,详情参考 benchmark 仓库

一、功能特性

  • 超级快:核心的编译能力均使用 Rust 编译,最大限度并行编译,秒起项目,毫秒级 HMR,极致性能体验!
  • 🚀 增量构建 :模块级磁盘持久缓存,未更改的模块最多只编译一次,热启动时间降低 80% ,搭配懒编译实现对任意规模项目 1s 启动以及预览
  • ⚙️ 海量特性 :内置支持 Html, Css, js/jsx/ts/tsx, 静态资源,
  • 🧰 插件化 & Vite兼容:编译能力由插件实现,兼容 Vite 插件生态,支持 Rust、Js 插件。
  • ⏱️ 懒编译:非首屏页面,按需编译,访问具体页面时才会编译,极大提速大型项目启动时间
  • ✔️ 生产优化:支持 tree shake、压缩、语法降级、polyfill 等完整生产能力,支持降级到 ES5
  • 📦 局部打包 :将模块按照依赖关系打包成 20 - 30 个左右的产物,同时 bundlebundless 两种模式的极端,在保证加载性能的同时,提升缓存复用率
  • 🔒 一致性:开发和生产使用完全一致的策略,开发所见即生产所得
  • 🌳 兼容性:同时兼容现代浏览器和老旧浏览器(ES5)

Farm v1.0 支持 React、Vue、Solid、Svelte 等常用框架,后文的项目演示模块详细介绍了使用 Farm 构建真实项目,以及迁移后的性能收益:

  • [React + Arco Pro + Farm 中后台项目](#React + Arco Pro + Farm 中后台项目 "#heading-11"):使用 Farm 构建的 React 中后台项目,500ms 完成编译并且看到页面
  • [Vue + Element Plus + Farm 中后台项目](#Vue + Element Plus + Farm 中后台项目 "#heading-12"):从 Vite 迁移到 Farm 的 Vue 中后台项目,迁移后 1s 启动并看到页面,比 VIte 快 5 倍

二、快速体验

Farm 提供了官方模板可以快速创建一个 React、Vue、Solid、Svelte 等项目:

bash 复制代码
pnpm create farm

然后选择创建的项目类型、特性等,项目创建完成后,然后启动项目:

bash 复制代码
pnpm start

如下图所示,20s 即可创建 + 启动你的第一个 Farm 项目!

更多细节参考 官方文档

三. 编译特性

4.1 基础编译能力

Farm 内置了 TS/TSX/JS/JSX, CSS/CSS Modules, HTML, 静态资源 等常见模块的编译能力,无需任何配置开箱即用。对于一个 web app 项目,可以直接以 html 作为入口,引入 JS/TS, css 文件,一个最简化的 React 项目示例如下,除需要安装 @farmfe/plugin-react 以支持 React Jsx 语法转换以及 react refresh 外,其他能力均可以开箱即用。

html 复制代码
<!-- index.html -->
<html>
    <head>...</head>
    <body>
        <div id="root"></div>
        <script src="./src/index.tsx"></script>
    </body>
</html>

上述 html 中引入了 ./src/index.tsx:

tsx 复制代码
// src/index.tsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import { Main } from './main';

import './index.css';

const container = document.querySelector('#root');
const root = createRoot(container);

root.render(<Main />);

通过 import './index.css'; 引入 css 文件:

css 复制代码
/* src/index.css */
#root {
  color: red;
}

对于 css modulespng/svg/font 等静态资源 均提供了开箱即用的编译能力支持:

tsx 复制代码
// src/main.tsx
// 默认通过 url 方式引入图片
import logo from './assets/logo.png';
// 引入 css modules
import styles from './main.module.css';

export function Main() {
    return <img src={logo} class={styles.logo} />;
}

Farm 内置了纯 Rust 实现的基础编译能力,无需配置额外插件,对于 html, ts/tsx, css/css modules, png/svg/font 等静态资源 等类型的文件,基础编译能力完全开箱即用。Farm 将各类型的模块html, css, js/ts/tsx 等,均视为一等公民,并通过局部打包将各类型的模块打包 成若干可以生产部署的产物 ,包括 js/ts/css 等不同类型的模块,均可以使用同一套打包规则。

查看文档 编译特性

4.2 懒编译

对于任意动态引入的模块(包括 js/tscss 等),将延迟编译,仅在资源真正需要被加载的时候才进行编译,这将极大提升 大型项目的启动速度!例如,对于大型项目,往往有多个动态加载的路由:

ts 复制代码
// 定义路由并且动态引入
export const routes = [
  {
    path: '/',
    component: () => import('./pages/home.vue')
  },
  {
    path: '/about',
    component: () => import('./pages/about.vue')
  },
  // ...
];

当启用 懒编译 后,import('./pages/home.vue') 将仅在访问 /home 路由的时才编译,其他路由如 /about 在被访问前,./pages/about.vue及其依赖均不会被编译。通过合理使用 懒编译 + 持久缓存,大型项目每个路由 的启动时间都可以被压缩到 1s 以内,极大提升大型项目开发的性能体验!

如上图所示,每次切换路由,都会极速懒编译该路由下的所有依赖模块。

通过 compiltion.lazyCompilation 可以配置,默认在 start 时开启。

ts 复制代码
import { defineConfig } from '@farmfe/core';

export default defineConfig({
    compilation: {
        // 配置关闭懒编译
        lazyCompilation: false
    }
});

4.3 增量构建

Farm 支持将模块级别 的编译产物缓存到本地磁盘,以支持增量构建,任意模块在没有更改前,永远都只会被重复编译!增量构建能够降低 80% 左右的项目启动时间,对于 React + Arco Pro 中后台项目,冷启动和热启动性能对比数据如下:

冷启动(无缓存) 热启动(有缓存) 性能差距
start 1519ms 371ms 热启动减少 75%
build 3582ms 562ms 热构建减少 84%

通过 compiltion.persistentCache 可以配置,默认开启。

ts 复制代码
import { defineConfig } from '@farmfe/core';

export default defineConfig({
    compilation: {
        // 配置关闭增量构建
        persistentCache: false
    }
});

当增量构建开启时,Farm 会将影响性能的编译动作以模块粒度全部缓存到 node_modules/.farm 目录下,例如,resolve/load/transform/parse AST压缩代码生成 等,在下一次编译时,将会从 .farm 目录下面读取缓存,去除大量的重复计算以极大提升编译性能。

更多细节参考文档 增量构建

4.4 生产优化/浏览器兼容

Farm 完全支持生产构建,目前已经有不少企业级项目使用或者迁移到 Farm,并且效果相当好!对于生产构建,Farm 默认开启了以下优化:

  • Tree Shake :对于 ESM 模块,所有未被使用的 export和其他语句将被删除,以减少产物体积
  • 压缩:产物(Html/JS/CSS)将会被混淆和压缩,以减少产物体积
  • 语法降级和Polyfill :默认会降级到支持 ES2017 规范的浏览器,并自动降级源代码中 ES2017 不支持的语法,同时为不支持的 API 自动 注入 Polyfill

Farm 支持产物降级到 ES5,如果你的项目有强兼容要求,可通过 targetEnv: 'browser-legacy' 配置:

ts 复制代码
import { defineConfig } from '@farmfe/core';

export default defineConfig({
    compilation: {
        output: {
            targetEnv: 'browser-legacy'
        }
    }
})

更多细节可以参考文档 Build For Production

4.5 局部打包

局部打包(Partial Bundling)是 Farm 用来打包模块的策略。目标是在bundlebundless 之间找到平衡,通过打包相关的模块以提高加载性能,同时不尽量丢失缓存颗粒度

目前,构建工具(比如 webpackrollup)处理模块的主要方法有两种:完全打包原生ESM。但它们都有缺点:

  • 对于完全打包,打包工具旨在将所有内容打包在一起,然后拆分出来进行优化,但拆分通常难以配置,手动平衡资源加载性能和缓存命中率很难。
  • 对于原生ESM,每个模块都可以单独编译和缓存,但当项目规模大起来,有数百个或数千模块请求时,会严重影响加载性能。

上图表示 bundlebundless 两种极端:bundle 将所有 TS/JS/TSXCSS 打包成一个输出文件,缓存复用率低,如果拆包,配置复杂且困难; bundless 完全不打包,对于大项目,动辄数百数千个模块,每次刷新页面都伴随大量的模块请求,严重影响性能和开发体验。

因此,我一直在思考是否有一种策略可以避免这两种极端情况 - 也许我们可以进行局部打包?我们可以直接将项目打包成若干个数量有限大小均衡的资源。我将这种思考命名为 局部打包Partial Bundling )- 全量打包不打包 之间找到平衡,通过打包相关的模块以提高加载性能,同时不尽量丢失缓存颗粒度

如上图所示,Farm 通过 局部打包,将有依赖关系的数千个模块,打包成有限的 jscss 产物,消除依赖的同时限制请求数量,在 bundlebundless 之间取得一个平衡。

基于 局部打包的思想 Farm 设计了一整套打包算法,并给出了实现。Farm 局部打包 与其它打包工具不同,Farm 不会尝试将所有内容打包在一起再使用像 splitChunks 之类的优化策略拆包。相反,Farm 会将项目直接打包成多个产物文件。例如,如果需要数百个模块来启动和渲染一个 html 页面,Farm 将基于 局部打包 算法尝试将它们直接打包成 20 到 30 个输出文件。

Farm 局部打包的目标是:

  1. 减少请求数量和请求层次: 将数百上千个模块请求减少到20-30个请求,避免大量并发请求,以及由于依赖层次结构而必须按照拓扑顺序逐层加载模块,从而加快资源的加载。
  2. 提高缓存命中率: 相关的模块会尽可能打包到一起,当某些模块发生更改时,确保只有少数输出文件受到影响,因此可以为项目提高缓存命中率。

对于传统打包工具,我们可能很难通过复杂的 splitChunksmanualChunks 配置来实现上述目标,但是 Farm 通过 局部打包 原生支持。

关于局部打包的更多细节,参考文档 Partial Bundling

4.6 插件生态

Farm 采用了插件化的设计,完全可拔插,并且设计了一整套完善插件系统来支持插件生态。当前 Farm 支持如下 4 中类型的插件:

  • Farm 编译插件 :支持 Rust 插件和 Js 插件,采用 rollup 风格的 hooks
    • Farm Rust 插件:使用 Rust 编写的插件,具有最佳性能
    • Farm Js 插件:使用 Js 编写的插件,性能差于 Rust,但编写更方便
  • Farm 运行时插件:增强 Farm 的运行时模块系统
  • Vite/Rollup/Unplugin 插件 :Farm 开箱即用支持 Vite/Rollup/Unplugin 插件
  • Swc 插件 :Farm 开箱即用支持 Swc 插件

Farm 插件钩子概览如下:

Vite/Rollup/Unplugin 的插件的兼容,是基于上述 Farm 插件钩子通过适配器实现

Farm 提供了大量的官方插件来支持常用的编译能力,如:

  • @farmfe/plugin-react:支持 React Jsx 转换以及 React Refresh
  • @farmfe/js-plugin-sass:支持 Sass 编译
  • @farmfe/js-plugin-less:支持 Less 编译
  • @farmfe/js-plugin-postcss:支持 Postcss 编译
  • ...

大部分的 Vite/Rollup/Unplugin 插件在 Farm 中开箱即用:

  • @vitejs/plugin-vue: 支持 Vue 编译
  • @vitejs/plugin-vue-jsx: 支持 Vue Jsx 编译
  • unplugin-auto-import
  • unplugin-auto-component
  • ...

关于在 Farm 中使用各类插件的,参考 Using Plugins,关于配置插件的介绍,参考 Plugins

编写自己的 Farm 插件也相当简单,Farm 提供了插件模板可一键创建:

sh 复制代码
pnpm create farm-plugin

支持 Rust 插件和 JS 插件,详情参考文档 Writing Plugins

4.7 SSR 支持

Farm 支持 SSR(Server-Side Rendering,服务端渲染),SSR 可以极大提升首屏的加载性能,提升页面的 SEO 等。基于 Farm 可以实现极速 SSR 构建,体验极致 SSR 性能!

一个典型的 Farm SSR 项目结构如下:

text 复制代码
.
├── index.html
├── farm.config.ts
├── farm.config.server.ts
├── server.js
└── src
    ├── index-client.tsx
    ├── index-server.tsx
    └── main.tsx

需要分别提供 clientserver 入口,然后使用 Farm 构建 clientserver 入口。Farm 为常用框架提供了 SSR 示例:

关于 SSR 的更多细节,参考文档 Server-Side Rendering

四、真实项目演示

Farm 支持 React、Vue、Solid、Svelte 等常见框架,并且已有真实项目从 Webpack/Vite 迁移到 Farm。如下我们给出了最常用的两种框架(React、Vue)的中后台项目示例。

4.1 React 中后台项目

如上图所示 Farm 可以在 500ms 热启动并渲染出一个复杂的中后台项目。

4.2 Vue 项目

下图中,下方是 Farm,上方是 Vite,明显可以看到,同为 热启动 + 全 Vite 插件 编译 Vue 项目的条件下,Farm 比 Vite 5。该项目是从 Vite 迁移到 Farm,由于 Farm 兼容 Vite 生态,该项目的所有 Vite 插件都可以直接复用,迁移成本很低。

五、小结

Farm 由开源社区共同开发建设,历经近两年的开发,终于发布了 1.0 版本。1.0 版本包含了 web 构建工具需要的全部能力,通过 Rust 多线程 + 懒编译 + 增量编译等手段,极大提升 web 项目构建性能,提供更加极致的构建性能体验!

未来 Farm 将:

  1. 继续做更多上层框架的建设,例如 SSR 框架等
  2. 打造 Rust 插件生态,使用 Rust 实现或者重构现有的常用工具,提供更加极致的性能体验

鸣谢:

  • brightwu(吴明亮):Farm 作者和 Lead Maintainer,创建、设计并实现了 Farm 的大部分功能
  • ErKeLost:Farm 核心维护者,设计并实现了大部分 Node 侧以及 Rust Resolver 的能力
  • shulandmimi:Farm 核心维护者,开发、维护了大量 Farm 插件,实现、优化了大量 Rust Compiler 的内置能力,如压缩、Tree Shake等等
  • Farm 组织成员:参与了 Farm 各类特性的优化、开发,Bugfix 等等
  • 社区贡献者:参与 Farm 的贡献,协助实现了各类特性和问题修复
相关推荐
茶卡盐佑星_7 分钟前
vue如何解决跨域?原理?
前端·javascript·vue.js
河北小田12 分钟前
十四、模板引用
前端·vue.js·程序员
Clank的游戏栈14 分钟前
Unity3D 场景树与组件化开发详解
前端
前端fighter18 分钟前
表单代码示例
前端·javascript·vue.js
二十雨辰38 分钟前
[JS]面向对象ES6
前端·javascript·ajax
GDAL39 分钟前
css之transform-origin
前端·css
疯狂创作者41 分钟前
十款绚丽的前端 CSS 菜单导航动画
前端·css
秃头女孩y1 小时前
前端之CSS篇--面试题总结
前端·css
2402_857583491 小时前
定制化的 CSS 魔法:WebKit 处理 CSS 变量的深度解析
前端·css·webkit
椰果uu1 小时前
实习手记(2):前端菜鸟的摸鱼与成长
前端·前端实习