Skip to content

Commit

Permalink
feat(esbuild): add output_css flag to esbuild()
Browse files Browse the repository at this point in the history
When esbuild encounters an 'import "./foo.css"' file in normal (non-splitting)
mode, it will place the contents of that file in a .css file next to the
main output .js file.

This patch adds a flag output_css, which when set to True, will declare
the created .css file as another output, so it can be consumed by other
rules.
  • Loading branch information
dae committed Mar 23, 2021
1 parent 8d0218c commit d58e100
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 1 deletion.
12 changes: 11 additions & 1 deletion packages/esbuild/esbuild.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ def _esbuild_impl(ctx):
fail("output_map must be specified if sourcemap is not set to 'inline'")
outputs.append(js_out_map)

if ctx.outputs.output_css:
outputs.append(ctx.outputs.output_css)

if ctx.attr.format:
args.add_joined(["--format", ctx.attr.format], join_with = "=")

Expand Down Expand Up @@ -216,6 +219,10 @@ See https://esbuild.github.io/api/#splitting for more details
mandatory = False,
doc = "Name of the output source map when bundling",
),
"output_css": attr.output(
mandatory = False,
doc = "Name of the output css file when bundling",
),
"platform": attr.string(
default = "browser",
values = ["node", "browser", "neutral", ""],
Expand Down Expand Up @@ -270,14 +277,16 @@ For further information about esbuild, see https://esbuild.github.io/
""",
)

def esbuild_macro(name, output_dir = False, **kwargs):
def esbuild_macro(name, output_dir = False, output_css = False, **kwargs):
"""esbuild helper macro around the `esbuild_bundle` rule
For a full list of attributes, see the `esbuild_bundle` rule
Args:
name: The name used for this rule and output files
output_dir: If `True`, produce a code split bundle in an output directory
output_css: If `True`, declare name.css as an output, which is the
case when your code imports a css file.
**kwargs: All other args from `esbuild_bundle`
"""

Expand All @@ -296,5 +305,6 @@ def esbuild_macro(name, output_dir = False, **kwargs):
name = name,
output = "%s.js" % name,
output_map = output_map,
output_css = None if not output_css else "%s.css" % name,
**kwargs
)
47 changes: 47 additions & 0 deletions packages/esbuild/test/css/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
load("//packages/esbuild/test:tests.bzl", "esbuild")
load("//packages/jasmine:index.bzl", "jasmine_node_test")
load("//packages/typescript:index.bzl", "ts_library")
load("@build_bazel_rules_nodejs//:index.bzl", "copy_to_bin")

copy_to_bin(
name = "external_copied",
srcs = ["external.css"],
)

ts_library(
name = "main",
srcs = [
"main.ts",
],
deps = [
"@npm//@types/node",
],
)

esbuild(
name = "default",
entry_point = "main.ts",
deps = [
"external_copied",
":main",
],
)

esbuild(
name = "with_css",
entry_point = "main.ts",
output_css = True,
deps = [
"external_copied",
":main",
],
)

jasmine_node_test(
name = "bundle_test",
srcs = ["bundle_test.js"],
data = [
":default",
":with_css",
],
)
21 changes: 21 additions & 0 deletions packages/esbuild/test/css/bundle_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const { stat } = require("fs");
const path = require("path");

const helper = require(process.env.BAZEL_NODE_RUNFILES_HELPER);
const locationBase = "build_bazel_rules_nodejs/packages/esbuild/test/css/";

const cssExpected = helper.resolve(path.join(locationBase, "with_css.css"));

describe("esbuild css", () => {
it("no css by default", () => {
expect(() =>
helper.resolve(path.join(locationBase, "default.css"))
).toThrow();
});

it("css if requested", () => {
stat(cssExpected, (err, stats) => {
expect(err).toBeNull();
});
});
});
Empty file.
1 change: 1 addition & 0 deletions packages/esbuild/test/css/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "./external.css";

0 comments on commit d58e100

Please sign in to comment.