laitimes

Turborepo v1.10 released! Can the Turbopack be faster?

author:Advanced front-end advanced

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

Turborepo v1.10 released! Can the Turbopack be faster?

preface

Vercel's mission is to deliver the speed and reliability innovators need when inspiration strikes. Vercel is focused on accelerating the way Next.js packages applications.

Saw huge performance improvements when moving from JavaScript-based tools to Rust-based tools. Translation speed increased by 17x after migrating from Babel. Replacing Terser results in 6x faster compression, significantly reducing load times and bandwidth usage.

Then in the end, there is only one obstacle left, and that is Webpack. With over 3.516 billion downloads, Webpack has become an integral part of building the web, but it's time to think about build speed! In this context, Vercel launched Turbopack, a packaging tool known as the successor to Webpack.

Turborepo v1.10 released! Can the Turbopack be faster?

Turbopack: The Rust-based Webpack successor

Led by Webpack creator Tobias Koppers, Turbopack has become the web's next generation of packagers. It's now open source and will work with all frameworks in the future.

1. Why is Turbopack so fast

1.1 What is incremental build

Taking the build of Webpack as an example, after executing the webpack-dev-server command, Webpack will perform an initial build, and after the build is completed, the development server enters a state waiting for updates, such as enabling watch mode. When there is a change in the local file, Webpack will immediately recompile the changed file and push the compiled code content to the browser, which is called "incremental build".

Turborepo v1.10 released! Can the Turbopack be faster?

Incremental builds are fast because everything needed for the build is stored upfront and kept in memory, so that the data can be read directly from memory on the next rebuild. However, build flows in production are typically done in remote build systems. For build systems that manage multiple projects, the build process is task-based, and after the task ends, the process ends and system resources are reclaimed.

Therefore, to increase build speed in a production environment, the first condition is to write the cache to the file system. Only by persisting cached data in the file system can you get rid of the dependency on the process. Webpack 5 already supports persistent cache based on file systems. For example, the following example:

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

1.2 Incremental builds of Turbopack

Turbopack is built on a new incremental architecture to provide the fastest development experience. On large applications, updates are up to 700 times faster than Webpack.

This is because Turbopack only packages the minimum resources required for development, so startup times are very fast. On an app with 5,000 modules, the Turbopack takes 4 seconds to launch, while the Vite (with SWC) takes 16.6 seconds.

The following is a comparison of the packaging time of different frameworks under cold start (the number of React components in the example is 1000).

Turborepo v1.10 released! Can the Turbopack be faster?

The following is a comparison of the packaging time of different frameworks when the file changes:

Turborepo v1.10 released! Can the Turbopack be faster?

Overall, whether it is a cold start or a hot start of file changes, Turbopack has better performance than Vite.

2. Why is Turbopack so fast

2.1 With the help of incremental memory frameworks

What is Turbo

Turborepo v1.10 released! Can the Turbopack be faster?

Turbo's logo

Turbo is a next-generation toolchain written in Rust for front-end development. It consists of 3 main parts:

  • Turbopack: Incremental Packer (successor to Webpack), maintained by Tobias Koppers, Maia Teegarden
  • Turborepo: Incremental build system, maintained by Jared Palmer (@jaredpalmer).
  • Turbo Engine: The underlying incremental computing and memory engine, maintained by Tobias Koppers, Maia Teegarden

Turbopack is based on Turbo

Turbopack's architecture draws lessons from tools like Turborepo and Google's Bazel, both of which focus on using caching to avoid doing the same work repeatedly.

Turborepo v1.10 released! Can the Turbopack be faster?

Turbopack is built on top of Turbo, which caches the results of any function in the program. When the program runs again, the functions do not rerun unless their inputs change. This fine-grained architectural tweaking allows programs to skip a lot of work at the function level.

Function-level caching

In programs driven by the Turbo engine, certain features can be marked as "to remember". When these functions are called, the Turbo engine remembers what they were called and the returned result, and then caches the result in memory.

For example, the following simplified example illustrates what each file looks like in the packager:

Turborepo v1.10 released! Can the Turbopack be faster?

First, both api.ts and sdk.ts called readFile. These files are then packaged using Turbopack, concatenated together to generate the final bundle. The results of all these function calls are saved in the cache for later use.

Assuming the packaging process runs on a development server, sdk.ts is saved natively. Turbopack receives a file system change event and knows it needs to recalculate readFile("sdk.ts"):

Turborepo v1.10 released! Can the Turbopack be faster?

Since the results of sdk.ts changed, Turbopack needed to be repackaged and then stitched again. Note that api.ts has not changed. Turbopack will read the result from the cache and pass it to concat. Therefore, repackaging api.ts files can be skipped to save time on repeated packaging.

Imagine a real packager with thousands of files to read, convert, execute. The above process will significantly improve packaging efficiency.

cache

The Turbo engine currently stores its cache in memory. This means that the cache lasts as long as the process running it, which is efficient for the development server. For example, running in Next v13:

next dev --turbo           

Turbopack will start the cache using the Turbo engine, and the cache will be cleared when the development server is stopped.

Turbopack plans to retain this caching capability in the future, such as to the file system, or to a remote cache like Turborepo, so as to enable Turbopack to run across machines.

2.2 Compile on demand

The Turbo engine helps deliver extremely fast updates on development servers, but there is another important metric to consider, startup time. The faster the development server is up and running, the faster it can be involved in R&D.

The solution to this problem is to do less work! Turbopack cleverly introduces an on-demand compilation strategy that compiles only the code needed to start, resulting in a significant increase in speed.

Page-level compilation

Previously, Next.js would compile the entire application, starting with Next.js 11, Turbopack only compiled the code on the requested page. However, this also creates some potential problems. For example, when a user navigates to a new route, Turbopack will package all client and server modules, dynamically imported modules, and referenced CSS and images. This means that if a large part of the page is hidden out of view, or hidden behind tabs, Turbopack will still compile it.

Request-level compilation

Turbopack is smart enough to compile only the requested code. This means that if a browser requests HTML, Turbopack compiles only the HTML, not everything referenced by the HTML.

If the browser requires some CSS, only the CSS will be compiled, not the referenced image. With request-level compilation, you can both reduce the number of requests and compile them using native speed, providing significant performance improvements.

3.Turbopack use

ECMAScript support

Turbopack uses SWC to package JavaScript and TypeScript files. Therefore, you need to match SWC support for ECMAScript versions. Anything WC supports, Turbopack will support. This means that all syntax in ESNext is supported by default.

Browserslist has become the industry standard for defining browsers that plan to target. To use it, you can add the browserslist field to package.json:

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

TypeScript support

Turbopack supports TypeScript out of the box. This means that you can import .ts files using Turbopack while supporting all the feature sets of TypeScript. You can also import .tsx files because of JSX support:

In TypeScript, you can use tsconfig.json's paths property to import files from a custom path.

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

Framework integration

The Turbopack program provides best-in-class support for multiple frameworks. Whether developers are using Svelte, React, Vue.js or other frameworks, they want to deliver a great experience on Turbopack.

Turbopack supports .jsx and .tsx files out of the box. Use SWC to compile JavaScript and TypeScript code for extremely fast compilation speeds. Similar to Next.js, Turbopack doesn't need to manually import React to use JSX:

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

CSS support

CSS packaging is handled by SWC using a Rust crate called swc_css. Turbopack has not yet documented swc_css separately, but it is integrated into Turbopack and supports several CSS features:

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

Turbopack handles postcss-nested syntax out of the box. This useful library allows developers to nest CSS declarations within each other:

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

Static resource import

Part of web packaging is dealing with all the asset types that the web supports, such as images, videos, JSON, fonts, and so on. Turbopack provides familiar tools that can be used right away.

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

environment variable

Turbopack parses and injects .env files out of the box.

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

The above will include all variations of these files:

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

4.Turborepo v1.10 New characteristics

On June 1, 2023, Turborepo v1.10 was released, which introduced several new features to improve the local development experience:

  • Code Generator: Use turbo Gen to generate source code, including creating a new workspace and copying an existing workspace.
  • Improved environment variable input: It's now easier to rely on environment variables with wildcard and .env support.
  • New environment mode: Developers can specify --env-mode=strict to control the environment variables included in the task hash.

You can quickly update it with the following command:

npx @tu rbo/codemod migrate           

4.1 Turborepo Code Generator

The Turborepo generator allows developers to add new code to the repository in a predictable and structured way. Previously, developers needed to copy the code themselves and manually add dependencies to the new workspace. With Generators, the process of creating a new workspace and integrating it into a repository is automated.

Developers can create a blank workspace from scratch, copy an existing workspace, or even create a custom builder for more control. Custom generators utilize Plop(opens in a new tab) configuration, a common template definition strategy used in the JavaScript ecosystem.

Custom builders can also be used to build more granular sets of code than workspaces, significantly speeding up the following tasks:

  • Add the new component to the UI library
  • Create a new unit test
  • Generate a new MDX blog post

Get started with the first generator by running the following command:

turbo gen           

4.2 Improved environment variable input

.env files are supported

.env files(Opens in a new tab) are typically used to load environment variables. This can cause problems when running with Turbo because these variables may not be visible and not easily included in the task's hash. When working locally, this issue can cause unexpected cache hits.

Turborepo now makes this easier by automatically supporting .env files. To ensure that Turborepo includes these variables in the hash, use the dotEnv key. For example, here is the configuration of the Next.js application:

{
  "$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"]
    }
  }
}           

Environment variable wildcards

Large applications may contain many environment variables in turbo.json, which can make the configuration difficult to manage and maintain.

Using wildcards, developers can now specify variable patterns to include in the hash.

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

Environment mode

The Turborepo environment mode is now out of experimental mode and is available for general use.

By default, when you call Turbo run with --env-mode=loose, all environment variables in the computer are available to each Turborepo task. This ensures maximum compatibility while accepting some risk that the task will implicitly access environment variables not specified in turbo.json.

In the new strict mode, when turbo is called with --env-mode=strict, only important system environment variables and environment variables enumerated in turbo.json will be available to the task.

5.The future of Turbopack

First, Turbopack will be used for the Next.js 13 development server. It will provide lightning-fast support for HMR and will natively support React server components, as well as TypeScript, JSX, CSS, and more.

Turbopack will also eventually support Next.js production builds on-premises and in the cloud, enabling Turbo's cache to be shared across the team using Vercel Remote Cache.

Turborepo v1.10 released! Can the Turbopack be faster?

Webpack users can also look forward to a gradual migration to a Rust-based future with Turbopack.

6. Summary of this article

This article mainly introduces you to the recently fried hot Turbopack. The article expands from many dimensions such as how fast Turbopack is, why Turbopack is so fast, and the future of Turbopack.

Due to space constraints, the article on more usage and features of Turbopack does not expand too much, if you are interested, you can continue reading on my homepage, and the references at the end of the article provide a lot of excellent documentation to study. Finally, welcome to like, comment, retweet, favorite, your support is my motivation to continue to create.

Resources

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