写点什么

构建系列之新一代利器 Esbuild(下)

作者:江湖修行
  • 2023-06-28
    北京
  • 本文字数:2049 字

    阅读完需:约 7 分钟

构建系列之新一代利器Esbuild(下)

前言

本篇文章接上文,通过尝试使用 esbuild 的能力和业界的落地方案作为切入点继续深入 esbuild 的原理。

尝试 Esbuild

ESBuild 在 API 层面上非常简洁, 主要的 API 只有两个: Transform 和 Build, 这两个 API 可以通过 CLI, JavaScript, Go 的方式调用。


Transform 主要用于对源代码的转换, 接受的输入是字符串, 输出的是转换后的代码


# 用CLI方式调用, 将ts代码转化为js代码echo 'let x: number = 1' | esbuild --loader=ts => let x = 1;
复制代码


Build 主要用于构建, 接受的输入是单文件或文件集合


// 用JS模式调用build方法require('esbuild').buildSync({  entryPoints: ['in.js'],  bundle: true,  outfile: 'out.js',})
复制代码


ESBuild 的内容类型(Content Type)包括了 ES 在打包时可以解析的文件类型, 这一点和 Webpack 的 loader 概念类似, 下面的例子是在打包时用 JSX Loader 解析 JS 文件。

require('esbuild').buildSync({  entryPoints: ['app.js'],  bundle: true,  loader: {    '.js': 'jsx'  },  outfile: 'out.js',})
复制代码


借助 esbuild 的能力:如果你觉得目前完全使用 ESBuild 还不成熟, 也可以在 Webpack 体系中使用 ESBuild 的 loader 来替代 babel 用于进行代码转换, 除此之外, esbuild-loader[5]还可以用于 JS & CSS 的代码最小化.


const { ESBuildMinifyPlugin } = require('esbuild-loader')

module.exports = { rules: [{ test: /.js$/, // 使用esbuild作为js/ts/jsx/tsx loader loader: 'esbuild-loader', options: { loader: 'jsx', target: 'es2015' } }, ], // 或者使用esbuild-loader作为JS压缩工具 optimization: { minimizer: [ new ESBuildMinifyPlugin({ target: 'es2015' }) ] }}
复制代码


注意:前面说过 Esbuild 转换的代码是无法降级到 ES5 及以下


使用 Esbuild 的虚拟模块,可以完成很丰富的功能,比如模块名当做一个函数来进行编译,甚至可以在编译阶段实现函数递归的过程。比如这个 Esbuild 插件:


{  name: 'fibo',  setup(build) {    build.onResolve({      filter: /^fib(\d+)/    }, args = > {      return {        path: args.path,        namespace: 'fib'      }    }) build.onLoad({      filter: /^fib(\d+)/,      namespace: 'fib'    }, args = > {      const match = /^fib((\d+))/.exec(args.path);      n = Number(match[1]);      console.log(n);      let contents = n < 2 ? `export      default $ {        n + 1      }` : `import n1 from 'fib(${n - 1})'      import n2 from 'fib(${n - 2})'      export      default n1 + n2`      return {        contents      }    })  }}
复制代码


引入这个插件,可以解析如下的 import 语句:


import fib5 from 'fib(5)'  console.log(fib5)  // 13
复制代码


所有的模块都是虚拟模块,在真实文件系统中并不存在,另外,还能借助虚拟模块来进行 URL Import,支持如下的 import 代码:


import React from 'https://esm.sh/react@17'
复制代码

业界落地方案

1.代码压缩工具

Esbuild 有非常优秀的代码压缩能力,有着比传统的压缩工具一个量级以上的性能差距。Vite 在 2.6 版本也官宣在生产环境中直接使用 Esbuild 来压缩 JS 和 CSS 代码。



2.Bundler 库

Vite 中在开发阶段使用 Esbuild 来进行依赖的预打包,将所有用到的第三方依赖转成 ESM 格式 Bundle 产物,并且未来有用到生产环境的打算。


同时业界也有一些平台基于纯 Esbuild 来做线上 cjs -> esm 的 CDN 服务,比如 esm.sh :




点击并拖拽以移动


编辑

3.小程序编译

对于小程序的场景,也可以使用 Esbuild 来代替 Webpack,大大提升编译速度,对于 AST 的转换则通过 Esbuild 插件嵌入 SWC 来实现,实现快速编译。

4.Web 构建

Web 场景就显得比较复杂了,对于兼容性和周边工具生态的要求比较高,比如低浏览器语法降级、CSS 预编译器、HMR 等等,如果要用纯 Esbuild 来做,还需要补充很多能力。


已有大佬基于 Esbuild 实现了一套 Web 开发脚手架 ewas,已经在 Github 开源,仓库地址: https://github.com/sanyuan0704/ewas


如今 Remix 1.0 正式发布,底层使用 Esbuild 构建,带来了极致的性能体验,成为 Next.js 强有力的竞争对手。


但总体来说,目前 Esbuild 对于真实的 Web 场景还有很多能力不支持,还有一些硬伤,包括语法不支持降级到 ES5,拆包不灵活、不支持 HMR,对于真正能作为 Webpack 一样的构建工具来讲还有很长的路要走。

总结

Esbuild 的性能是其一大利器,这对于很多开发者和框架都会是一个优先考虑的因素,我们夜看到在整个生态系统中其也在慢慢的进行渗透,但就目前而言还不能完全替代 Webpack 等主流工具,毕竟整体生态环境有待完善。


建议如果想尝试 esbuild 的能力,但已有的基础设施稳定并且替换成本较大时, 可以尝试渐进式的利用新工具(loader)或者 Vite 这种基于 ESBuild 二次封装的构建工具。


欢迎各位 coder关注微信公众号,文章首发,欢迎转发交流。

发布于: 刚刚阅读数: 4
用户头像

江湖修行

关注

还未添加个人签名 2021-12-05 加入

还未添加个人简介

评论

发布
暂无评论
构建系列之新一代利器Esbuild(下)_前端_江湖修行_InfoQ写作社区