webpack 不是内部-什么

涡轮包的速度,比 Webpack 快 700 倍?

10 月 25 日,Next.js13 将发布。同时,Vercel还推出并开源了下一代包装工具:Turbopack。Turbopack 是一个针对 JavaScript 和 TypeScript 优化的增量打包工具,由 Webpack 创建者 Tobias Koppers 和 Next.js 团队在 Rust 中编译。Turbopack的推出吸引了很多开发者的关注,那么我们来看看Turbopack的优势吧!

涡轮包有多快?

Turbopack 建立在新的增量架构之上,可提供最快的开发体验。在小应用程序上,它的更新速度比 Vite 快 10 倍,比 Webpack 快 700 倍。对于较大的应用程序,它通常比 Vite 快 20 倍。

由于 Turbopack 仅打包开发所需的最少资源,因此启动时间特别快。在具有3000个模块的应用中,Turbopack需要1.8秒才能启动,而Vite需要11.4秒。

为什么涡轮包这么快?

涡轮包性能有两个很好的技巧:高度优化的机器代码和低级增量估计引擎,可以缓存到单个函数的级别。它的架构从Turborepo和Google的Bazel等工具中吸取了教训,这两种工具都专注于使用缓存来防止重复完成相同的工作。

涡轮增压发动机的工作原理

Turbopack 之所以如此之快,是因为它建立在可重用的 Rust 库之上,该库支持称为 Turbo 引擎的增量估计。这是它的工作原理。

内部审计工作是_webpack 不是内部_内部是什么意思

在Turbopack驱动的程序中,单个功能可以标记为“待记住”。当调用这些函数时,Turbo 引擎会记住它们的名称以及它们返回的内容。之后,它会将其保存在视频内存缓存中。下面是一个简化的示例:

我们首先在两个文件中调用 readFile,api.ts 和 sdk.ts。然后打包这些文件,将它们拼接在一起,最后得到完整的捆绑包。所有此类函数调用的结果都保存在缓存中供以后使用。

由于 sdk.ts 的结果已更改,因此需要再次打包,然后再次拼接。重要的是,api.ts没有改变。只需从缓存中读取其结果并将其传递给 concat。因此,通过不阅读和重新包装来节省时间。

Turbo 引擎目前将其缓存存储在视频内存中。这意味着缓存将与运行它的进程一样长,这对 Devserver 来说非常有用。将来,计划是将此缓存保存到文件系统或像 Turborepo 这样的远程缓存中。这意味着 Turbopack 可以记住跨运行和机器完成的工作。

这些技巧使 Turbopack 在估计应用程序的增量更新方面非常快,优化 Turbopack 以处理开发中的更新,这意味着 Devserver 将始终响应更改。

根据需要编译

Turbo 引擎有助于在 Devserver 上提供极快的更新,但还有另一个重要的指标需要考虑 - 启动时间。开发服务器开始运行的速度越快,它开始工作的速度就越快。有两种方法可以使该过程更快:更快地工作或减少工作。为了启动 Devserver,减少工作负载的方法是仅编译启动所需的代码。

(1) 页面级编译

下一个.js版本在 2-3 年前编译了整个应用程序,然后显示 Devserver。从 Next.js11 开始,仅编译请求页上的代码。这会更好,但并不完美。导航到 /users 时,将打包所有客户端和服务器模块、动态导出的模块以及引用的 CSS 和图像。这意味着,如果页面的很大一部分隐藏在视图中webpack 不是内部,或者隐藏在选项卡前面,它仍将被编译。

(2)诉状级汇编

Turbopack足够聪明,只能编译请求代码。这意味着,如果浏览器请求 HTML,它只会编译 HTML,而不是 HTML 引用的任何内容。如果浏览器需要CSS,它只会编译CSS,而不是它引用的图像,Turbopack甚至知道除非ChromeDevTools打开,否则不会编译源映射。通过请求方级别的编译,请求方的数量减少,性能显著提高。

为什么要基于 Rust 进行开发?

Turbopack 基于 Rust,每次 Next.js 团队将基于 JavaScript 的工具迁移到基于 Rust 的工具时,他们都会看到巨大的改进。接下来.js替换了 JavaScript 编译器 Babel,它将编译速率提高了 17 倍,并替换了 Terser,将压缩率提高了 6 倍,同时还减少了加载时间和带宽使用。

为什么选择涡轮增压?

Turbopack的创建是为了提高Next.js的速度,希望它能取代Webpack成为下一代Web打包工具。那么为什么不选择新一代的打包工具esbuild和SWC,而是选择创建自己的呢?

增量估计数

通常,有两种方法可以推进流程:减少工作量或并行工作。如果你想构建最快的包装工具,你需要用力驱动这两个杠杆。决定为分布式和增量行为创建一个可重用的 Turbo 构建引擎。Turbo 引擎的工作方式类似于函数调用的调度程序,允许在所有可用内核上并行调用函数。Turbo 引擎缓存它调度的所有功能的结果,这意味着它永远不必两次执行相同的工作。简而言之,它以最大速率完成最少的工作量。

其他工具采用不同的方法来“减少工作量”。例如,Vite 通过在开发模式下使用本机 ESM 来最大程度地减少工作量。在底层,Vite 使用 esbuild 来完成许多任务。esbuild是一个非常快速的打包程序,它不会强迫我们使用本机ESM。但是出于几个原因,决定不使用esbuild:

具有增量估计的 Rust 驱动的打包器在更大范围内比 esbuild 性能更好。

懒惰包装

Next.js的早期版本尝试在开发模式下打包整个Web应用程序,这不是最佳的。Next.js 的现代版本仅打包 Devserver 请求的页面。例如,如果你移动到localhost:3000,它将只打包pages/index.jsx和它导出的模块。

这些更“懒惰”的方式是快速开发服务器的关键。Esbuild没有“懒惰”包装的概念 - 它是全有或全无的。Turbopack 的开发模型根据请求创建应用程序导出和导入的最小图表,并且仅打包所需的最少代码。

此策略使 Turbopack 在首次启动 Devserver 时速度极快。只需估计呈现页面所需的代码,然后将其发送到单个块上的浏览器。在大规模应用中,这最终比本机ESM快得多。

这就是Turbopack进来的原因。

涡轮包的特点

构建 Web 应用程序的做法尤其多样化。仅在CSS中,就有SCSS,Less,CSSModule,PostCSS等。React、Vue 和 Svelte 等框架需要自定义设置。

在构建打包工具时,我们希望它开箱即用,无需配置,并且可以通过插件获得一些功能。目前,Turbopack 仍处于 alpha 阶段,在当前状态下,Turbopack 尚不可配置,因此插件尚不可用。

以下是 Turbopack 默认配置中开箱即用的功能,以及将来将通过插件配置的功能:

TurbopackvsVitevsWebpackTurbopackvsVite

Turbopack在两个关键指标上优于Vite。

(1) 开发服务器启动时间

Turbopack 的 Devserver 启动速度比 Vite 快得多。在包含 1000 个模块的应用程序中,Vite 需要 4.8 秒才能启动。涡轮包启动仅需 0.9 秒,速度快 5.5 倍。在小型应用中webpack 不是内部,这些差异将是一致的。在 30,000 个模块的应用中,Turbopack 的启动速度比 Vite 快 5.4 倍。

(2) 代码更新

修改文件时,它需要向浏览器显示更改。它的速度越快,反馈回路就越紧密,释放速度就越快。在包含 1,000 个模块的应用程序中,Turbopack 修改文件的速度比 Vite 快 5.8 倍。

TurbopackvsWebpack

Turbopack的增量架构在两个关键指标上超过了Webpack的速度。

(1) 开发服务器启动时间

Turbopack 的开发服务器启动速度比 Webpack 快得多。Next.js12 在引擎盖下使用 Webpack,它可以在 3.4 秒内在 1000 个模块的应用程序上启动构建服务器。涡轮增压组的启动速度提高了 0.9 秒至 3.9 倍。

(2) 代码更新

在开发服务器上执行的最常见操作是修改文件。修改文件时,它需要向浏览器显示更改。它的速度越快,反馈回路就越紧密,释放速度就越快。在包含 1000 个模块的应用程序中,Turbopack 对文件更改的反应速度比 Webpack 快 8.9 倍:

涡轮增压组的未来

到目前为止,Turbopack 在 Next.jsv13 中可用。未来,将发布独立的CLI,插件API,以及对Svelte和Vue等其他框架的支持。

Turbopack 将用于 Next.js13Devserver。它将为闪电般的HMR提供支持,并将原生支持React服务器端组件,以及TypeScript,JSX,CSS等。Webpack 用户还可以期待使用 Turbopack 进入基于 Rust 的未来增量迁移路径。

在Webpack创建者Tobias Koppers的带领下,Turbopack将成为Web的下一代打包工具。

参考:

¥9.9 抢980元“麦当劳+麦当劳”高级卡!

全年无限次使用!

文章目录

巴别塔(Tower of Babel),圣经中,为了阻止人们建造巴别塔(Tower of Babel),上帝让人类讲不同的语言,使人类无法互相交流,所以计划失败了,人类从此散乱。

JavaScript的babel就是将各个版本的JavaScript翻译成同一个版本或者为它们提供统一的运行环境。

babel相关包

7.0前后版本变化较大。 许多包的名称已更改。 为了统一名称,改为@babel开头。 例如,babel-core 更改为@babel/core。

图表

7.0之前 7.0之后备注

babel 核心

@babel/核心

babel-polyfill

@babel/polyfill

7.4 后已弃用,使用其他替代方案

babel 运行时

@babel/运行时

封装简介 备注

巴别塔装载机

webpack 加载代码的插件。

webpack 使用

@babel/核心

babel的核心是编译器,提供了转换API。

箭头函数、class句等转换语法

核心js

为低版本浏览器提供套接字的库。 分为core-js@2和@core-js@3

提供如:Promise全局变量实例方法Array.fill等。

再生器运行时

提供独立的函数运行时,es5环境下的es6生成器实现

包含再生器模块。 生成器函数(function*()、yeil)、async、await 函数。

@babel/polyfill

为低版本浏览器提供了socket库,本质上由core-js和regenerator-runtime组成。

7.4 弃用

@babel/助手

定义一些处理新句子关键词的辅助函数,并将必要的辅助函数作为模块导入到代码中

@babel/core 在处理时也会将辅助函数插入到代码中。 其处理方式是在每个文件中插入相应的辅助函数,而@babel/helpers则将辅助函数作为模块导入。 一个文件只需要调用这个模块即可。这个包基本上可以看成是Babel自己用的,我们自己不需要,而且好像也不让我们用

@babel/插件转换运行时

用于插入垫圈的插件

删除转换过程中@babel/core插入的函数,并替换为@babel/helpers中的函数,

@babel/运行时

包含@babel/helpers 和 regenerator-runtime

函数是这两个包的组合

@babel/runtime-corejs2

由 core-js@2、@babel/helpers 和 regenerator-runtime 组成

这三个包的功能组合

配置环境变量的位置在哪里_webpack 环境配置_配置环境变量是什么意思

@babel/runtime-corejs3

由 core-js@3、@babel/helpers 和 regenerator-runtime 组成

这三个包的功能组合

@babel/预设环境

插件设置预设配置,

此预设包含所有转换 ECMA 标准句型的插件,但不包括各个阶段的动作。

@babel/preset-stage-X

插件集,包括stage-0,1,2,3

V7.0之后弃用,这些插件的特性并不一定确定进入最终标准,因为有些人可能在生产环境中不受限制地使用它们并导致一些问题,所以babel官方弃用了它们。

查看每个提案处于哪个阶段

关于插件集@babel/preset-env:当我们执行语言转换为浏览器提供polyfills时,我们有几个选项,

import all,即引入所有的垫片,这样我们就可能不会使用到一些功能,而引入它们的垫片白白减少了很多无效代码。 文件中介绍了手动按需引用,比如当前文件使用了哪些。 比如我们的文件中使用Promise,我们会在文件中引入它webpack 环境配置,import '@babel/runtime-corejs3/core-js/promise',这样带来的问题是,如果多个文件使用它,每个文件必须介绍一下。 使用webpack打包,我们可以收集所有需要的垫片并导入到入口文件中,这样我们只需要导入一次即可。但是如果垫片很多,入口文件上就会出现一排排重复的类似代码

import "@babel/runtime-corejs3/core-js/promise";
import "@babel/runtime-corejs3/core-js/xxx";
import "@babel/runtime-corejs3/core-js/xxx";
import "@babel/runtime-corejs3/core-js/xxx";

为了处理此类代码,引入了一组插件。 插件parade根据配置手动转换句型并导入垫片,所以不需要在入口处放置大量声明。

在 webpack 中使用

安装相关包

npm 我 @babel/core @babel/preset-env babel-loader -D

配置网络包

// webpack.config.js
  module: {
    rules: [
      ...
        {
          test: /.js$/,
          exclude: /node_moduels/,
          use: {
            loader: "babel-loader"
          }
        }
      ],
  }
....

配置巴贝尔

webpack 环境配置_配置环境变量是什么意思_配置环境变量的位置在哪里

babel.config.json(官方推荐)。 .babelrc 是 .babelrc.json 的别名,“babel”属性是在 package.json 中创建的。 babelrc.json 使用了 webpack 的 loader 配置。 也可以使用js文件动态生成,只要文件导出导入符合babel配置即可,但是由于配置是动态生成的,所以配置只是在运行时获取,所以可能会影响缓存、IDE等功能手动完成。

// babel.config.js
module.exports = function (api) {
  api.cache(true);
  const presets = [ ... ];
  const plugins = [ ... ];
  return {
    presets,
    plugins
  };
}

babel.config.json、.babelrc 和 .babelrc.json 实际上只是一个内容相同的 JSON 文件。 而且package.json和loader中配置babel内容没有太大区别。

官方相关配置文档

根据自己的需要选择配置文件类型。 。 。 。 。

就目前的情况来说,首先选择.babelrc进行配置。

{
  "presets": [
    [
      "@babel/preset-env", // 也可以简写为 “@babel/env”
      {
        "targets": {
          "chrome": "68",
          "ie": "11"
        }
      }
    ]
  ]
}

关于目标

目标环境可以通过(推荐)来指定,很多项目都是用这个来确定目标环境的。

如果提供了.browserslistrc,则不能再指定目标,因为目标将覆盖.browserslistrc的配置。 如果指定目标并希望使用 .browserslistrc,则需要指定ignoreBrowserslistConfig 属性。

如何使用polyfill方法

babel-polyfill 已弃用,但 core-js 的工作原理类似。

全部导入import "core-js";,也可以根据自己的需要导入哪些。

安装babel相关包

npm i @babel/core @babel/preset-env babel-loader -D

配置文件

// .babelrc
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "chrome": "68",
          "ie": 10
        },
        "useBuiltIns": "entry",
        "corejs": 2
      }
    ]
  ]
}

参数介绍,

target:转换结果的目标,代码最终的执行环境,根据目标环境判断是否需要转换句子类型,并对这些句子类型进行转换,如箭头函数、类语法等。

useBuiltIns: false | “进入”| “用法”

webpack 环境配置_配置环境变量的位置在哪里_配置环境变量是什么意思

选项说明

假(默认)

此时corejs属性无效,不引入垫片,只有对目标属性进行判断后才转换对应的句型。

“入口”

在入口处自动引入垫片,并根据目标环境手动完成所有缺失的功能,无论我们的代码是否使用了相应的功能。

“用法”

在测量文件中所需使用的垫片的同时自动检查目标环境,并手动导入相应的垫片。 (官方推荐),目标环境不支持并且我们的代码不使用将无法完成。

核心js: 2| 3

corejs 属性仅在 useBuiltIns 设置为非 false 时才有效。

corejs中设置不同参数时注意安装对应的包。 如果useBuiltIns为“入口”,也需要在入口处自动导入。

corejs 选项需要额外安装的包注释

2(默认)

npm 我 core-js@2 -S

已停止添加

npm 我 core-js@3 -S

现在如果通过 npm i core-js -S 安装时不指定版本,则默认安装 3。

使用转换运行时

runtime-transform 和 core-js 类似,但是transform-runtime提供的沙箱式的washer单独生成一个运行沙箱,不会污染全局变量。一般在代码运行在我们不具备的环境中时使用控制,例如; 发布的 npm 包

安装相关包

npm 我 @babel/core @babel/preset-env @babel/plugin-transform-runtime babel-loader -D

配置环境变量是什么意思_webpack 环境配置_配置环境变量的位置在哪里

配置文件

// .babelrc
{
  "presets": [["@babel/preset-env"]],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "corejs": 3
      }
    ]
  ]
}

corejs设置不同的参数时,需要安装相应的包。

corejs选项描述了需要安装的附加包

假(默认值)

只辅助转换句型,如:箭头函数、类语法

npm 我@babel/runtime -S

在 false 的基础上减少对全局变量和静态方法的支持,如 Promise、Array.from

npm 我@babel/runtime-corejs2 -S

在2的基础上,减少支持[].includes()等实例方法

npm 我@babel/runtime-corejs3 -S

两种使用方式的区别在于是否污染地球环境。 不能同时使用。

在VUE中使用

VUE中推荐使用polyfill的形式。 因为使用transform-runtime时,它默认只会对我们的代码进行改造,而不会在node_module中的库中添加垫片。 如果你想让它转换 mode_module 中的代码,你需要使用 babel.config.js 来特殊配置,并且转换的结果可能无法使用。 node_module中的库可能有自己的垫片,但是如果要使用vuex的功能,浏览器控制台会报错,提示我们提供全局垫片,因为vuex没有自己的垫片。

我们自己开发网络程序。 目前最麻烦的就是如下配置,并且导入所有的polyfill,这样我们就不用担心漏掉什么了。 如果你之前有时间webpack 环境配置,如果你想优化包装,比如减少包装结果的体积,你可以再次优化。 开发初期,直接全部导入,不要用哪个再引入哪个,不然来回改起来就有点麻烦了。

安装 npm i @babel/core @babel/preset-env babel-loader -D 和 npm i core-js@3 -S 的软件包;

在文件入口index.js开头引入core-js

// index.js
import 'core-js/stable`

或者可以在webpack打包配置中减少core-js;

// webpack.config.js
...
module.exports = {
  ...
  entry: {
    main: ["core-js/stable", "./src/index.js"]
  },
  ...
}

巴贝尔配置文件

// .babelrc
{
  "presets": [
    [
      "@babel/preset-env",
      {
        // target 要根据自己的情况进行配置
        "targets": {
          "chrome": "68",
          "ie": 10
        },
        "useBuiltIns": "entry",
        "corejs": 3
      }
    ]
  ]
}