工程化4 分钟阅读

ESBuild

ESbuild 是一款基于 Golang 开发的打包工具,相比传统的 webpack、rollup 等主打性能优势,在构建速度上可以快 10~100 倍。

李李顺2022 · 05 · 30

ESbuild 是一款基于 Golang 开发的打包工具,相比传统的 webpack、rollup 等主打性能优势,在构建速度上可以快 10~100 倍。 图片

安装

bash
npm i esbuild

打包

esbuild 包含了两个打包方法,同步打包buildSync和异步打包build。 接受一个打包对象 option。

  • entryPoints:入口文件,Array/String
  • outfile:打包输出文件,Array/String
  • bundle:将依赖项内联到文件本身,并且是递归的,默认不会捆绑依赖。Boolean ::: tip 如果 bundle=true,会打包成一个 iife 立即执行函数 :::
  • loader:对文件类型使用对应的 loader 解释文件。 ::: tip 类型包含有 js、ts、jsx、json、css、text、binary、base64、data url、external file :::
  • plugin:插件,Array

示例

text
require('esbuild').buildSync({
  entryPoints: ['main.js'],
  outfile: 'out.js',
  bundle: true,
  loader: {'.js': 'jsx', '.json': 'js'},
  plugin:[]
})

plugin

  • 一个 esbuild 插件是一个包含 name 属性和 setup 函数的对象
  • 他们以数组的形式传递给构建 API 调用,setup 函数接收一个build参数,函数在每次BUILD API调用时都会运行一次。

命名空间 name

  • 每个模块都有一个关联的命名空间。默认情况下,esbuild 在 file 命名空间中云星,该命名空间对应文件系统上的文件类型
  • esbuild 也可以处理在文件系统上没有对应位置的“虚拟”模块
  • 插件可用于创建虚拟模块。虚拟模块通常使用命名空间而不是 file 将他们与文件系统模块区分开来,通常命名空间特定于创建他们的插件

setup 函数

  • setup 函数接受一个 build 参数,build 指的就是 esbuild,在 esbuild 打包过程中会调用每一个插件里 setup 中的回调函数,onResolve,onLoad

onResolve 回调

  • 使用添加的回调 onResolve 将在 esbuild 构建的每个模块中的每个导入路径上运行
  • 回调函数可以自定义 esbuild 如何解析路径。例如可以拦截导入路径并将他们重定向到其他地方,也可以将路径标记为外部:external:true
  • 回调函数中如果返回了内容,那么不会再走后续插件中的 onResolve 回调
js
// 最终生成的onResolve回调[p1.onResolve1, p1.onResolve2, p2.onResolve1, p2.onResolve2]
// plugin1
const plugin1 = {
  name: "p1",
  setup(build) {
    build.onResolve({ filter: /.js$/ }, () => {
      console.log("p1 resolve1");
      return {
        path: "C:/Users/xxx/xxx/xxx/xxx.js",
      };
    });
    build.onResolve({ filter: /.js$/ }, () => {
      console.log("p1 resolve2");
    });
  },
};
// plugin2
const plugin2 = {
  name: "p2",
  setup(build) {
    build.onResolve({ filter: /.js$/ }, () => {
      console.log("p2 resolve1");
    });
    build.onResolve({ filter: /.js$/ }, () => {
      console.log("p2 resolve2");
    });
  },
};

require("esbuild").build({
  entryPoints: ["title.js"],
  outfile: "out.js",
  // bundle: false,
  loader: { ".js": "jsx" },
  plugins: [plugin1, plugin2],
});
// 最终只会输出p1 resolved

Resolve 参数

当 esbuild 调用由注册的回调时 onResolve,将会为这些参数提供有关导入路径的信息

  • path 这是来自底层代码的没有解析路径
  • namespace 这是包含要解析的此导入模块的命名空间

onLoad 回调

  • onLoad 将为每个未标记为外部的唯一路径/命名空间对运行添加回调
  • 它的工作是返回模块内容并告诉 esbuild 如何解析
  • 回调可以在不提供内容的情况下返回。这样加载模块的责任传递到下一个注册的回调。对于给定的模块,onLoad 所有插件的所有回调都将按照他们注册的顺序运行,直到有人负责加载模块。如果没有回调返回模块内容,esbuild 件运行默认的模块加载逻辑
  • 如果 load 回调中返回了内容,后续的 load 回调也不会再执行
js
const plugin1 = {
  name: "p1",
  setup(build) {
    build.onResolve({ filter: /.js$/ }, () => {
      console.log("p1 resolve1");
    });
    build.onResolve({ filter: /.js$/ }, () => {
      console.log("p1 resolve2");
      return {
        path: "C:/Users/Administrator/Desktop/test/title2.js",
      };
    });
    build.onLoad({ filter: /.js$/ }, async ({ path }) => {
      const contents = await fs.readFile(path);
      console.log(contents.toString(), "p1 load1");
      return {
        contents,
      };
    });
    build.onLoad({ filter: /.js$/ }, (arg) => {
      console.log("p1 load2");
    });
  },
};
// 只会输出p1 load1

onLoad 选项

  • filter 每个回调都必须提供过滤器
  • namespace 这是可选的,如果提供,回调仅在提供的命名空间中模块内的路径上运行

load 结果

  • contents 将此设置为字符串以指定模块的内容。如果设置了此项,则不会针对此解析路径运行更多加载回调。如果未设置,esbuild 将继续运行后续注册的回调,最终如果都没有设置内容,解析的路径在 file 命名空间中,则将默认从文件系统加载内容
  • loader 告诉 esbuild 如何解析内容。例如,js 加载器将内容解释为 JavaScript,css 加载器将内容解释为 CSS。

过滤器

  • 每个回调都必须提供一个正则作为过滤器。当路径与其不匹配,esbuild 会跳过回调的调用
  • 命名空间也可以用于过滤。回调必须提供过正则,也可以选择命名空间进一步限制匹配路径

envPlugin

js
// main.js
import { PATH } from "env";
console.log(`PATH is ${PATH}`);

// index.js
let envPlugin = {
  name: "env",
  setup(build) {
    // 拦截名为env的导入路径,以便esbuild不会尝试将它们映射到文件系统位置
    // 用env-ns名称空间标记它们,以便为该插件保留它们
    build.onResolve({ filter: /^env$/ }, (args) => ({
      path: args.path,
      namespace: "env-ns",
    }));
    //加载带有env-ns名称空间标记的路径,它们的行为就像指向包含环境变量的JSON文件一样
    build.onLoad({ filter: /.*/, namespace: "env-ns" }, () => ({
      contents: JSON.stringify(process.env),
      loader: "json",
    }));
  },
};

require("esbuild")
  .build({
    entryPoints: ["entry.js"],
    bundle: true,
    outfile: "out.js",
    plugins: [envPlugin],
  })
  .catch(() => process.exit(1));

其他

具体详细文档参考 es-build

标签 · TAGS

评论 · COMMENTS

评论由 Giscus 承载 · 需要 GitHub 账号登录

站点不保存任何读者账号与凭证

未配置:在 lib/site.config.ts 填入 giscus 的 repo / repoId / category / categoryId