为什么ESbuilld打包构建比较快?

语言优势

大多数前端打包工具是基于javascript实现的,而Esbuild选择使用Go语言编写。
在CPU密集的场景下,Go更加具有性能优势。
因为javascript本质上是一门解释型的语言,每次执行的时候都会先将源码翻译成机器码,一边调度执行;而Go是一种编译型语言,在编译阶段就已经将源码转移成机器码,启动的时候只需要直接执行这些机器码即可。也就意味着,Go语言编写的程序比js少了一个动态解释的过程。

多线程优势

Go天生具有多线程运行能力,而javascript本质上是一门单线程语言,直到引入WebWoker才可能在浏览器/node中实现多线程。
Rollup/Webpack并没有使用WebWoker提供的多线程能力,而ESbuild的实现尽可能的使用各个CPU核,特别是打包过程的解析/代码生成阶段已经实现完全并行的处理。
esbuild的模块打包器
并且Go语言多个线程之间还能共享相同的内存空间,而javascript的每个线程都有自己的内存堆,这意味着Go中多个处理单元,例如解释资源A的线程,可以直接读取资源B线程的运行结果,而js中相同的操作需要调用通讯接口woker.postMessage在线程间复制数据。

节制

ESbuild仅仅提供了构建一个现代Web应用所需的最小功能的集合

  • 支持 js、ts、jsx、css、json、文本、图片等资源
  • 增量更新
  • Sourcemap
  • 开发服务器支持
  • 代码压缩
  • Code split
  • Tree shaking
  • 插件支持
    并且有很多功能官网明确声明没有计划实现支持。

定制

在之前的打包工具中,我们使用了很多第三方插件来解决各种工程需求,比如:

  • 使用babel实现ES版本转译
  • 使用ESlint实现代码检查
  • 使用TSC实现ts代码转译
  • 使用less/stylus/sass等css预处理工具
    我们已经完全习惯了这种方式,但是esBuild使用了另一种做法,直接完全重写整套编译流程所用的所有的工具,也就是说需要重写js/ts/jsx/json等资源文件的加载/解析/链接/代码生成逻辑。
    开发成本很高,但是他可以以性能为最高级定制编译的各个阶段,比如说:
  • 重写ts转译工具,完全抛弃ts类型检查,只做代码转换
  • 大多数打包工具把词法分析、语法分析、符号声明等步骤拆解为多个高内聚低耦合的单元,可读性和可维护性比较高,但是esbuild坚持性能第一,将多个处理算法混合在一起降低编译过程数据流转所带来的性能损耗。
    结构一致性
    我们提到esbuilld选择重写js/ts/jsx/css等语言在内的转译工具,所以他比较能保持编译步骤之间的结构一致性,比如在Webpack中使用babel-loader处理javascript代码的时候,可能需要经过多次数据转换:
  • Webpack读入源码,此时是字符串形式
  • Babel解析源码,转换为AST形式
  • Babel将源码AST转换为低版本的AST,Babel将低版本AST generator为低版本源码,字符串形式
  • Webpack解析低版本源码
  • Webpack将多个模块打包为最终产物
    源码需要经历string=>AST=>AST=>string=>AST=>string,在字符串与AST之间反复横跳。
    而Esbuild重写大多数转译工具之后,能够在过个编译阶段共用相似的AST(到底是咋共用的,有待研究),尽可能减少字符串到AST的结构转换,提升内存使用效率。

你可能感兴趣的:(javascript,前端)