当前位置:网站首页>Esbuild & SWC: a new generation of construction tools
Esbuild & SWC: a new generation of construction tools
2022-07-06 03:19:00 【phial03】
First , ESBuild & swc What is it? ?
ESBuild Is based on Go Language development JavaScript Bundler, from Figma front CTO Evan Wallace Development , And was also Vite Used for dependency resolution and analysis of development environment Transform.
SWC Is based on Rust Of JavaScript Compiler( Its ecology also includes packaging tools spack), At present for Next.JS/Parcel/Deno And other well-known projects in the front-end circle .
Why focus on these two tools ?
You may have encountered in your daily work , The construction time of the project increases gradually with the volume and complexity of the project , Sometimes it takes a few minutes to edit a project locally ( here @Webpack)
This is ESBuild The official website packages it 10 Share three.js Velocity contrast
SWC It claims to be better than Babel fast 20 times ( In the case of quad core, it can be fast 70 times )
that ESBuild & SWC It's really so fast ? Or the developer's own words ? Let's test it by experiment , First look at ESBuild
Let's start with a very simple piece of code
import * as React from 'react' import * as ReactServer from 'react-dom/server' const Greet = () => <h1>Hello, world!</h1> console.log(ReactServer.renderToString(<Greet />))
Then let's go through Webpack & ESBuild Build it
use ESBuild Pack it up
# compile > build-esb > esbuild ./src/app.jsx --bundle --outfile=out_esb.js --minify # Build product size and build time out_esb.js 27.4kb Done in 13ms # Run the product node out_esb.js <h1 data-reactroot="">Hello, world!</h1>
use Webpack Pack it up
# compile > build-wp > webpack --mode=production # Build products asset out_webpack.js 25.9 KiB [compared for emit] [minimized] (name: main) 1 related asset modules by path ./node_modules/react/ 8.5 KiB ./node_modules/react/index.js 189 bytes [built] [code generated] ./node_modules/react/cjs/react.production.min.js 8.32 KiB [built] [code generated] modules by path ./node_modules/react-dom/ 28.2 KiB ./node_modules/react-dom/server.browser.js 227 bytes [built] [code generated] ./node_modules/react-dom/cjs/react-dom-server.browser.production.min.js 28 KiB [built] [code generated] ./src/app.jsx 254 bytes [built] [code generated] ./node_modules/object-assign/index.js 2.17 KiB [built] [code generated] # Build time webpack 5.72.0 compiled successfully in 1680 ms npm run build-wp 2.79s user 0.61s system 84% cpu 4.033 total # function node out_webpack.js <h1 data-reactroot="">Hello, world!</h1>
Look again. swc Compilation efficiency
It's another simple ES6 Code
// Some variables declare const PI = 3.1415; let x = 1; // spread let [foo, [[bar], baz]] = [1, [[2], 3]]; const node = { loc: { start: { line: 1, column: 5 } } }; let { loc, loc: { start }, loc: { start: { line }} } = node; // arrow function var sum = (num1, num2) => { return num1 + num2; } // set const s = new Set(); [2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x)); // class class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } }
First use Babel Translate
yarn compile-babel yarn run v1.16.0 warning package.json: No license field $ babel src/es6.js -o es6_babel.js Done in 2.38s.
Reuse swc Translate
yarn compile-swc yarn run v1.16.0 warning package.json: No license field $ swc src/es6.js -o es6_swc.js Successfully compiled 1 file with swc. Done in 0.63s.
The product comparison of the two
// es6_babel "use strict"; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } var PI = 3.1415; var x = 1; var foo = 1, bar = 2, baz = 3; var node = { loc: { start: { line: 1, column: 5 } } }; var loc = node.loc, start = node.loc.start, line = node.loc.start.line; var sum = function sum(num1, num2) { return num1 + num2; }; var s = new Set(); [2, 3, 5, 4, 5, 2, 2].forEach(function (x) { return s.add(x); }); var Point = /*#__PURE__*/function () { function Point(x, y) { _classCallCheck(this, Point); this.x = x; this.y = y; } _createClass(Point, [{ key: "toString", value: function toString() { return '(' + this.x + ', ' + this.y + ')'; } }]); return Point; }();
// es6 swc
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for(var i = 0; i < props.length; i++){
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
var PI = 3.1415;
var x = 1;
var foo = 1, bar = 2, baz = 3;
var node = {
loc: {
start: {
line: 1,
column: 5
}
}
};
var loc = node.loc, start = node.loc.start, _loc = node.loc, line = _loc.start.line;
var sum = function(num1, num2) {
return num1 + num2;
};
var s = new Set();
[2,3,5,4, 5,2, 2].forEach(function(x1) {
return s.add(x1);
});
var Point = /*#__PURE__*/ function() {
"use strict";
function Point(x2, y) {
_classCallCheck(this, Point);
this.x = x2;
this.y = y;
}
_createClass(Point, [
{
key: "toString",
value: function toString() {
return "(" + this.x + ", " + this.y + ")";
}
}
]);
return Point;
}();
//# sourceMappingURL=es6_swc.js.map
It can be seen from the above data that
- In the comparison of packaged code , ESBuild The speed of (20ms) Far faster than Webpack(1680ms)
- In the comparison of compiled code , swc Also on the babel It has obvious performance advantages (0.63s vs 2.38s).
- What needs to be added is , The code used as an example is very simple , And in the comparison, all construction optimization strategies of various construction tools are not fully used , Just compare the speed of several tools under the most basic configuration , This and the list of tools benchmark The data will be different , And the construction speed is also related to the hardware performance / Runtime state .
ESBuild/swc So fast ? That's OK Webpack/Babel Throw it away ? Don't worry , current ESBuild and Swc It may not completely replace Webpack. But through this sharing, we may have a more comprehensive understanding of them , You can also explore future opportunities to use these new generation front-end tools at work
ESBuild/swc Positioning in front-end Ecology
- In today's front-end world , New tools emerge in endlessly , Sometimes there are so many different tools that I can't tell what their functions are for a while , So let's study it first ESBuild/swc Role in today's front-end engineering system .
- From the screenshot above, select several front-end engineering tools that we contact most frequently in our daily life :
- Task Runner Task runner : Developers set up scripts for the build tool to complete the development 、 structure 、 A series of tasks in deployment , What we usually use is npm/yarn The script function of ; Earlier , More popular Gulp/Grunt Such a tool
- Package Manager Package manager : This is no stranger to everyone , npm/Yarn/pnmp Help developers download and manage dependencies , It is essential for current front-end development .
- Compiler/Transpiler compiler : In the market, many browsers only support ES5 In grammar , Babel In this way Comipler It is essential in front-end development ; If you use TypeScript Words , It also needs to pass tsc perhaps ts-loader Compile .
- Bundler Packaging tools : Starting from the entrance set by the developer , Analyze module dependencies , Load and package various resources into 1 Tools for one or more files .
- Loader: Because the front-end project contains various file types and data , It needs to be transformed into JS Modules can be used and built for packaging tools . JS Of Compiler And other types of files Loader May be collectively referred to as Transfomer.
- Plugin: You can further customize the construction process , Transform the module ( Like compression JS Of Terser)
- There are also some front-end building tools that are encapsulated or add additional functions based on general building tools , such as CRA/Jupiter/Vite/Umi
- ESBuild The location is Bundler, But it's also Compiler( Yes Transform The power of code )
- swc Call itself Compiler + Bundler, But at the moment spack It's not very easy to use
ESBuild/SWC Why so fast ?
- Think about it , Go & Rust These two languages and JavaScript What's the difference between ?
ESBuild The implementation of the ( Reference resources ESBuild FAQ)
from Go Implement and compile into local code : Most of the Bundler It's all by JavaScript Realized , however CLI Apply to JIT Compiling languages are the worst performing . Each run Bundler When , JS Virtual machines are parsed from the perspective of running code for the first time Bundler( such as Webpack) Code for , No optimization information . When ESBuild In parsing JavaScript When , Node Still parsing Bundler Of JS Code
Heavy use of parallel computing : Go The design of the language itself attaches great importance to parallel computing , therefore ESBuild This will be exploited . There are three main links in the construction : analysis (Parsing), link (Linking) And code generation (Code generation), In the process of parsing and code generation, multi-core parallel computing will be used as much as possible
ESBuild Everything in the code is implemented from zero : Avoid performance problems caused by third-party libraries by implementing all logic by yourself , Unified data structure can reduce the cost of data conversion , And you can change the architecture as needed , Of course, the biggest disadvantage is that the workload is doubled .
- It's amazing SpaceX This company , A large number of parts are produced in-house , Effectively reduce production costs
- It's amazing SpaceX This company , A large number of parts are produced in-house , Effectively reduce production costs
Efficient use of memory : ESBuild In the implementation, try to reduce the transmission and conversion of data , ESBuild Minimize the impact on the whole AST The transfer , And reuse as much as possible AST data , Other Bundler Data formats may be converted back and forth at different stages of compilation (string -> TS -> JS -> older JS -> string…). In terms of memory storage efficiency Go Is better than JavaScript More efficient .
swc The implementation of the
- swc Our official documents and websites are not correct swc A more specific explanation of the internal implementation , According to its Blog Some analysis in , babel The main reason for the slowness is its single threaded nature
A summary
- from ESBuild and swc In the official resources of , The common point is to make good use of Parallel computing .JS Because the goal at the beginning of the design is to serve the browser scene well , So single thread & Event driven is not suitable for CPU Intensive Computing , and ESBuild/Rust It is also on this point that we are based on Node Our build tools have a systematic speed advantage .
How to use ESBuild/swc Efficiency improvement ?
- Now we know that ESBuild/Rust What does it do , And what are the characteristics , How can we use... In our work ESBuild/swc To improve our development experience ?
Use ESBuild
ESBuild stay API Very concise on the level , The main API Only two. : Transform and Build, these two items. API Can pass CLI, JavaScript, Go Method call
Transform Mainly used for the conversion of source code , The input accepted is a string , The output is the converted code
# use CLI Way to call , take ts Code to js Code echo 'let x: number = 1' | esbuild --loader=ts => let x = 1;
Build Mainly for building , The input accepted is one or more files
// use JS Mode call build Method require('esbuild').buildSync({ entryPoints: ['in.js'], bundle: true, outfile: 'out.js', })
ESBuild The type of content (Content Type) It includes ES File types that can be resolved during packaging , This and Webpack Of loader Similar concepts , The following example is used when packaging JSX Loader analysis JS file .
require('esbuild').buildSync({
entryPoints: ['app.js'],
bundle: true,
loader: {
'.js': 'jsx' },
outfile: 'out.js',
})
- ESBuild It also includes plug-in system , During the construction process (Transform API The plug-in cannot be used ) Change your build process through plug-ins
// Plug in demonstration from the official website
let envPlugin = {
name: 'env',
setup(build) {
// Intercept import paths called "env" so esbuild doesn't attempt
// to map them to a file system location. Tag them with the "env-ns"
// namespace to reserve them for this plugin.
build.onResolve({
filter: /^env$/ }, args => ({
path: args.path,
namespace: 'env-ns',
}))
// Load paths tagged with the "env-ns" namespace and behave as if
// they point to a JSON file containing the environment variables.
build.onLoad({
filter: /.*/, namespace: 'env-ns' }, () => ({
contents: JSON.stringify(process.env),
loader: 'json',
}))
},
}
// The use of plug-in
require('esbuild').build({
entryPoints: ['app.js'],
bundle: true,
outfile: 'out.js',
plugins: [envPlugin],
}).catch(() => process.exit(1))
Use in other tools ESBuild
If you think it's completely used now ESBuild Not yet mature , It can also be in Webpack Used in the system ESBuild Of loader To replace babel For code conversion , besides ,
esbuild-loader
It can also be used for JS & CSS Minimize your code .
const { ESBuildMinifyPlugin } = require('esbuild-loader') module.exports = { rules: [ { test: /.js$/, // Use esbuild As js/ts/jsx/tsx loader loader: 'esbuild-loader', options: { loader: 'jsx', target: 'es2015' } }, ], // Or use esbuild-loader As JS Compression tool optimization: { minimizer: [ new ESBuildMinifyPlugin({ target: 'es2015' }) ] } }
Be careful
- ESBuild Can't turn ES5 Code and some other Syntax , Please refer to esbuild.github.io/content-typ…
Use Vite
- Want to say 2021 New tools with high attention in the front-end circle in , Vite It can be said to be among the best , that Vite and ESBuild/swc What does it matter ?
- Vite The core idea of is to use ESM+ Compile language tools (ESBuild) Speed up local operations
- Vite In the development environment ESBuild Pre build , In the production environment Rollup pack , It is also possible to use ESBuild Build the production environment .
- Support ES5 Need to introduce plug-ins github.com/vitejs/vite…
Use swc
Comilation
have access to swc Command line tools (swc/cli) coordination The configuration file Compiling Files
# Transpile one file and emit to stdout npx swc ./file.js # Transpile one file and emit to `output.js` npx swc ./file.js -o output.js # Transpile and write to /output dir npx swc ./my-dir -d output
swc The core of swc/core There are three main types API
- Transform: Code conversion API, Enter the source code => Output the converted code
- Parse: Analyze the source code , Output AST
- Minify: Minimize code
swc Also launched swc/wasm modular , Allows users to use... In a browser environment wasm Code conversion
If you want to Webpack Use under the system swc( replace babel), You can also use swc-loader
Bundle
- ️swc It also supports packaging , But at present, the function is not very complete , And there are many in use Bug. The author is currently trying to use spack Pack a simple React The application is not yet successful , You can't use it out of the box
- at present swc Of Bundle The tool is called spack, Later, it will be renamed swcpack.
- Packaging can be done through spack.config.js File
A little summary and thinking
Full text summary
ESBuild/swc It is a new generation of front-end tool written in compiled language , Yes JS The build tool written has a system level speed advantage
ESBuild Can be used to compile JS Code and module packaging , swc It is claimed that it can support both, but its packaging tool is still in the early stage of development
At present, these two tools cannot completely replace Webpack And other mainstream tools have developed a huge ecosystem in recent years
When the existing infrastructure is stable and the replacement cost is high , You can try to use new tools incrementally (loader) perhaps Vite This is based on ESBuild Construction tools for secondary packaging
Extended thinking
Continue to pay attention to the new development of front-end Ecology , Make good use of the open source community to improve R & D efficiency and experience .
While using new tools , Understand or participate in the technical principles behind it , Go It can be used as a server language , Rust It can be used as a system programming language , Learning a new language can open up a new Xintiandi , Beauty is not true ?
Reference material :
边栏推荐
- 【Rust 笔记】18-宏
- 出现Permission denied的解决办法(750权限谨慎使用)
- Handwriting database client
- svg拖动点裁剪图片js特效
- JS regular filtering and adding image prefixes in rich text
- Pytorch load data
- [kubernetes series] learn the exposed application of kubernetes service security
- Deno介绍
- jsscript
- Data and Introspection__ dict__ Attributes and__ slots__ attribute
猜你喜欢
Mysqldump data backup
【指针训练——八道题】
如何做好功能测试
The real machine cannot access the shooting range of the virtual machine, and the real machine cannot Ping the virtual machine
[kubernetes series] learn the exposed application of kubernetes service security
Analyze menu analysis
JS regular filtering and adding image prefixes in rich text
电机控制反Park变换和反Clarke变换公式推导
ERA5再分析资料下载攻略
canvas切积木小游戏代码
随机推荐
指针笔试题~走近大厂
canvas切积木小游戏代码
Microsoft Research, UIUC & Google research | antagonistic training actor critic based on offline training reinforcement learning
pytorch加载数据
[Li Kou] the second set of the 280 Li Kou weekly match
Who is the winner of PTA
How to write compile scripts compatible with arm and x86 (Makefile, cmakelists.txt, shell script)
Era5 reanalysis data download strategy
【SLAM】lidar-camera外参标定(港大MarsLab)无需二维码标定板
MPLS experiment
暑期刷题-Day3
Polymorphic day02
resulttype和resultmap的区别和应用场景
These are not very good
Leetcode problem solving -- 99 Restore binary search tree
Leetcode problem solving -- 173 Binary search tree iterator
【Rust 笔记】18-宏
3857墨卡托坐标系转换为4326 (WGS84)经纬度坐标
Exness foreign exchange: the governor of the Bank of Canada said that the interest rate hike would be more moderate, and the United States and Canada fell slightly to maintain range volatility
如何做好功能测试