Turborepo v1.10 发布!Turbopack 还能更快?

家好,很高兴又见面了,我是"高级前端 进阶 ",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。

前言

Vercel 的使命是提供创新者在灵感迸发时所需的速度和可靠性。 Vercel专注于加快 Next.js 打包应用程序的方式。

从基于 JavaScript 的工具转移到基于 Rust 的工具时看到了巨大的性能改进。 从 Babel 迁移出来后转译速度提高了 17 倍。 替换了 Terser 使压缩速度提高了 6 倍,从而显著减少了加载时间和带宽使用。

那么最终只剩下一个障碍,那就是Webpack。 Webpack 已被下载超过 35.16 亿次, 它已成为构建 Web 不可或缺的一部分,但现在是时候考虑构建速度了!在此背景下,Vercel推出了Turbopack,即一个号称 Webpack 继任者的打包工具。

Turbopack:基于 Rust 的 Webpack 继承者

在 Webpack 创建者 Tobias Koppers 的带领下,Turbopack 已经俨然成为 Web 的下一代打包器。 而且目前已经开源,未来将适用于所有框架。

1.为什么 Turbopack 这么快

1.1 什么是增量构建

以 Webpack的构建为例,在执 webpack-dev-server 命令后,Webpack 会进 次初始化的构建,构建完成后开发服务器进 到等待更新的状态,比如开启了watch模式。当本地 件有变更时,Webpack 会即时将变更的 件进 重新编译,并将编译后的代码内容推送到浏览器端,这就是所谓的“增量构建”。

增量构建之所以快是因为将构建所需的内容都预先存储、保留在内存中,使下 次重新构建时可直接从内存读取数据。但是, 产环境下的构建流通常在远程构建系统中完成。对于管理多项 的构建系统 ,构建过程是任务式的,任务结束后则进程结束,系统资源回收。

因此,要想在 产环境下提升构建速度, 要条件是将缓存写 到 件系统中。只有将 件系统中的缓存数据持久化,才能脱离对进程的依赖。目前Webpack 5 中已经 持基于 件系统的持久化缓存(Persistent Cache)。比如下面的例子:

cache: {
    type: "filesystem",
    buildDependencies: {
        config: [ __filename ] 
       // 当 CLI 自动添加它时,您可以忽略它
    }
}

1.2 Turbopack的增量构建

Turbopack 建立在新的增量架构之上,以提供最快的开发体验。 在大型应用程序上,更新速度比 Webpack 快 700 倍。

这是因为Turbopack 仅打包开发所需的最少资源,因此启动时间非常快。 在具有 5,000 个模块的应用程序上,Turbopack 需要 4 秒才能启动,而 Vite(带有 SWC)需要 16.6 秒。

下面是冷启动下不同框架的打包时长对比(示例中React组件数量为1000)。

下面是文件变化时候不同框架的打包时长对比:

总体来说,不论是冷启动、还是文件变化的热启动,Turbopack相较于Vite都有更好的性能表现。

2.为什么 Turbopack 这么快

2.1 借助于增量记忆框架

什么是Turbo

Turbo的logo

Turbo 是用 Rust 编写的用于前端开发的下一代工具链。 它由3个主要部分组成:

Turbopack基于Turbo

Turbopack 的架构吸取了 Turborepo 和 Google 的 Bazel 等工具的经验教训,这两个工具都专注于使用缓存来避免重复执行相同的工作。

Turbopack 建立在 Turbo 之上,Turbo 可以缓存程序中任何函数的结果。 当程序再次运行时,函数不会重新运行,除非它们的输入发生变化。 这种细粒度的架构调整使得程序能够在函数级别跳过大量工作。

函数级缓存

在 Turbo 引擎驱动的程序中,可以将某些功能标记为“要记住”。 当这些函数被调用时,Turbo 引擎会记住它们被调用的内容以及返回结果,然后将结果缓存在内存中。

比如下面的简化示例,说明了在打包器中各个文件的的样子:

首先两个文件 api.ts 和 sdk.ts 都调用了 readFile。 然后使用Turbopack打包这些文件,将它们连接在一起,生成最后的bundle。 所有这些函数调用的结果都保存在缓存中以备后用。

假设打包过程在开发服务器上运行, sdk.ts 将保存在本机上。 Turbopack 收到文件系统的变更事件,知道自己需要重新计算 readFile("sdk.ts"):

由于sdk.ts的结果变了,Turbopack需要重新打包,然后再拼接。需要注意的是,api.ts 没有改变。 Turbopack将从缓存中读取结果并将其传递给 concat 。 因此,可以跳过重新打包api.ts文件来节省重复打包时间。

想象一下,在一个真正的打包器中,有成千上万的文件要读取、转换、执行。以上流程将显著提升打包效率。

缓存

Turbo 引擎目前将其缓存存储在内存中。 这意味着缓存的持续时间与运行它的进程一样长,这对开发服务器来说很有效。 比如在 Next v13 中运行 :

next dev --turbo

Turbopack 将使用 Turbo 引擎启动缓存,当停止开发服务器时,缓存将被清除。

Turbopack未来计划保留此缓存能力 ,比如保存到文件系统,或保存到类似 Turborepo 的远程缓存中,从而实现Turbopack 的跨机器运行能力。

2.2 按需编译

Turbo 引擎有助于在开发服务器上提供极快的更新,但还有另一个重要指标需要考虑,启动时间。 开发服务器开始运行的速度越快,就能越快的介入研发工作。

解决这个问题的方法就是做更少的工作!Turbopack 巧妙的引入了按需编译策略,只编译启动所需的代码,从而大幅度提升速度。

页面级编译

以前的Next.js会编译整个应用程序, 从 Next.js 11开始,Turbopack只编译请求的页面上的代码。但是,这也会产生一些潜在问题。比如, 当用户导航到新的路由时,Turbopack将打包所有客户端和服务器模块、动态导入的模块以及引用的 CSS 和图像。 这意味着如果页面的很大一部分隐藏在视图之外,或者隐藏在选项卡后面,Turbopack仍然会对其进行编译。

请求级编译

Turbopack 足够聪明,可以只编译请求的代码。 这意味着如果浏览器请求 HTML,Turbopack只编译 HTML,而不是 HTML 引用的所有内容。

如果浏览器需要一些 CSS,将只编译CSS,而不编译引用的图像。 通过请求级编译,既可以减少请求的数量,又可以使用本机速度来编译它们,从而提供显著的性能改进。

3.Turbopack 使用

ECMAScript支持

Turbopack 使用 SWC 打包 JavaScript 和 TypeScript 文件。因此,需要匹配 SWC 对 ECMAScript 版本的支持。WC 支持的任何内容,Turbopack 都将支持。 这意味着默认情况下支持 ESNext 中的所有语法。

Browserslist已成为定义计划定位的浏览器的行业标准。要使用它,可以将 browserslist 字段添加到 package.json:

{
  "browserslist": [
    "last 1 version",
    "> 1%",
    "not dead"
  ]
}

TypeScript支持

Turbopack 开箱即用地支持 TypeScript。这意味着可以使用 Turbopack 导入 .ts 文件,同时支持 TypeScript 的所有功能集。 由于 JSX 支持,还可以导入 .tsx 文件:

在 TypeScript 中,可以使用 tsconfig.json 的 paths属性从自定义路径导入文件。

{
  "compilerOptions": {
    "baseUrl": "src",
    "paths": {
        "app/*": ["app/*"],
        "config/*": ["app/_config/*"],
        "shared/*": ["app/_shared/*"],
    },
}

框架集成

Turbopack 计划为多个框架提供一流的支持。无论开发者使用的是 Svelte、React、Vue.js 还是其他框架,都希望在 Turbopack 上提供出色的体验。

Turbopack 开箱即用地支持 .jsx 和 .tsx 文件。 使用 SWC编译 JavaScript 和 TypeScript 代码,从而实现极快的编译速度。与 Next.js 类似,Turbopack 不需要手动导入 React 即可使用 JSX:

- import React from 'react';
const Component = () => {
  return 
}

CSS支持

CSS 打包由 SWC 使用名为 swc_css 的 Rust crate 处理。Turbopack尚未单独记录 swc_css,但它已集成到 Turbopack 中并支持多种 CSS 功能:

import './globals.css';
// 全局导入
import cssExports from './phone.module.css'
// css module支持

Turbopack 开箱即用地处理 postcss-nested语法。这个有用的库可以让开发者将 CSS 声明相互嵌套:

.phone {
    &_title {
        width: 500px;
        @media (max-width: 500px) {
            width: auto;
        }
        body.is_dark & {
            color: white;
        }
    }
    img {
        display: block;
    }
}

静态资源导入

Web 打包的一部分是处理 Web 支持的所有资产类型,比如图像、视频、JSON、字体等等。 Turbopack 提供了熟悉的工具,可以直接使用。

import img from './img.png'
import video from './video.mp4'
import audio from './audio.wav'
import fixtures from './fixtures.json';

环境变量

Turbopack 将开箱即用地解析和注入 .env 文件。

NEXT_PUBLIC_DEPLOYMENT_NAME="my-site"
DATABASE_URL="postgres://"

以上将包括这些文件的所有变体:

.env
.env.local
.env.development
.env.production.local

4.Turborepo v1.10 新特性

2023 年 6 月 1 日,Turborepo v1.10 发布,该版本引入了诸多新功能改善本地开发体验:

可以通过下面命令快速更新:

npx @tu rbo/codemod migrate

4.1 Turborepo 代码生成器

Turborepo 生成器允许开发者以可预测的结构化方式将新代码添加到存储库中。 以前,开发者需要自己复制代码并手动将依赖项添加到新工作区。 借助 Generators,自动化了创建新工作区并将其集成到存储库中的过程。

开发者可以从头开始创建空白工作区、复制现有工作区,甚至创建自定义生成器以进行更多控制。 自定义生成器利用 Plop(在新选项卡中打开)配置,这是 JavaScript 生态系统中使用的常见模板定义策略。

自定义生成器还可以用于构建比工作区更细粒度的代码集,从而显著加快以下任务的速度:

通过运行以下命令开始使用第一个生成器:

turbo gen

4.2 改进的环境变量输入

支持 .env 文件

.env 文件(在新选项卡中打开)通常用于加载环境变量。 当使用 Turbo 运行时,这可能会导致问题,因为这些变量可能是不可见的,并且不容易包含在任务的哈希中。 在本地工作时,此问题可能会导致意外的缓存命中。

Turborepo 现在通过自动支持 .env 文件使这一切变得更加容易。为了确保 Turborepo 在哈希中包含这些变量,请使用 dotEnv 键。 例如,以下是 Next.js 应用程序的配置:

{
  "$schema": "https://turbo.build/schema.json",
  "globalDotEnv": [".env"],
  "pipeline": {
    "build": {
      "dotEnv": [".env.production.local", ".env.local", ".env.production", ".env"]
    },
    "dev": {
      "dotEnv": [".env.development.local", ".env.local", ".env.development", ".env"]
    },
    "test": {
      "dotEnv": [".env.test.local", ".env.test", ".env"]
    }
  }
}

环境变量通配符

大型应用程序的 turbo.json 中可能会包含许多环境变量,这可能会使配置难以管理和维护。

使用通配符,开发者现在可以指定要包含在哈希中的变量模式。

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "env": ["ACME_*"]
    }
  }
}

环境模式

Turborepo 环境模式现已脱离实验模式,可供一般使用。

默认情况下,当使用 --env-mode=loose 调用 Turbo run 时,计算机中的所有环境变量都可供每个 Turborepo 任务使用。 这确保了最大的兼容性,同时接受任务将隐式访问turbo.json中未指定的环境变量的一些风险。

在新的严格模式中,当使用 --env-mode=strict 调用turbo 时,只有重要的系统环境变量和turbo.json 中枚举的环境变量将对任务可用。

5.Turbopack的未来

首先,Turbopack 将用于 Next.js 13 开发服务器。 它将为快如闪电的 HMR 提供支持,并将原生支持 React 服务器组件,以及 TypeScript、JSX、CSS 等。

Turbopack 最终还将为本地和云端的 Next.js 生产构建提供支持,从而能够使用 Vercel 远程缓存在整个团队中共享 Turbo 的缓存。

Webpack 用户还可以期待通过 Turbopack 逐步迁移到基于 Rust 的未来。

6.本文总结

本文主要和大家介绍下最近炒的火热的Turbopack。文章从Turbopack 有多快 、为什么 Turbopack 这么快, Turbopack的未来等诸多维度进行展开。

因为篇幅有限,关于Turbopack 的更多用法和特性文章并没有过多展开,如果有兴趣,可以在我的主页继续阅读,同时文末的参考资料提供了大量优秀文档以供学习。最后,欢迎大家点赞、评论、转发、收藏,您的支持是我不断创作的动力。

参考资料

https://vercel.com/blog/turbopack

https://turbo.build/pack/docs/core-concepts

https://www.jianshu.com/p/b86af1b35fdc

https://dev.to/omher/what-is-turbopack-58ll

https://turbo.build/pack/docs/why-turbopack

https://github.com/vercel/turbo

https://turbo.build/pack

https://turbo.build/blog/turbo-1-10-0

展开阅读全文

页面更新:2024-04-17

标签:生成器   增量   开发者   缓存   环境变量   框架   速度   代码   文件   工作

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top