查看原文
科技

都在卷打包工具?Rspack 又有什么特性?

程序员Sunday 程序员Sunday
2024-08-31

前端训练营:1v1私教,终身辅导计划,帮你拿到满意的 offer 已帮助数百位同学拿到了中大厂 offer

Hello,大家好,我是 Sunday。

Webpack 作为最经典的 前端打包工具,这几年过的可真是不太平。

前有 Vite 出现,号称可以 “颠覆 webpack”。后有webpack创始人推出新的打包工具 Turbopack,号称比 webpack 快 700 倍。

这不,三天前(8月28日),字节跳动也推出了全新的打包工具 Rspack,号称 能够无缝替换 webpack, 并提供闪电般的构建速度

那么到目前为止,Rspack 也正式推出 3 天了,所以今天咱们就来看看它吧!

制作 Rspack 的初衷

根据原生团队描述:Rspack 的推出,最初是为了解决字节内部 巨石应用 的问题。

使用 webpack 时,每次编译都需要耗时 十几分钟,甚至半个小时的时间,并且基于 webpack 的优化收效甚微,因此才有了构建 Rspack 的需求。

整个构建的过程,遵循以下 4 个标准:

  • 快速的 Dev 启动性能:npm run dev 是开发者每天需要运行很多次的命令,但大型项目每次都需要等待 10 分钟,这对于工程师来说非常痛苦,因此优化开发模式下启动的时间至关重要。

  • 高效的 Build 性能:npm run build 经常在 CI/CD 环境中运行,它决定了应用生产交付的效率。有些应用在生产环境中需要 20 到 30 分钟的构建时间,如果能缩短这段时间,对开发流程也将非常有帮助。

  • 灵活的配置:用户工程的配置非常灵活,不够统一。在之前的尝试中,将 webpack 配置迁移到其他构建工具时,我们遇到了许多问题,因为其他构建工具的配置不如 webpack 灵活。

  • 生产环境的优化能力:在启用 Rspack 之前,我们尝试了社区内的各种方案,但它们都面临着一定程度的生产环境负优化,例如拆分包不够精细等。因此,优化生产环境的产物是我们不可放弃的功能。

体验下 Rspack

整个 Rspack 的使用场景主要分为两种:

  1. 直接使用 Rspack 创建全新项目
  2. 从一个基于 webpack 的项目迁移到 Rspack。毕竟 Rspack 号称可以 “无缝替换 webpack”。如果大家也在现有项目中饱受 编译过慢 的问题,那么不妨可以进行一下尝试。

直接使用 Rspack 创建全新项目

这种操作比较简单,与使用 vue-cli、vite、CRA 的区别并不大

官方 推荐使用 Rsbuild 创建项目

Rsbuild 是由 Rspack 驱动的高性能构建工具,由 Rspack 团队开发。它默认包含了一套精心设计的构建配置,提供开箱即用的开发体验,并能够充分发挥出 Rspack 的性能优势。

npm create rsbuild@latest

从 webpack 中迁移

这应该是很多同学真正的痛点了。

如果大家也在现有项目中饱受 编译过慢 的问题,那么不妨可以进行一下尝试。

在这里,Rspack 提供了多种迁移方案:

我们以 vue-cli 为例,整个迁移过程比较平滑:

1. 安装依赖

首先你需要把 Vue CLI 的 npm 依赖替换为 Rsbuild 的依赖。

移除 Vue CLI 的依赖:

npm remove @vue/cli-service @vue/cli-plugin-babel @vue/cli-plugin-eslint core-js

安装 Rsbuild 的依赖:

npm add @rsbuild/core @rsbuild/plugin-vue -D

如果你的项目是基于 Vue 2 的,请将 @rsbuild/plugin-vue 替换为 @rsbuild/plugin-vue2。

2. 更新 npm scripts

下一步,你需要把 package.json 中的 npm scripts 更新为 Rsbuild 的 CLI 命令。

{
"scripts": {
- "serve": "vue-cli-service serve",
- "build": "vue-cli-service build",
+ "serve": "rsbuild dev",
+ "build": "rsbuild build",
+ "preview": "rsbuild preview"
}
}

Rsbuild 未集成 ESLint,因此没有提供用于替换 vue-cli-service lint 的命令,你可以直接使用 ESLint 的 CLI 命令 作为替代。

3. 创建配置文件

在 package.json 的同级目录下创建 Rsbuild 的配置文件 rsbuild.config.ts,并添加以下内容:

import { defineConfig } from '@rsbuild/core';
import { pluginVue } from '@rsbuild/plugin-vue';

export default defineConfig({
  plugins: [pluginVue()],
  source: {
    // 指定入口文件
    entry: {
      index'./src/main.js',
    },
  },
});

如果你的项目是基于 Vue 2 的,请使用 import { pluginVue2 } from '@rsbuild/plugin-vue2';。

4. HTML 模板

Vue CLI 默认使用 public/index.html 文件作为 HTML 模板。在 Rsbuild 中,你可以通过 html.template 来指定 HTML 模板:

// rsbuild.config.ts
export default defineConfig({
  html: {
    template: './public/index.html',
  },
});

在 HTML 模板中,如果使用了 Vue CLI 的 BASE_URL 变量,请替换为 Rsbuild 的 assetPrefix 变量,并使用斜杠进行连接:

- <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+ <link rel="icon" href="<%= assetPrefix %>/favicon.ico">

这样就完成了从 Vue CLI 到 Rsbuild 的基本迁移,此时你可以执行 npm run serve 命令来尝试启动开发服务器。

5. 配置迁移处理方案

部分配置方案需要进行替换:

6. 环境变量处理方案

Vue CLI 默认会将 VUE_APP_ 开头的环境变量注入到 client 代码中,而 Rsbuild 默认会注入 PUBLIC_ 开头的环境变量(参考 public 变量)。

为了兼容 Vue CLI 的行为,你可以手动调用 Rsbuild 提供的 loadEnv 方法来读取 VUE_APP_ 开头的环境变量,并通过 source.define 配置项注入到 client 代码中。

// rsbuild.config.ts
import { defineConfig, loadEnv } from '@rsbuild/core';

const { publicVars } = loadEnv({ prefixes: ['VUE_APP_'] });

export default defineConfig({
  source: {
    define: publicVars,
  },
});

和其他构建工具的对比

每个工具出现之后,都会和其他的工具对比一番,并借此描述出 “自己的各种优势”。

因此,这种对比可能并没有那么的“公正(毕竟大佬针对特定场景下性能问题的撕逼情况也并不少见)”。因此 该部分仅供参考

和 webpack 的区别

webpack 是目前最为成熟的构建工具,有着活跃的生态,灵活的配置和丰富的功能,但是其最为人诟病的是其性能问题,尤其在一些大型项目上,构建花费的时间可能会达到几分钟甚至几十分钟,性能问题是目前 webpack 最大的短板。因此 Rspack 解决的问题核心就是 webpack 的性能问题。 Rspack 比 webpack 快得益于如下几方面:

  • Rust 语言优势: Rspack 使用 Rust 语言编写, 得益于 Rust 的高性能编译器支持, Rust 编译生成的 Native Code 通常比 JavaScript 性能更为高效。
  • 高度并行的架构: webpack 受限于 JavaScript 对多线程的羸弱支持,导致其很难进行高度的并行化计算,而得益于 Rust 语言的并行化的良好支持, Rspack 采用了高度并行化的架构,如模块图生成,代码生成等阶段,都是采用多线程并行执行,这使得其编译性能随着 CPU 核心数的增长而增长,充分挖掘 CPU 的多核优势。
  • 内置大部分的功能: 事实上 webpack 本身的性能足够高效,但是因为 webpack 本身内置了较少的功能,这使得我们在使用 webpack 做现代 Web App 开发时,通常需要配合很多的 plugin 和 loader 进行使用,而这些 loader 和 plugin 往往是性能的瓶颈,而 Rspack 虽然支持 loader 和 plugin,但是保证绝大部分常用功能都内置在 Rspack 内,从而减小 JS plugin | loader 导致的低性能和通信开销问题。
  • 增量编译: 尽管 Rspack 的全量编译足够高效,但是当项目庞大时,全量的编译仍然难以满足 HMR 的性能要求,因此在 HMR 阶段,我们采用的是更为高效的增量编译策略,从而保证,无论你的项目多大,其 HMR 的开销总是控制在合理范围内。

和 Vite 的区别

Vite 提供了很好的开发者体验,但 Vite 在生产构建中依赖了 Rollup ,因此与其他基于 JavaScript 的工具链一样,面临着生产环境的构建性能问题。

另外,Rollup 相较于 webpack 做了一些平衡取舍,在这里同样适用。比如,Rollup 缺失了 webpack 对于拆包的灵活性,即缺失了 optimization.splitChunks 提供的很多功能。

和 esbuild 的区别

我们在内部进行过大规模地将 esbuild 作为通用的 Web App 构建工具的实践,但是遇到如下一些问题:

缺乏对 JavaScript HMR 和增量编译的良好支持,这导致大型项目中的 HMR 性能较差。 拆包策略也非常原始,难以满足业务复杂多变的拆包优化需求。

和 Turbopack 的区别

Rspack 和 turbopack 都是基于 Rust 实现的 bundler,且都发挥了 Rust 语言的优势。

与 turbopack 不同的是,Rspack 选择了对 webpack 生态兼容的路线,一方面,这些兼容可能会带来一定的性能开销,但在实际的业务落地中,我们发现对于大部分的应用来说,这些性能开销是可以接受的,另一方面,这些兼容也使得 Rspack 可以更好地与上层的框架和生态进行集成,能够实现业务的渐进式迁移。

和 Rollup 的区别

Rspack 和 Rollup 虽然都是打包工具,但是两者的侧重领域不同,Rollup 更适合用于打包库,而 Rspack 适合用于打包应用。因此 Rspack 对打包应用进行了很多优化,如 HMR、Bundle splitting 等功能,而 Rollup 则比 Rspack 的编译产物对库更为友好,如更好的 ESM 产物支持。 社区上也有很多的工具在 Rollup 基础上进行了一定的封装,提供了对应用打包更友好的支持,如 vite 和 wmr, 目前 Rspack 比 Rollup 有更好的生产环境构建性能。

和 Parcel 的区别

Rspack 的整体架构与 Parcel 有很多共同之处。例如都将 CSS 资源视为一等公民,都支持基于 filter 的 transformer。然而,Parcel 更加注重开箱即用的体验,而 Rspack 更加注重为上层框架提供灵活的配置。Parcel 开创性地设计了 Unified Graph 和使 HTML 成为一等公民的特性。Rspack 也计划在未来支持这些特性。

1v1私教,帮大家拿到满意的 offer

  1v1 帮大家 offer 

通,备注【训练营】


继续滑动看下一个
程序员Sunday
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存