Skip to content

Commit

Permalink
feat(esbuild): add support for toolchains (#2704)
Browse files Browse the repository at this point in the history
Add toolchain support for esbuild, removing the need for the tool attribute. Users can load the esbuild_repositories macro and call it within their WORKSPACE, this will by default define esbuild binaries for Windows, MacOS and Linux (all amd64).

esbuild package now uses toolchains, and the tools attribute has been removed. By default, toolchains for Windows, Mac (amd64, arm64) and Linux (amd64, arm64) are included.

See the docs for configure_esbuild_toolchain for defining custom toolchains

Add the following to the `WORKSPACE` file (changing `@npm` as required), see the docs for an alternate load method

```
load("@npm//@bazel/esbuild:esbuild_repositories.bzl", "esbuild_repositories")

esbuild_repositories()
```
  • Loading branch information
mattem authored Jun 2, 2021
1 parent c6ae95c commit ae011bf
Show file tree
Hide file tree
Showing 31 changed files with 351 additions and 259 deletions.
4 changes: 2 additions & 2 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ browser_repositories(
)

# Setup esbuild dependencies
load("//packages/esbuild:esbuild_repo.bzl", "esbuild_dependencies")
load("//packages/esbuild:esbuild_repositories.bzl", "esbuild_repositories")

esbuild_dependencies()
esbuild_repositories()

#
# Dependencies to run stardoc & generating documentation
Expand Down
111 changes: 67 additions & 44 deletions docs/esbuild.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,64 +22,40 @@ or using yarn
yarn add -D @bazel/esbuild
```

Add an `http_archive` fetching the esbuild binary for each platform that you need to support.
The esbuild binary is fetched from npm automatically and exposed via toolchains. Add the `esbuild_repositories` rule to the `WORKSPACE`:

```python
_ESBUILD_VERSION = "0.12.1" # reminder: update SHAs below when changing this value
http_archive(
name = "esbuild_darwin",
urls = [
"https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-%s.tgz" % _ESBUILD_VERSION,
],
strip_prefix = "package",
build_file_content = """exports_files(["bin/esbuild"])""",
sha256 = "efb34692bfa34db61139eb8e46cd6cf767a42048f41c8108267279aaf58a948f",
)
load("@npm//@bazel/esbuild:esbuild_repositories.bzl", "esbuild_repositories")

http_archive(
name = "esbuild_windows",
urls = [
"https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-%s.tgz" % _ESBUILD_VERSION,
],
strip_prefix = "package",
build_file_content = """exports_files(["esbuild.exe"])""",
sha256 = "10439647b11c7fd1d9647fd98d022fe2188b4877d2d0b4acbe857f4e764b17a9",
)
esbuild_repositories()
```

As esbuild is being fetched from `npm`, the load statement above can cause eager fetches of the `@npm` external repository.
To work around this, it's possible to fetch the `@bazel/esbuild` package via an `http_archive`

```python
http_archive(
name = "esbuild_linux",
name = "bazel_esbuild",
urls = [
"https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-%s.tgz" % _ESBUILD_VERSION,
"https://registry.npmjs.org/@bazel/esbuild/-/esbuild-4.0.0.tgz",
],
strip_prefix = "package",
build_file_content = """exports_files(["bin/esbuild"])""",
sha256 = "de8409b90ec3c018ffd899b49ed5fc462c61b8c702ea0f9da013e0e1cd71549a",
)
```

These can then be referenced on the `tool` attribute of the `esbuild` rule.
load("@bazel_esbuild//:esbuild_repositories.bzl", "esbuild_repositories")

```python
esbuild(
name = "bundle",
...
tool = select({
"@bazel_tools//src/conditions:darwin": "@esbuild_darwin//:bin/esbuild",
"@bazel_tools//src/conditions:windows": "@esbuild_windows//:esbuild.exe",
"@bazel_tools//src/conditions:linux_x86_64": "@esbuild_linux//:bin/esbuild",
}),
)
esbuild_repositories()
```

It might be useful to wrap this locally in a macro for better reuseability, see `packages/esbuild/test/tests.bzl` for an example.
## Overview

The `esbuild` rule can take a JS or TS dependency tree and bundle it to a single file, or split across multiple files, outputting a directory.

```python
load("@npm//@bazel/esbuild:index.bzl", "esbuild")
load("@npm//@bazel/typescript:index.bzl", "ts_library")
load("@npm//@bazel/typescript:index.bzl", "ts_project")

ts_library(
ts_project(
name = "lib",
srcs = ["a.ts"],
)
Expand All @@ -97,9 +73,9 @@ To create a code split bundle, set `splitting = True` on the `esbuild` rule.

```python
load("@npm//@bazel/esbuild:index.bzl", "esbuild")
load("@npm//@bazel/typescript:index.bzl", "ts_library")
load("@npm//@bazel/typescript:index.bzl", "ts_project")

ts_library(
ts_project(
name = "lib",
srcs = ["a.ts"],
deps = [
Expand All @@ -125,7 +101,7 @@ This will create an output directory containing all the code split chunks, along
<pre>
esbuild(<a href="#esbuild-name">name</a>, <a href="#esbuild-args">args</a>, <a href="#esbuild-define">define</a>, <a href="#esbuild-deps">deps</a>, <a href="#esbuild-entry_point">entry_point</a>, <a href="#esbuild-entry_points">entry_points</a>, <a href="#esbuild-external">external</a>, <a href="#esbuild-format">format</a>, <a href="#esbuild-launcher">launcher</a>,
<a href="#esbuild-link_workspace_root">link_workspace_root</a>, <a href="#esbuild-max_threads">max_threads</a>, <a href="#esbuild-minify">minify</a>, <a href="#esbuild-output">output</a>, <a href="#esbuild-output_css">output_css</a>, <a href="#esbuild-output_dir">output_dir</a>, <a href="#esbuild-output_map">output_map</a>,
<a href="#esbuild-platform">platform</a>, <a href="#esbuild-sourcemap">sourcemap</a>, <a href="#esbuild-sources_content">sources_content</a>, <a href="#esbuild-srcs">srcs</a>, <a href="#esbuild-target">target</a>, <a href="#esbuild-tool">tool</a>)
<a href="#esbuild-platform">platform</a>, <a href="#esbuild-sourcemap">sourcemap</a>, <a href="#esbuild-sources_content">sources_content</a>, <a href="#esbuild-srcs">srcs</a>, <a href="#esbuild-target">target</a>)
</pre>

Runs the esbuild bundler under Bazel
Expand Down Expand Up @@ -302,9 +278,56 @@ See https://esbuild.github.io/api/#target for more details

Defaults to `"es2015"`

<h4 id="esbuild-tool">tool</h4>

(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>, mandatory*): An executable for the esbuild binary
## configure_esbuild_toolchain

**USAGE**

<pre>
configure_esbuild_toolchain(<a href="#configure_esbuild_toolchain-name">name</a>, <a href="#configure_esbuild_toolchain-binary">binary</a>, <a href="#configure_esbuild_toolchain-exec_compatible_with">exec_compatible_with</a>)
</pre>

Defines a toolchain for esbuild given the binary path and platform constraints

**PARAMETERS**


<h4 id="configure_esbuild_toolchain-name">name</h4>

unique name for this toolchain, generally in the form "esbuild_platform_arch"



<h4 id="configure_esbuild_toolchain-binary">binary</h4>

label for the esbuild binary



<h4 id="configure_esbuild_toolchain-exec_compatible_with">exec_compatible_with</h4>

list of platform constraints




## esbuild_repositories

**USAGE**

<pre>
esbuild_repositories(<a href="#esbuild_repositories-name">name</a>)
</pre>

Helper for fetching and setting up the esbuild versions and toolchains

**PARAMETERS**


<h4 id="esbuild_repositories-name">name</h4>

currently unused

Defaults to `""`


36 changes: 4 additions & 32 deletions examples/esbuild/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -25,42 +25,14 @@ http_archive(
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/3.5.1/rules_nodejs-3.5.1.tar.gz"],
)

_ESBUILD_VERSION = "0.12.1"

http_archive(
name = "esbuild_darwin",
build_file_content = """exports_files(["bin/esbuild"])""",
sha256 = "efb34692bfa34db61139eb8e46cd6cf767a42048f41c8108267279aaf58a948f",
strip_prefix = "package",
urls = [
"https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-%s.tgz" % _ESBUILD_VERSION,
],
)

http_archive(
name = "esbuild_windows",
build_file_content = """exports_files(["esbuild.exe"])""",
sha256 = "10439647b11c7fd1d9647fd98d022fe2188b4877d2d0b4acbe857f4e764b17a9",
strip_prefix = "package",
urls = [
"https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-%s.tgz" % _ESBUILD_VERSION,
],
)

http_archive(
name = "esbuild_linux",
build_file_content = """exports_files(["bin/esbuild"])""",
sha256 = "de8409b90ec3c018ffd899b49ed5fc462c61b8c702ea0f9da013e0e1cd71549a",
strip_prefix = "package",
urls = [
"https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-%s.tgz" % _ESBUILD_VERSION,
],
)

load("@build_bazel_rules_nodejs//:index.bzl", "npm_install")

npm_install(
name = "npm",
package_json = "//:package.json",
package_lock_json = "//:package-lock.json",
)

load("@npm//@bazel/esbuild:esbuild_repositories.bzl", "esbuild_repositories")

esbuild_repositories()
5 changes: 0 additions & 5 deletions examples/esbuild/src/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ esbuild(
minify = True,
# setting node as the platform will default us to CJS
platform = "node",
tool = select({
"@bazel_tools//src/conditions:darwin": "@esbuild_darwin//:bin/esbuild",
"@bazel_tools//src/conditions:linux_x86_64": "@esbuild_linux//:bin/esbuild",
"@bazel_tools//src/conditions:windows": "@esbuild_windows//:esbuild.exe",
}),
deps = [
":lib",
],
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
"bazel:update-deleted-packages": "sed -i.bak \"/--deleted_packages/s#=.*#=$(find {examples,e2e}/*/* \\( -name BUILD -or -name BUILD.bazel \\) | xargs -n 1 dirname | paste -sd, -)#\" .bazelrc && rm .bazelrc.bak",
"update-codeowners": "./scripts/update_codeowners.sh",
"update-nodejs-versions": "node ./scripts/update-nodejs-versions.js > internal/node/node_versions.bzl",
"update-esbuild-versions": "node ./scripts/update-esbuild-versions.js > packages/esbuild/esbuild_repo.bzl",
"update-esbuild-versions": "node ./scripts/update-esbuild-versions.js",
"format": "git-clang-format",
"format-all": "clang-format --glob='{internal/**/,examples/**/}*.{js,ts}' -i",
"version": "conventional-changelog -p angular -i CHANGELOG.md -s && node ./scripts/on-version.js && bazel build //:release && node ./scripts/on-release.js && git stage version.bzl docs/install.md packages/create/index.js README.md CHANGELOG.md e2e/*/WORKSPACE examples/*/WORKSPACE",
Expand Down
25 changes: 18 additions & 7 deletions packages/esbuild/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@ codeowners(

bzl_library(
name = "bzl",
srcs = glob(["**/*.bzl"]),
srcs = glob(["**/*.bzl"]) + [
"@bazel_tools//tools:bzl_srcs",
],
deps = [
"//packages/esbuild/toolchain:bzl",
"@bazel_skylib//lib:paths",
"@build_bazel_rules_nodejs//:bzl",
"@build_bazel_rules_nodejs//internal/common:bzl",
Expand All @@ -51,20 +54,28 @@ copy_file(
out = ":npm_version_check.js",
)

pkg_npm(
name = "npm_package",
filegroup(
name = "srcs",
srcs = [
"esbuild.bzl",
"esbuild_packages.bzl",
"esbuild_repositories.bzl",
"helpers.bzl",
"index.bzl",
"launcher.js",
"package.json",
],
build_file_content = """exports_files(["launcher.js"])
""",
)

pkg_npm(
name = "npm_package",
srcs = [
":srcs",
"//packages/esbuild/toolchain:srcs",
],
build_file_content = """exports_files(["launcher.js"])""",
substitutions = dict({
"@build_bazel_rules_nodejs//packages/esbuild:esbuild.bzl": "//@bazel/esbuild:esbuild.bzl",
"@build_bazel_rules_nodejs//packages/esbuild:launcher.js": "//@bazel/esbuild:launcher.js",
"@build_bazel_rules_nodejs//packages/esbuild": "//@bazel/esbuild",
}),
deps = [
":README.md",
Expand Down
15 changes: 6 additions & 9 deletions packages/esbuild/esbuild.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ esbuild rule
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
load("@build_bazel_rules_nodejs//:providers.bzl", "ExternalNpmPackageInfo", "JSEcmaScriptModuleInfo", "JSModuleInfo", "node_modules_aspect", "run_node")
load("@build_bazel_rules_nodejs//internal/linker:link_node_modules.bzl", "MODULE_MAPPINGS_ASPECT_RESULTS_NAME", "module_mappings_aspect")
load("@build_bazel_rules_nodejs//packages/esbuild/toolchain:toolchain.bzl", "TOOLCHAIN")
load(":helpers.bzl", "desugar_entry_point_names", "filter_files", "generate_path_mapping", "resolve_entry_point", "write_jsconfig_file")

def _esbuild_impl(ctx):
Expand Down Expand Up @@ -135,7 +136,7 @@ def _esbuild_impl(ctx):
execution_requirements = {"no-remote-exec": "1"}

launcher_args = ctx.actions.args()
launcher_args.add("--esbuild=%s" % ctx.executable.tool.path)
launcher_args.add("--esbuild=%s" % ctx.toolchains[TOOLCHAIN].binary.path)

run_node(
ctx = ctx,
Expand All @@ -148,7 +149,7 @@ def _esbuild_impl(ctx):
env = env,
executable = "launcher",
link_workspace_root = ctx.attr.link_workspace_root,
tools = [ctx.executable.tool],
tools = [ctx.toolchains[TOOLCHAIN].binary],
)

outputs_depset = depset(outputs)
Expand Down Expand Up @@ -307,15 +308,11 @@ edge16, node10, esnext). Default es2015.
See https://esbuild.github.io/api/#target for more details
""",
),
"tool": attr.label(
allow_single_file = True,
mandatory = True,
executable = True,
cfg = "exec",
doc = "An executable for the esbuild binary",
),
},
implementation = _esbuild_impl,
toolchains = [
str(TOOLCHAIN),
],
doc = """Runs the esbuild bundler under Bazel
For further information about esbuild, see https://esbuild.github.io/
Expand Down
Loading

0 comments on commit ae011bf

Please sign in to comment.