xinpianchang / fe-weekly

weekly for fe-team
10 stars 2 forks source link

esbuid 探究 #62

Open dailynodejs opened 3 years ago

dailynodejs commented 3 years ago

esbuild

An extremely fast JavaScript bundler and minifier.

image

随着产物越来越大,编译上线和 CI 的时间越来越长,其中 1/3 及更多时间都在压缩部分,OOM 的问题也来源于压缩,UglifyCache 和 autoExternal 是用来解决产物大了之后压缩慢从而可能导致 OOM 的问题

git 地址:https://github.com/evanw/esbuild

快的原因是啥?

好像给我安装了一个东西

image

"scripts": {
    "postinstall": "node install.js"
},

image

看看 install.js 的内容:

  1. 通过 os 获取当前系统的信息
const os = require("os")
// darwin x64 LE
// os.arch -- http://nodejs.cn/api/os.html#os_os_arch
// 返回为其编译 Node.js 二进制文件的操作系统的 CPU 架构。 可能的值有:'arm'、 'arm64'、 'ia32'、 'mips'、 'mipsel'、 'ppc'、 'ppc64'、 's390'、 's390x'、 'x32' 和 'x64'。

// os.endianness -- http://nodejs.cn/api/os.html#os_os_endianness
// 返回一个字符串,该字符串标识为其编译 Node.js 二进制文件的 CPU 的字节序。
const key = `${process.platform} ${os.arch()} ${os.endianness()}`;

2、按 platform 分为对应的 knownUnixlikePackages 和 installOnUnix

const knownWindowsPackages = {
  "win32 ia32 LE": "esbuild-windows-32",
  "win32 x64 LE": "esbuild-windows-64"
};
const knownUnixlikePackages = {
  "darwin x64 LE": "esbuild-darwin-64",
  "freebsd arm64 LE": "esbuild-freebsd-arm64",
  "freebsd x64 LE": "esbuild-freebsd-64",
  "linux arm64 LE": "esbuild-linux-arm64",
  "linux ia32 LE": "esbuild-linux-32",
  "linux ppc64 LE": "esbuild-linux-ppc64le",
  "linux x64 LE": "esbuild-linux-64"
};
if (key in knownWindowsPackages) {
  installOnWindows(knownWindowsPackages[key]);
} else if (key in knownUnixlikePackages) {
  installOnUnix(knownUnixlikePackages[key]);
} else {
  console.error(`Unsupported platform: ${key}`);
  process.exit(1);
}

3、看看 installOnUnix

function installOnUnix(name) {
  if (process.env.ESBUILD_BIN_PATH_FOR_TESTS) {
    fs.unlinkSync(binPath);
    fs.symlinkSync(process.env.ESBUILD_BIN_PATH_FOR_TESTS, binPath);
  } else {
    installBinaryFromPackage(name, "bin/esbuild", binPath).catch((e) => setImmediate(() => {
      throw e;
    }));
  }
}

4、installUsingNPM

通过 npm 来下载对应的包

function installUsingNPM(name, file) {
  const installDir = path.join(__dirname, ".install");
  fs.mkdirSync(installDir, {recursive: true});
  fs.writeFileSync(path.join(installDir, "package.json"), "{}");
  const env = __assign(__assign({}, process.env), {npm_config_global: void 0});
  child_process.execSync(`npm install --loglevel=error --prefer-offline --no-audit --progress=false ${name}@${version}`, {cwd: installDir, stdio: "pipe", env});
  const buffer = fs.readFileSync(path.join(installDir, "node_modules", name, file));
  removeRecursive(installDir);
  return buffer;
}

bundler 功能

minifier 功能

dailynodejs commented 3 years ago

esbuild-webpack-plugin

git 地址:https://github.com/sorrycc/esbuild-webpack-plugin

dailynodejs commented 3 years ago

ESM

A fast, global content delivery network for ES Modules. All modules in NPM are transformed to ESM by esbuild.

服务地址:http://esm.sh/

dailynodejs commented 3 years ago

基础概念 esm

ECMA Script Modules

MDN 地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Modules

dailynodejs commented 3 years ago

terser 提供速度

如果不为体积,为了速度可以设置:

terser file.js -m

API:

await minify(code, { compress: false, mangle: true });

d3.js size gzip size time (s)
original 451,131 108,733 -
terser@3.7.5 mangle=false, compress=false 316,600 85,245 0.82
terser@3.7.5 mangle=true, compress=false 220,216 72,730 1.45
terser@3.7.5 mangle=true, compress=true 212,046 70,954 5.87
babili@0.1.4 210,713 72,140 12.64
babel-minify@0.4.3 210,321 72,242 48.67
babel-minify@0.5.0-alpha.01eac1c3 210,421 72,238 14.17

文档地址:https://github.com/terser/terser#terser-fast-minify-mode

dailynodejs commented 3 years ago

配置

target

默认: esnext

esbuid app.js --target=es2020,chrome58

官网地址:https://esbuild.github.io/api/#target

dailynodejs commented 3 years ago

@umijs/plugin-esbuild

地址:https://github.com/umijs/plugins/blob/master/packages/plugin-esbuild/src/index.ts

dailynodejs commented 3 years ago

esbuild-loader

地址:https://github.com/privatenumber/esbuild-loader/issues

注意对 webpack 版本的依赖:https://github.com/privatenumber/esbuild-loader/blob/develop/package.json#L49

"webpack": "^4.40.0 || ^5.0.0"
dailynodejs commented 3 years ago

基于 go 项目的基本知识

go.mod

go 1.11 版本引入的官方包管理

源码地址:https://github.com/evanw/esbuild/blob/master/go.mod

module github.com/evanw/esbuild

go 1.13

require golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3
dailynodejs commented 3 years ago

参考:

https://zhuanlan.zhihu.com/p/357607473