今天给大家带来的主题是Farm,即一个快速、强大、本地与生产环境保持一致的 Web 打包器,目标是解决 Vite 面临的主要问题。话不多说,直接开始!
随着 web 项目规模的扩大,构建性能成为了开发者面临的主要问题。对于一个巨大的前端项目而言,使用 webpack 编译可能需要 10 分钟甚至更长时间,而热更新可能需要超过 10s,从而大大降低了前端开发的效率。
随着 vite 的出现,它在开发模式下使用原生的 ESM(即非打包模式) ,同时使用 esbuild 预打包依赖项,极大提升了应用开发服务器启动和热更新效率。但是非打包模式(Unbundled)并不完美,对于大型项目来说还是有很大的问题:
鉴于 Vite 的现状和面临的问题,Farm 认为,前端开发者需要一个快速、强大、本地/生产环境一致的 Web 打包器,从而解决 Vite 面临的问题。
其实,Farm 不仅仅是一个用 Rust 重写的普通打包器,它还包括很多强大和进步的设计。在性能方面,Vite 与其他工具的基准测试(使用 Turbopack 的基准测试,1000 个 React 组件)数据如下:
不论是在冷启动,热更新等方面,Farm 比 Webpack(纯 JS 打包)、Vite(本质也算 Rust 方案)、Turbopack(Rust 方案)、Rspack(Rust 方案,字节开源) 等都有显著的优势。
值得一提的是,Farm 的作者是 brightwu(吴明亮),曾就职于字节跳动和腾讯。 Farm 开源时间不到一年,在 Github 上已有 500+的 star,是一个值得持续关注的项目。
Farm 的目标是成为真正的下一代构建工具,快速、强大、多环境一致,并为 Web 开发人员提供最佳的开发体验。
Farm 需要 Node 16 及以上版本,如果开发者使用的是 linux,请确保操作系统版本为 ubuntu 22 及以上(GLIBC >= 2.32)。
@farmfe/cli 包提供创建、启动和构建 Farm 项目或 Farm 插件的能力。使用如下创建命令来初始化一个新的 Farm 项目。
npx @farmfe/cli@latest create
需要注意的是:create 命令目前只支持初始化一个简单的 React 项目,但是已经在逐步增强功能阶段。
首先执行 install 命令 ,可以选择喜欢的包管理器,npm 或 yarn 或 pnpm:
cd farm-react && npm install
// npm
cd farm-react && yarn
// yarn
cd farm-react && pnpm install
// pnpm
npm start
// 开始项目
直接通过浏览器访问地址 http://localhost:9000 即可开始。
该项目由项目根目录下的 farm.config.ts 文件配置,比如下面是 farm.config.ts 的内容:
import { defineConfig } from '@farmfe/core/dist/config';
export default defineConfig({
// 与编译相关的选项
compilation: {
input: {
//可以是相对路径或绝对路径
index: './index.html',
},
output: {
path: './build',
publicPath: '/',
},
// ...
},
// 与开发服务器相关的选项
server: {
port: 9000,
// ...
},
// 附加插件配置
plugins: [],
});
目前,Farm 已经实现了 Web 构建工具的基本功能, 但是要用于生产环境部署还有很多事情要做。
如上列表所示,目前 Farm 很多生产部署功能还依然在开发中,值得期待!
当涉及到一个大项目时,开发者可以拆分成小块并按需加载,这可以通过动态导入来实现。
const page = React.lazy(() => import('./page'));
// 懒加载
默认情况下,Farm 会延迟编译这些动态导入,只有在真正需要模块时才编译它们。
回到 webpack,开发者经常使用 splitChunks 来拆分 bundle,试图优化资源加载时间和提高缓存命中率。 但是配置 splitChunks 很复杂,有时达不到想要的效果。
所以 Farm 引入了 Partial Bundling,根据依赖关系和资源大小自动将应用程序打包到多个资源中。
从 v0.4 Farm 开始支持三种资源加载方式: url, inline, raw 。下面是 url 模式:
import rocketUrl from './assets/rocket.svg'; // return the url of this image
export function MAIn() {
return <img src={rocketUrl} />; // using the url
}
使用 query ?inline 告诉 Farm 想要内联资产,然后资产将转换为 base64,例如:
// importer
import logo from './assets/logo.png?inline';
// logo is a base 64 str
// the image module
export default 'data:image/png,base64,xxxxx==';
例如,使用 ?raw 告诉 Farm 想要读取资产的原始字符串
// import
import logo from './assets/license.txt?raw';
// return the content string of the assets
// license.txt
export default 'MIT xxxx';
Farm 支持开箱即用地编译 Js/Jsx/Ts/Tsx,默认将 Jsx/Tsx 编译为 React。
import Button from './Button';
function ButtonGroup(props: ButtonProps) {
return (
<div>
{props.buttons.map((b) => (
<Button>{b}</Button>
))}
</div>
);
}
默认情况下 Farm 使用 swc 来编译脚本,可以使用 compilation.script 修改配置。
本文主要和大家介绍Farm,即一个快速、强大、本地与生产环境保持一致的 Web 打包器,目标是解决 Vite 面临的主要问题。当然,正如文中所言,Farm的很多能力还在陆续开发、增强中,但是它目的非常明确,是一个值得长期关注的方案。
因为篇幅有限,文章并没有过多展开,如果有兴趣,文末的参考资料提供了优秀文档以供学习。最后,欢迎大家点赞、评论、转发、收藏!
https://farm-fe.github.io/docs/why-farm
https://github.com/farm-fe/farm
https://github.com/farm-fe/performance-compare
https://farm-fe.github.io/docs/features/static
https://farm-fe.github.io/docs/features/script