阅读 199

webpack 或 esbuild:为什么不是两者兼而有之?

【翻译于LogRocket网站上John Reilly所写的webpack or esbuild: Why not both?】 使用像esbuild的工具可以更快地进行构建。但是,如果您正投资于webpack,但是仍想利用更快的构建,那么有一种方法。

在本教程中,我们将向您展示如何将 esbuild 与 webpack 与esbuild-loader一起使用。

webpack-esbuild-why-not-both.jpeg

Web 开发的世界正在发展

向那些遭受 JavaScript 疲劳的人道歉,Web 开发的世界再次发展。长期以来,通过某种基于 Node.js 的构建工具(如 webpack 或 rollup.js)运行 JavaScript 和 TypeScript 一直是常见做法。这些工具是用它们编译成的相同语言编写的——即 JavaScript 或 TypeScript。

博客上的新成员是esbuild、Vite和swc等工具。它们与它们的前辈之间的显着区别在于,新式工具是用 Go 和 Rust 等语言编写的。Go 和 Rust 的性能比 JavaScript 好得多。这转化为显着更快的构建。

这些新工具具有变革性,可能代表了 Web 构建工具的未来。从长远来看,esbuild、Vite和朋友之类的工具很可能会取代当前的标准构建工具——webpacks、rollups 等。

然而,这是长期的。有很多项目已经在他们当前的构建工具上投入了大量资金——主要是 webpack。迁移到新的构建工具并非易事。新项目可能会从 Vite 开始,但现有项目不太可能被移植。webpack 如此受欢迎是有原因的;它确实可以很好地完成很多事情。它经过大型项目的实战测试,非常成熟,并且可以处理广泛的用例。

因此,如果您的团队想要更快的构建但没有时间进行大规模迁移,您有什么可以做的吗?是的,有一个中间地带需要探索。

有一个相对较新的项目,名为esbuild-loader。esbuild-loader由hiroki osame开发,是一个建立在 esbuild 之上的 webpack 加载器。它允许用户通过它交换ts-loader babel-loader,这大大提高了构建速度。

在这里声明一个兴趣以进行全面披露,我是ts-loader的主要维护者,这是一个流行的 TypeScript 加载器,通常与 webpack 一起使用。但是,我强烈认为这里重要的是开发人员的生产力。作为Node.js为基础的项目,ts-loaderbabel-loader将永远无法与esbuild-loader在相同方式上竞争。作为一种语言,Go 真的,呃,可行!

虽然 esbuild 可能不适用于所有用例,但它适用于大多数任务。因此,esbuild-loader代表了一个中间立场——也是一种在不告别 webpack 的情况下获得 esbuild 提供的更高构建速度的早期方法。本演练将探索在您的 webpack 设置中使用esbuild-loader

将现有项目迁移到 esbuild

使用无论babel-loader或是ts-loader都可以非常直接的迁移一个项目到esbuild-loader。首先,安装依赖:

npm i -D esbuild-loader复制代码

如果你正用babel-loader, 根据下文修改您的webpack.config.js

module.exports = {
    module: {
    rules: [
-       {
-         test: /\.js$/,
-         use: 'babel-loader',
-       },
+       {
+         test: /\.js$/,
+         loader: 'esbuild-loader',
+         options: {
+           loader: 'jsx',  // Remove this if you're not using JSX
+           target: 'es2015'  // Syntax to compile to (see options below for possible values)
+         }
+       },复制代码

创建基线应用程序

让我们在练习中看看esbuild-loader是如何工作的。我们正用Create React App创建一个新的 React 应用:

npx create-react-app my-app --template typescript复制代码

这将在my-app目录中使用 TypeScript 构建一个新的 React 应用程序。值得一提的是 Create React App在幕后使用了babel-loader

CRA 还使用Fork TS Checker Webpack 插件来提供 TypeScript 类型检查。这非常有用,因为 esbuild 只是进行转译而不是设计来提供类型检查支持。所以幸运的是我们仍然有那个插件。否则,我们将失去类型检查。

现在您理解了迁移esbuild的优势,我们先需要一个基线来理解用babel-loader会有怎样的表现。我们运行time npm run build去执行一个我们简单app的构建。

webpack-esbuild-completed-build-create-react-app.png

我们的完整构建、TypeScript 类型检查、转译、缩小等全部耗时 22.08 秒。现在的问题是,如果我们将 esbuild 放入组合中会发生什么?

介绍 esbuild-loader

自定义 Create React App 构建的一种方法是运行npm run eject, 然后自定义 CRA 输出的代码。这样做很好,但这意味着您无法跟上 CRA 的发展。另一种方法是使用诸如Create React App Configuration Override (CRACO) 之类的工具,它允许您就地调整配置。CRACO 将自己描述为“为create-react-app的一个简单易懂的配置层。”

让我们添加esbuild-loader和CRACO的依赖

npm install @craco/craco esbuild-loader --save-dev复制代码

接着我们将交换我们各种scripts在我们的package.json以便使用CRACO

"start": "craco start",
"build": "craco build",
"test": "craco test",复制代码

我们的应用使用CRACO,但是我们还未配置他。所以我们正添加一个craco.config.js的文件到我们项目的根目录上。这是我们为esbuild-loader而换出babel-loader:

`const { addAfterLoader, removeLoaders, loaderByName, getLoaders, throwUnexpectedConfigError } = require('@craco/craco');
const { ESBuildMinifyPlugin } = require('esbuild-loader');

const throwError = (message) =>
    throwUnexpectedConfigError({
        packageName: 'craco',
        githubRepo: 'gsoft-inc/craco',
        message,
        githubIssueQuery: 'webpack',
    });

module.exports = {
    webpack: {
        configure: (webpackConfig, { paths }) => {
            const { hasFoundAny, matches } = getLoaders(webpackConfig, loaderByName('babel-loader'));
            if (!hasFoundAny) throwError('failed to find babel-loader');

            console.log('removing babel-loader');
            const { hasRemovedAny, removedCount } = removeLoaders(webpackConfig, loaderByName('babel-loader'));
            if (!hasRemovedAny) throwError('no babel-loader to remove');
            if (removedCount !== 2) throwError('had expected to remove 2 babel loader instances');

            console.log('adding esbuild-loader');

            const tsLoader = {
                test: /\.(js|mjs|jsx|ts|tsx)$/,
                include: paths.appSrc,
                loader: require.resolve('esbuild-loader'),
                options: { 
                loader: 'tsx',
                target: 'es2015'
                },
            };

            const { isAdded: tsLoaderIsAdded } = addAfterLoader(webpackConfig, loaderByName('url-loader'), tsLoader);
            if (!tsLoaderIsAdded) throwError('failed to add esbuild-loader');
            console.log('added esbuild-loader');

            console.log('adding non-application JS babel-loader back');
            const { isAdded: babelLoaderIsAdded } = addAfterLoader(
                webpackConfig,
                loaderByName('esbuild-loader'),
                matches[1].loader // babel-loader
            );
            if (!babelLoaderIsAdded) throwError('failed to add back babel-loader for non-application JS');
            console.log('added non-application JS babel-loader back');

            console.log('replacing TerserPlugin with ESBuildMinifyPlugin');
            webpackConfig.optimization.minimizer = [
                new ESBuildMinifyPlugin({
                    target: 'es2015' 
                })
            ];

            return webpackConfig;
        },
    },
};复制代码

那么这里发生了什么?该脚本在默认的 Create React App 配置中查找babel-loader的用法。将有两种:一种用于 TypeScript/JavaScript 应用程序代码(我们想替换它),一种用于非应用程序 JavaScript 代码。目前尚不清楚存在或可能存在哪些非应用程序 JavaScript 代码,因此我们将其保留;这可能很重要。我们真正关心的代码是应用程序代码。

您不能使用CRACO删除单个加载程序,因此,我们将删除两者并重新添加非应用程序 JavaScript babel-loader。我们还将添加esbuild-loader{ loader: 'tsx', target: 'es2015' }选项设置,以确保我们能处理JSX / TSX。

最后,我们也将使用Terser替换为esbuild的 JavaScript 缩小。

巨大的性能提升

我们的迁移已完成。下次我们构建时,我们将在没有弹出的情况下用esbuild-loader运行 Create React App 。再一次,我们将运行time npm run build以执行我们的简单应用程序的构建并确定需要多长时间:

webpack-esbuild-completed-build-create-react-app-esbuild.png

我们的完整构建、TypeScript 类型检查、转译、缩小等全部耗时 13.85 秒。通过迁移到esbuild-loader,我们将整体编译时间减少了大约三分之一。这是一个巨大的进步!

随着代码库的扩展和应用程序的增长,编译时间可能会激增。使用esbuild-loader,您应该从构建时间中获得持续的好处。


作者:DisonTangor
链接:https://juejin.cn/post/7023240232522743844


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐